Updated Progressive Bot System
This commit is contained in:
		
							parent
							
								
									fb99760b29
								
							
						
					
					
						commit
						dded8a81d6
					
				|  | @ -259,7 +259,7 @@ Centering On Player Zoom Level = 0.15 | |||
| # Setting type: Single | ||||
| # Default value: 0 | ||||
| # Acceptable value range: From 0 to 15 | ||||
| Main map zoom = 2.593422 | ||||
| Main map zoom = 3.833475 | ||||
| 
 | ||||
| ## The keyboard shortcut to peek at the map | ||||
| # Setting type: KeyboardShortcut | ||||
|  |  | |||
|  | @ -1,6 +1,6 @@ | |||
| { | ||||
|     "name": "Acids Progressive Bot System", | ||||
|     "version": "1.4.1", | ||||
|     "version": "1.4.2", | ||||
|     "sptVersion": "~3.10", | ||||
|     "loadBefore": [], | ||||
|     "loadAfter": [ | ||||
|  |  | |||
|  | @ -61,10 +61,8 @@ export class APBSBotGeneratorHelper extends BotGeneratorHelper | |||
|             return maxResource; | ||||
|         } | ||||
| 
 | ||||
|         const newResourceValue = this.randomUtil.getInt( | ||||
|             this.randomUtil.getPercentOfValue(randomizationValues.resourcePercent, maxResource, 0), | ||||
|         return this.randomUtil.getInt(this.randomUtil.getPercentOfValue(randomizationValues.resourcePercent, maxResource, 2), | ||||
|             maxResource | ||||
|         ) | ||||
|         return newResourceValue ? newResourceValue : 1; | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,28 @@ | |||
| [General] | ||||
| gameName=spt | ||||
| modid=0 | ||||
| version=d2025.1.14.0 | ||||
| newestVersion= | ||||
| category="1," | ||||
| nexusFileStatus=1 | ||||
| installationFile=acidphantasm-progressivebotsystem.zip | ||||
| repository= | ||||
| ignoredVersion= | ||||
| comments= | ||||
| notes= | ||||
| nexusDescription= | ||||
| url= | ||||
| hasCustomURL=false | ||||
| lastNexusQuery= | ||||
| lastNexusUpdate= | ||||
| nexusLastModified=2024-12-16T07:04:24Z | ||||
| nexusCategory=0 | ||||
| converted=false | ||||
| validated=false | ||||
| color=@Variant(\0\0\0\x43\0\xff\xff\0\0\0\0\0\0\0\0) | ||||
| tracked=0 | ||||
| 
 | ||||
| [installedFiles] | ||||
| 1\modid=0 | ||||
| 1\fileid=0 | ||||
| size=1 | ||||
|  | @ -0,0 +1,21 @@ | |||
| MIT License | ||||
| 
 | ||||
| Copyright (c) 2024 acidphantasm | ||||
| 
 | ||||
| Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| of this software and associated documentation files (the "Software"), to deal | ||||
| in the Software without restriction, including without limitation the rights | ||||
| to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
| copies of the Software, and to permit persons to whom the Software is | ||||
| furnished to do so, subject to the following conditions: | ||||
| 
 | ||||
| The above copyright notice and this permission notice shall be included in all | ||||
| copies or substantial portions of the Software. | ||||
| 
 | ||||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
| AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
| OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||
| SOFTWARE. | ||||
|  | @ -0,0 +1,47 @@ | |||
| # Welcome to PBS (Progressive Bot System) | ||||
| 
 | ||||
| The goal of this mod is to provide a system that allows all bots to progress with the player.  | ||||
| 
 | ||||
| In vanilla, scavs are a minor annoyance once you reach level 30+. This aims to change that, they may not always have the best ammo but they won't always be rocking crappy shotguns or low level weapons. | ||||
| 
 | ||||
| ## General Notes | ||||
| 
 | ||||
| This mod has only been tested with SAIN, SWAG+Donuts, QuestingBots, and LootingBots. | ||||
| 
 | ||||
| This mod may have missing mods or templates for weapons. If you see errors or warning - REPORT THEM. | ||||
| 
 | ||||
| This mod may have issues that prevent the game from working - if this happens, REMOVE THE MOD and REPORT THEM. | ||||
| 
 | ||||
| Currently all bots that are due to spawn or have spawned are logged inside the \user\mods\acidphantasm-progressivebotsystem\logs\ folder. These logs are wiped when you restart the server. These may be needed to provide support, and are a nice thing to review if you happen to want to know everything that has or will spawn. | ||||
| 
 | ||||
| ## Put this mod last in your load order. If you have issues and it isn't last, then move it last. | ||||
| 
 | ||||
| ### Current Features | ||||
| - All AI will level with you. | ||||
| - All AI have a tiering system. | ||||
| - All AI will use modded weapons that you have installed. | ||||
| - USEC spawn with weapons that you would expect from non-Russian forces. | ||||
| - BEAR spawn with weapons that you would expect from Russian forces. | ||||
| - Scavs pull a weapon from the Tier they have spawned from (any weapon available in that tier from USEC or BEAR can be chosen.) | ||||
|   - Scavs pull from ammo pools that do not contains meta ammo. I felt this was too easy a source of ammunition. This is subject to change. | ||||
| - Bosses pull weapons from their vanilla pools until a later version. | ||||
|   - Bosses & guards pull ammo from a Tier4 pool. | ||||
|   - Boss guards pull a Tier4 weapon from the combined pools of USEC & BEAR. | ||||
| 
 | ||||
| ### Current Tiers | ||||
| - Tier 1 = Lv1-10 | ||||
|   - Level Variance +/- 5 | ||||
| - Tier 2 = Lv11-20 | ||||
|   - Level Variance +/- 7 | ||||
| - Tier 3 = Lv21-30 | ||||
|   - Level Variance +/- 10 | ||||
| - Tier 4 = Lv31-40 | ||||
|   - Level Variance +/- 15 | ||||
| - Tier 5 = Lv41-50 | ||||
|   - Level Variance +/- 15 | ||||
| - Tier 6 = Lv51-60 | ||||
|   - Level Variance +/- 20 | ||||
| - Tier 7 = Lv61-78 | ||||
|   - Level Variance +/- 30 | ||||
| 
 | ||||
| ## Put this mod last in your load order. If you have issues and it isn't last, then move it last. | ||||
|  | @ -0,0 +1,264 @@ | |||
| { | ||||
| // Enable/Disable using a preset | ||||
| // Presets are to be built and shared among APBS users. If enabled, ensure that you set the "presetName" to the name of the folder of your preset | ||||
|         "usePreset": false, | ||||
|         "presetName": "example", | ||||
| 
 | ||||
| // If you enable either of these settings, support will not be granted. | ||||
| // enableModdedWeapons - Any mods adding weapons loaded before APBS will have their weapons & attachments imported. | ||||
| // enableModdedEquipment - Any mods adding equipment loaded before APBS will be imported with their attachments (if any). | ||||
| // enableModdedClothing - Any mods adding clothing loaded before APBS will be imported. | ||||
| // initialTierAppearance - Whatever number (1-7) you put here, will be the first tier that imported mod items will be added to. | ||||
| // pmcWeaponWeights - Weight of modded weapons being added to PMCs | ||||
| // scavWeaponWeights - Weight of modded weapons being added to Scavs | ||||
| // followerWeaponWeights - Weight of modded weapons being added to boss followers (not Goons) | ||||
| // enableSafeGuard - Enables preventing weapon importing from bastardizing vanilla weapons. If you disable this, you will get cursed vanilla weapons. | ||||
| // Higher weights = more often. Lower weights = less often. If you add a LOT of mod weapons, I suggest using a lower value.  | ||||
| // REVIEW THE APBS LOGS TO TUNE YOUR CONFIG. (\user\mods\acidphantasm-progressivebotsystem\logs) | ||||
|         "enableModdedWeapons": true, | ||||
|         "enableModdedEquipment": true, | ||||
|         "enableModdedClothing": true, | ||||
|         "initalTierAppearance": 3, | ||||
|         "pmcWeaponWeights": 10, | ||||
|         "scavWeaponWeights": 1, | ||||
|         "followerWeaponWeights": 7, | ||||
|         "enableSafeGuard": true, | ||||
| 
 | ||||
| // Enable/Disable PMC Seasonal Clothing | ||||
| // If true, PMCs will wear seasonal appropriate clothing to blend into the environment better. If disabled, clothing will be tiered by level instead. | ||||
| // If true, modded clothing will not import, regardless of setting, to protect the appearance of appropriate clothing. | ||||
|         "seasonalPmcAppearance": true, | ||||
| 
 | ||||
| // Enable/Disable Realism Gas Mask Compatibility | ||||
| // APBS automatically detects Realism and adds gas masks to bots due to Radiation Zones. If you dont want this to happen, set to true. | ||||
|         "disableRealismGasMasks": false, | ||||
| 
 | ||||
| // Looking for a challenge, or maybe just want to chill and wreck some bots? | ||||
| // Enable "onlyChads" to force all bots to be Tier7, or enable "tarkovAndChill" to force all bots to be Tier1 | ||||
| // Enabling both will enable chaos mode, bots will pull gear and weapons from completely random Tiers during generation. It's chaos. | ||||
| // Alternatively, enable "blickyMode" to give everyone a blicky. It's actually the real chill mode. | ||||
| // Side note on "blickyMode" - it breaks some boss guards. Don't report it. It's a joke mode. It also won't do anything if either of the other two "modes" are enabled. | ||||
|         "onlyChads": false, | ||||
|         "tarkovAndChill": false, | ||||
|         "blickyMode": false, | ||||
| 
 | ||||
| // Enable/Disable specific bot generation | ||||
| // If set to true, it will disable APBS generation for that bot type, if false - will use APBS generation. | ||||
|         "disableScavTierGeneration": false, | ||||
|         "disablePMCTierGeneration": false, | ||||
|         "disableBossTierGeneration": false, | ||||
|         "disableBossFollowerTierGeneration": false, | ||||
|         "disableRaiderRogueTierGeneration": false, | ||||
| 
 | ||||
| // Enable/Disable bots having the chance to roll ammo choice for rig magazines after selecting ammo choice for weapon | ||||
| // "enableBotsToRollAmmoAgain" If set to true, AI PMCs will roll their ammo choice for additional magazines based on the chance configured - if false all magazines will always have the same ammo selected for the weapon. | ||||
| // "chanceToRollAmmoAgain" chance out of 100 that bot will roll ammo again for each subsequent additional magazine they spawn with in their rig. | ||||
|         "enableBotsToRollAmmoAgain": true, | ||||
|         "chanceToRollAmmoAgain": 50, | ||||
| 
 | ||||
| // Enable/Disable custom game version weights for AI PMCs | ||||
| // If set to true, AI PMCs will roll their weights from the values below - if false will use SPT defaults. | ||||
| // The values listed below ARE the SPT defaults (for reference) | ||||
|         "gameVersionWeight": false, | ||||
|         "standard": 2, | ||||
|         "left_behind": 1, | ||||
|         "prepare_for_escape": 1, | ||||
|         "edge_of_darkness": 4, | ||||
|         "unheard_edition": 2, | ||||
| 
 | ||||
| // Enable/Disable PMC ammo tier sliding | ||||
| // If set to true, it will enabling a sliding system for PMC ammo pools. If you enable this, the below numbers are the recommended amounts. Tweak as you wish. | ||||
| // Example: "pmcAmmoTierSlideAmount: 1 will allow a Tier5 PMC to "slide" down and pick from a Tier4 ammo pool, if it passes the roll for "slideChance". | ||||
|         "enablePMCAmmoTierSliding": false, | ||||
|         "slideAmount": 1, | ||||
|         "slideChance": 33, | ||||
| 
 | ||||
| // Enable/Disable using individual weapon type attachment chances. | ||||
| // If set to true, will allow generation to use individual category based weapon attachment chances, if false - all weapons use the same attachment chance pool. | ||||
| // For Preset Makers:  | ||||
| // If the below setting is false, "weaponMods" in the chances.json is the attachment chance rolls used. | ||||
| // If the below setting is true, then you must also fill out each weapons category of chances. | ||||
|         "enablePerWeaponTypeAttachmentChances": true, | ||||
| 
 | ||||
| // Force weapon stocks | ||||
| // If set to true, will enforce all AI weapons to have stocks, if false - will use APBS values | ||||
| // "stockButtpadChance" will allow dynamic configuration of any butt pads spawning on a stock that can take them. | ||||
|         "forceStock": false, | ||||
|         "stockButtpadChance": 50, | ||||
| 
 | ||||
| // Force weapon dust covers | ||||
| // If set to true, will enforce all AI weapons to have dust covers, if false - will use APBS values | ||||
|         "forceDustCover": false, | ||||
|          | ||||
| // Force weapon mod_scope slot | ||||
| // If set to true, will enforce all AI weapons to have a mod in the mod_scope slot  | ||||
| // This slot is *MOSTLY* optics but it's sometimes a laser/flashlight depending on gun, if false - will use APBS values | ||||
|         "forceScopeSlot": false, | ||||
| 
 | ||||
| // Force weapon muzzles | ||||
| // "forceMuzzle" If set to true, will enforce all AI PMC weapons to have muzzles based on the chance configured, if false - will use APBS values | ||||
| // "muzzleChance" chance of muzzle being selected (overrides preset and database values) for each tier [ T1, T2, T3, T4, T5, T6, T7 ] | ||||
| // "forceChildrenMuzzle" If set to true, enforces muzzle children to also spawn (so if it rolls to pick a threaded adapter, the child silencer will be forced to spawn), if false - will roll those slots independently  | ||||
| // "forceChildrenMuzzle" works regardless of you setting forceMuzzle or not - if you just want to see more children adapters spawn, just set this true | ||||
|         "forceMuzzle": false, | ||||
|         "muzzleChance": [ 10, 25, 40, 55, 65, 75, 75 ], | ||||
|         "forceChildrenMuzzle": false, | ||||
| 
 | ||||
| // Force weapon mod count limits | ||||
| // If set to true, will enforce all AI weapons to be limited to the scopeLimit & tacticalLimit, if disabled the generation may go wild | ||||
|         "forceWeaponModLimits": true, | ||||
|         "scopeLimit": 2, | ||||
|         "tacticalLimit": 1, | ||||
| 
 | ||||
| // Enable/disable AI having T-7 thermal goggles | ||||
| // If set to true, will allow AI to spawn with T-7 thermal goggles, if false they will not. | ||||
| // "startTier" controls what tier the goggles will be available in. "5c110624d174af029e69734c" | ||||
|         "enableT7Thermals": false, | ||||
|         "startTier": 6, | ||||
| 
 | ||||
| // Enable/Disable PMC/scav Loot | ||||
| // If set to true, will allow PMCs/scavs to have backpack/rig/pocket loot. If disabled, they will not. | ||||
| // Add ItemIDs to the blacklist array to prevent them from spawning | ||||
| // Blacklist example "pmcLootBlacklistItems": ["6711039f9e648049e50b3307", "5c0e531286f7747fa54205c2"] | ||||
|         "pmcLoot": false, | ||||
|         "pmcLootBlacklistItems": [ "6711039f9e648049e50b3307" ], | ||||
|         "scavLoot": true, | ||||
| 
 | ||||
| // Enable/Disabe Scav specific tiering options | ||||
| // "enableScavAttachmentTiering" - If set to true, will allow scavs to get additional weapon/equipment attachments as they tier up. If disabled, they will always have tier 1 attachments. | ||||
| // "enableScavEqualChanceEquipmentTiering" - If set to true, will allow scavs to have equal chances for any equipment in their pools. If disabled, they will use APBS defaults (low chances for good gear). | ||||
|         "enableScavAttachmentTiering": false, | ||||
|         "enableScavEqualEquipmentTiering": false, | ||||
| 
 | ||||
| // Enable/Disable adding keys to Scav Backpack loot | ||||
| // Pick -ONE- option below and enable it if you would like to expand the backpack key pool for scavs. | ||||
| // All keys include every key/keycard. | ||||
| // Mechanical keys are keys that aren't keycards. <- Recommended, if you are going to enable something | ||||
| // Keycards include ALL keycards.  | ||||
|         "addAllKeysToScavs": false, | ||||
|         "addOnlyMechanicalKeysToScavs": false, | ||||
|         "addOnlyKeyCardsToScavs": false, | ||||
| 
 | ||||
| // Configure Weapon Durability per AI Bot Type | ||||
| // Numbers are as follows: [ minDurability, maxDurability, minDelta, maxDelta ] | ||||
| // Example: [ 50, 90, 0, 25 ] | ||||
| // Ex ctd: Minimum possible "max" durability would be 50%, the highest possible "max" durability is 90% | ||||
| // Ex ctd: Whatever value is picked between 50% & 90% will be the "max" durability of the weapon ("max" is the limit you can repair the weapon to) | ||||
| // Ex ctd: After the max durability is selected, it will roll for the actual current durability which will be between 0-25% lower than the max. | ||||
| // Ex ctd: Weapons are safeguarded to never fall below 40%. | ||||
|         "scavWeaponDurability": [ 50, 90, 0, 20 ], | ||||
|         "pmcWeaponDurability": [ 95, 100, 0, 5 ], | ||||
|         "bossWeaponDurability": [ 80, 100, 0, 20 ], | ||||
|         "guardWeaponDurability": [ 80, 100, 0, 20 ], | ||||
|         "raiderWeaponDurability": [ 80, 100, 0, 20 ], | ||||
| 
 | ||||
| // Enable/Disable custom plate chances | ||||
| // If you REALLY don't like APBS plate chances then you can adjust it here. | ||||
| // If set to true, will change all AI plate chances to the values you set below, if false - will use APBS values  | ||||
| // If set to true, Main Plates = front/back and Side Plates = left/right, if false - APBS uses individual plate chances for front/back and sides. | ||||
| // Values are configured for each tier, example: [ Tier1, Tier2, Tier3, Tier4, Tier5, Tier6, Tier7 ] | ||||
|         "enableCustomPlateChances": false, | ||||
|         "scavMainPlateChance":  [ 25, 25, 25, 25, 25, 25, 25 ], | ||||
|         "scavSidePlateChance":  [ 25, 25, 25, 25, 25, 25, 25 ], | ||||
|         "pmcMainPlateChance":  [ 65, 75, 90, 90, 95, 100, 100 ], | ||||
|         "pmcSidePlateChance":  [ 15, 25, 50, 75, 90, 95, 100 ], | ||||
|         "bossMainPlateChance":  [ 75, 75, 75, 75, 75, 75, 75 ], | ||||
|         "bossSidePlateChance":  [ 50, 50, 50, 50, 50, 50, 50 ], | ||||
|         "guardMainPlateChance":  [ 75, 75, 75, 75, 75, 75, 75 ], | ||||
|         "guardSidePlateChance":  [ 75, 75, 75, 75, 75, 75, 75 ], | ||||
|         "raiderMainPlateChance":  [ 75, 75, 75, 75, 75, 75, 75 ], | ||||
|         "raiderSidePlateChance":  [ 75, 75, 75, 75, 75, 75, 75 ], | ||||
| 
 | ||||
| // Enable/Disable randomization of medical and food resource values | ||||
| // If set to true, all scavs and PMCs will have randomized resource values, based on the chances you set below, for medical and food items.  | ||||
| // If disabled the items will always be full resource values.  | ||||
| // Explanation: "pmcMedRates": [ Chance for full resource value available, Minimum percent of item randomized between min and max resource ] | ||||
| // Example.. "pmcMedRates": [ 65, 20 ] --- AFAK on a PMC has a 65% chance to be 400/400 and 35% chance to be between 0% and 80% used (it would spawn somewhere between 80/400 to 400/400). | ||||
|         "enableConsumableResourceRandomization": true, | ||||
|         "scavFoodRates": [ 10, 25 ], | ||||
|         "scavMedRates": [ 10, 25 ], | ||||
|         "pmcFoodRates": [ 10, 25 ], | ||||
|         "pmcMedRates": [ 10, 25 ], | ||||
| 
 | ||||
| // Blacklist specific ammo types from all AI -- USE "https://db.sp-tarkov.com/" to get the item _id | ||||
| // Configure per tier blacklists | ||||
| // Example.. this will blacklist 9x19 RIP and 5.45x39mm PP from all bots in Tier1 | ||||
| // tier1AmmoBlacklist: [ "5c0d56a986f774449d5de529", "56dff2ced2720bb4668b4567" ] | ||||
|         "tier1AmmoBlacklist": [], | ||||
|         "tier2AmmoBlacklist": [], | ||||
|         "tier3AmmoBlacklist": [], | ||||
|         "tier4AmmoBlacklist": [], | ||||
|         "tier5AmmoBlacklist": [], | ||||
|         "tier6AmmoBlacklist": [], | ||||
|         "tier7AmmoBlacklist": [], | ||||
| 
 | ||||
| // Blacklist specific equipment from all AI -- USE "https://db.sp-tarkov.com/" to get the item _id | ||||
| // Configure per tier blacklists | ||||
| // Example.. this will blacklist BlackRock chest rig and GSSh-01 headset from all bots in Tier1 | ||||
| // tier1EquipmentBlacklist: [ "5648a69d4bdc2ded0b8b457b", "5b432b965acfc47a8774094e" ] | ||||
|         "tier1EquipmentBlacklist": [], | ||||
|         "tier2EquipmentBlacklist": [], | ||||
|         "tier3EquipmentBlacklist": [], | ||||
|         "tier4EquipmentBlacklist": [], | ||||
|         "tier5EquipmentBlacklist": [], | ||||
|         "tier6EquipmentBlacklist": [], | ||||
|         "tier7EquipmentBlacklist": [], | ||||
| 
 | ||||
| // Blacklist specific weapons from all AI -- USE "https://db.sp-tarkov.com/" to get the item _id | ||||
| // Configure per tier blacklists | ||||
| // Example.. this will blacklist PKP and PKM from all bots in Tier1 | ||||
| // tier1EquipmentBlacklist: [ "64ca3d3954fc657e230529cc", "64637076203536ad5600c990" ] | ||||
|         "tier1WeaponBlacklist": [], | ||||
|         "tier2WeaponBlacklist": [], | ||||
|         "tier3WeaponBlacklist": [], | ||||
|         "tier4WeaponBlacklist": [], | ||||
|         "tier5WeaponBlacklist": [], | ||||
|         "tier6WeaponBlacklist": [], | ||||
|         "tier7WeaponBlacklist": [], | ||||
| 
 | ||||
| // Blacklist specific attachments from all AI -- USE "https://db.sp-tarkov.com/" to get the item _id | ||||
| // Configure per tier blacklists - very useful setting for those that play with modded weapon/equipment importing | ||||
| // Example.. this will blacklist "AK 7.62x39 aluminium 10-round magazine" and "Ops-Core SLAAP Armor Helmet Plate" from all bots in Tier1 | ||||
| // tier1EquipmentBlacklist: [ "5b1fd4e35acfc40018633c39", "5c0e66e2d174af02a96252f4" ] | ||||
|         "tier1AttachmentBlacklist": [], | ||||
|         "tier2AttachmentBlacklist": [], | ||||
|         "tier3AttachmentBlacklist": [], | ||||
|         "tier4AttachmentBlacklist": [], | ||||
|         "tier5AttachmentBlacklist": [], | ||||
|         "tier6AttachmentBlacklist": [], | ||||
|         "tier7AttachmentBlacklist": [], | ||||
| 
 | ||||
| // LevelDelta's are the lowest and highest levels that AI can spawn relative to the player's level.  | ||||
| // Examples:  | ||||
| // "tier1LevelDelta": [ 5, 5 ] --- While you are Tier1 (lv1-10), all AI will be leveled -5 to +5 of your level. | ||||
| // "tier2LevelDelta": [ 10, 25 ] --- While you are Tier2 (lv11-20), all AI will be leveled -10 to +25 of your level. | ||||
| // "enableCustomLevelDeltas" if true will use the values you set below, otherwise they will use APBS values | ||||
| // THE BELOW VALUES BY DEFAULT ARE APBS DEFAULTS | ||||
| // IF YOU WANT EVERY TIER AT EVERY LEVEL, SET ALL OF THESE TO: [ 79, 79 ] | ||||
|         "enableCustomLevelDeltas": true, | ||||
|         "tier1LevelDelta": [ 10, 5 ], // 1-10 | ||||
|         "tier2LevelDelta": [ 20, 5 ], // 11-20 | ||||
|         "tier3LevelDelta": [ 25, 7 ], // 21-30 | ||||
|         "tier4LevelDelta": [ 35, 10 ], // 31-40 | ||||
|         "tier5LevelDelta": [ 40, 15 ], // 41-50 | ||||
|         "tier6LevelDelta": [ 50, 20 ], // 51-60 | ||||
|         "tier7LevelDelta": [ 55, 20 ], // 61-79 | ||||
| 
 | ||||
| // LevelDelta's are the lowest and highest levels that AI can spawn relative to the player's level.  | ||||
| // Examples:  | ||||
| // "tier2ScavLevelDelta": [ 10, -10 ] --- While you are Tier2 (lv11-20), scavs will be leveled -10 to -10 of your level. (always 10 levels behind you) | ||||
| // "tier3ScavLevelDelta": [ 30, -10 ] --- While you are Tier3 (lv21-30), scavs will be leveled -30 to -10 of your level. (always 10 to 30 levels behind you) | ||||
| // "enableScavCustomLevelDeltas" if true will use the values you set below, otherwise they will use APBS values | ||||
| // Default values below will always spawn scavs that are at least 1 tier below you unless you are Tier1. | ||||
|         "enableScavCustomLevelDeltas": false, | ||||
|         "tier1ScavLevelDelta": [ 10, 0 ], // 1-10 | ||||
|         "tier2ScavLevelDelta": [ 10, -10 ], // 11-20 | ||||
|         "tier3ScavLevelDelta": [ 15, -10 ], // 21-30 | ||||
|         "tier4ScavLevelDelta": [ 20, -10 ], // 31-40 | ||||
|         "tier5ScavLevelDelta": [ 30, -10 ], // 41-50 | ||||
|         "tier6ScavLevelDelta": [ 40, -10 ], // 51-60 | ||||
|         "tier7ScavLevelDelta": [ 50, -10 ], // 61-79 | ||||
| 
 | ||||
| // Enable/disable debug logging | ||||
|         "enableDebugLog": true | ||||
| } | ||||
|  | @ -0,0 +1,32 @@ | |||
| { | ||||
|     "name": "Acids Progressive Bot System", | ||||
|     "version": "1.4.1", | ||||
|     "sptVersion": "~3.10", | ||||
|     "loadBefore": [], | ||||
|     "loadAfter": [ | ||||
|         "DanW-SPTQuestingBots" | ||||
|     ], | ||||
|     "incompatibilities": [], | ||||
|     "isBundleMod": false, | ||||
|     "main": "src/mod.js", | ||||
|     "scripts": { | ||||
|         "setup": "npm i", | ||||
|         "build": "node ./build.mjs", | ||||
|         "buildinfo": "node ./build.mjs --verbose" | ||||
|     }, | ||||
|     "devDependencies": { | ||||
|         "@types/node": "20.11", | ||||
|         "@typescript-eslint/eslint-plugin": "7.2", | ||||
|         "@typescript-eslint/parser": "7.2", | ||||
|         "archiver": "^6.0", | ||||
|         "eslint": "8.57", | ||||
|         "fs-extra": "11.2", | ||||
|         "ignore": "^5.2", | ||||
|         "tsyringe": "4.8.0", | ||||
|         "typescript": "5.4", | ||||
|         "winston": "3.12" | ||||
|     }, | ||||
|     "author": "acidphantasm", | ||||
|     "contributors": [], | ||||
|     "license": "MIT" | ||||
| } | ||||
|  | @ -0,0 +1,479 @@ | |||
| { | ||||
|     "scavAmmo": { | ||||
|         "Caliber1143x23ACP": { | ||||
|             "5efb0fc6aeb21837e749c801": 1, | ||||
|             "5efb0d4f4bc50b58e81710f3": 3 | ||||
|         }, | ||||
|         "Caliber127x55": { | ||||
|             "5cadf6e5ae921500113bb973": 1 | ||||
|         }, | ||||
|         "Caliber12g": { | ||||
|             "5d6e6772a4b936088465b17c": 2, | ||||
|             "5d6e6806a4b936088465b17e": 2, | ||||
|             "5d6e67fba4b9361bc73bc779": 2, | ||||
|             "560d5e524bdc2d25448b4571": 2, | ||||
|             "5d6e6869a4b9361c140bcfde": 1, | ||||
|             "5d6e68b3a4b9361bca7e50b5": 1, | ||||
|             "58820d1224597753c90aeb13": 1, | ||||
|             "5d6e68dea4b9361bcc29e659": 1, | ||||
|             "5d6e6891a4b9361bd473feea": 1, | ||||
|             "5d6e68e6a4b9361c140bcfe0": 1, | ||||
|             "5d6e689ca4b9361bc8618956": 1 | ||||
|         }, | ||||
|         "Caliber20g": { | ||||
|             "5d6e695fa4b936359b35d852": 2, | ||||
|             "5d6e69b9a4b9361bc8618958": 2, | ||||
|             "5a38ebd9c4a282000d722a5b": 2, | ||||
|             "5d6e69c7a4b9360b6c0d54e4": 1, | ||||
|             "5d6e6a53a4b9361bd473feec": 1 | ||||
|         }, | ||||
|         "Caliber23x75": { | ||||
|             "5f647f31b6238e5dd066e196": 3, | ||||
|             "5e85a9a6eacf8c039e4e2ac1": 1 | ||||
|         }, | ||||
|         "Caliber366TKM": { | ||||
|             "59e6658b86f77411d949b250": 3, | ||||
|             "59e6542b86f77411dc52a77a": 1 | ||||
|         }, | ||||
|         "Caliber40mmRU": { | ||||
|             "5656eb674bdc2d35148b457c": 1 | ||||
|         }, | ||||
|         "Caliber40x46": { | ||||
|             "5ede4739e0350d05467f73e8": 1, | ||||
|             "5ede47405b097655935d7d16": 1, | ||||
|             "5ede474b0c226a66f5402622": 1, | ||||
|             "5ede475339ee016e8c534742": 1, | ||||
|             "5ede475b549eed7c6d5c18fb": 1, | ||||
|             "5f0c892565703e5c461894e9": 1 | ||||
|         }, | ||||
|         "Caliber46x30": { | ||||
|             "5ba26812d4351e003201fef1": 3, | ||||
|             "5ba26844d4351e00334c9475": 1 | ||||
|         }, | ||||
|         "Caliber545x39": { | ||||
|             "56dff216d2720bbd668b4568": 1, | ||||
|             "56dff338d2720bbd668b4569": 4, | ||||
|             "56dff421d2720b5f5a8b4567": 4, | ||||
|             "56dff4ecd2720b5f5a8b4568": 2, | ||||
|             "56dff4a2d2720bbd668b456a": 4, | ||||
|             "56dff0bed2720bb0668b4567": 3, | ||||
|             "56dff3afd2720bba668b4567": 1 | ||||
|         }, | ||||
|         "Caliber556x45NATO": { | ||||
|             "59e6927d86f77411da468256": 2, | ||||
|             "59e6918f86f7746c9f75e849": 2, | ||||
|             "59e68f6f86f7746c9f75e846": 4, | ||||
|             "59e6920f86f77411d82aa167": 5, | ||||
|             "54527a984bdc2d4e668b4567": 1 | ||||
|         }, | ||||
|         "Caliber57x28": { | ||||
|             "5cc86832d7f00c000d3a6e6c": 2, | ||||
|             "5cc80f79e4a949033c7343b2": 3, | ||||
|             "5cc86840d7f00c002412c56c": 3, | ||||
|             "5cc80f8fe4a949033b0224a2": 1, | ||||
|             "5cc80f53e4a949000e1ea4f8": 1 | ||||
|         }, | ||||
|         "Caliber68x51": { | ||||
|             "6529302b8c26af6326029fb7": 1 | ||||
|         }, | ||||
|         "Caliber762x25TT": { | ||||
|             "573602322459776445391df1": 2, | ||||
|             "573601b42459776410737435": 2, | ||||
|             "5735fdcd2459776445391d61": 1, | ||||
|             "5736026a245977644601dc61": 1 | ||||
|         }, | ||||
|         "Caliber762x35": { | ||||
|             "6196365d58ef8c428c287da1": 1, | ||||
|             "6196364158ef8c428c287d9f": 6, | ||||
|             "5fbe3ffdf8b6a877a729ea82": 3 | ||||
|         }, | ||||
|         "Caliber762x39": { | ||||
|             "59e4d3d286f774176a36250a": 2, | ||||
|             "64b7af734b75259c590fa895": 2, | ||||
|             "64b7af5a8532cf95ee0a0dbd": 6, | ||||
|             "59e4d24686f7741776641ac7": 4, | ||||
|             "59e4cf5286f7741778269d8a": 2, | ||||
|             "5656d7c34bdc2d9d198b4587": 1 | ||||
|         }, | ||||
|         "Caliber762x51": { | ||||
|             "5e023e88277cce2b522ff2b1": 2, | ||||
|             "5e023e6e34d52a55c3304f71": 2, | ||||
|             "5e023e53d4353e3302577c4c": 1 | ||||
|         }, | ||||
|         "Caliber762x54R": { | ||||
|             "64b8f7c241772715af0f9c3d": 2, | ||||
|             "64b8f7b5389d7ffd620ccba2": 2, | ||||
|             "64b8f7968532cf95ee0a0dbf": 2, | ||||
|             "5e023cf8186a883be655e54f": 2, | ||||
|             "5887431f2459777e1612938f": 1 | ||||
|         }, | ||||
|         "Caliber86x70": { | ||||
|             "5fc382b6d6fa9c00c571bbc3": 2, | ||||
|             "5fc382c1016cce60e8341b20": 1 | ||||
|         }, | ||||
|         "Caliber9x18PM": { | ||||
|             "5737218f245977612125ba51": 5, | ||||
|             "57372140245977611f70ee91": 5, | ||||
|             "5737207f24597760ff7b25f2": 2, | ||||
|             "573719762459775a626ccbc1": 3, | ||||
|             "57371f8d24597761006c6a81": 3, | ||||
|             "57371f2b24597761224311f1": 5, | ||||
|             "57371eb62459776125652ac1": 1, | ||||
|             "57371b192459775a9f58a5e0": 1, | ||||
|             "57371e4124597760ff7b25f1": 1 | ||||
|         }, | ||||
|         "Caliber9x19PARA": { | ||||
|             "5efb0e16aeb21837e749c7ff": 1, | ||||
|             "58864a4f2459770fcc257101": 7, | ||||
|             "5a3c16fe86f77452b62de32a": 12, | ||||
|             "5c3df7d588a4501f290594e5": 6, | ||||
|             "64b7bbb74b75259c590fa897": 4, | ||||
|             "56d59d3ad2720bdb418b4577": 2 | ||||
|         }, | ||||
|         "Caliber9x21": { | ||||
|             "5a26ac06c4a282000c5a90a8": 5, | ||||
|             "5a26abfac4a28232980eabff": 3, | ||||
|             "5a269f97c4a282000b151807": 1 | ||||
|         }, | ||||
|         "Caliber9x33R": { | ||||
|             "62330c40bdd19b369e1e53d1": 5, | ||||
|             "62330bfadc5883093563729b": 3, | ||||
|             "62330c18744e5e31df12f516": 1 | ||||
|         }, | ||||
|         "Caliber9x39": { | ||||
|             "6576f96220d53a5b8f3e395e": 7, | ||||
|             "57a0dfb82459774d3078b56c": 5, | ||||
|             "5c0d668f86f7747ccb7f13b2": 1 | ||||
|         }, | ||||
|         "Caliber127x33": { | ||||
|             "66a0d1c87d0d369e270bb9de": 10, | ||||
|             "66a0d1f88486c69fce00fdf6": 1 | ||||
|         } | ||||
|     }, | ||||
|     "pmcAmmo": { | ||||
|         "Caliber1143x23ACP": { | ||||
|             "5ea2a8e200685063ec28c05a": 1, | ||||
|             "5efb0fc6aeb21837e749c801": 8, | ||||
|             "5efb0d4f4bc50b58e81710f3": 40, | ||||
|             "5e81f423763d9f754677bf2e": 15 | ||||
|         }, | ||||
|         "Caliber127x55": { | ||||
|             "5cadf6e5ae921500113bb973": 45 | ||||
|         }, | ||||
|         "Caliber12g": { | ||||
|             "5d6e6806a4b936088465b17e": 10, | ||||
|             "5c0d591486f7744c505b416f": 3, | ||||
|             "5d6e68d1a4b93622fe60e845": 3, | ||||
|             "5d6e6869a4b9361c140bcfde": 2, | ||||
|             "5d6e68b3a4b9361bca7e50b5": 4, | ||||
|             "58820d1224597753c90aeb13": 6, | ||||
|             "5d6e68dea4b9361bcc29e659": 8, | ||||
|             "5d6e6891a4b9361bd473feea": 12, | ||||
|             "5d6e68e6a4b9361c140bcfe0": 12, | ||||
|             "5d6e689ca4b9361bc8618956": 9 | ||||
|         }, | ||||
|         "Caliber20g": { | ||||
|             "5d6e695fa4b936359b35d852": 8, | ||||
|             "5d6e69b9a4b9361bc8618958": 8, | ||||
|             "5a38ebd9c4a282000d722a5b": 8, | ||||
|             "5d6e69c7a4b9360b6c0d54e4": 10, | ||||
| 
 | ||||
|             "5d6e6a5fa4b93614ec501745": 3, | ||||
|             "5d6e6a53a4b9361bd473feec": 3 | ||||
|         }, | ||||
|         "Caliber23x75": { | ||||
|             "5f647f31b6238e5dd066e196": 10, | ||||
|             "5e85a9a6eacf8c039e4e2ac1": 2 | ||||
|         }, | ||||
|         "Caliber366TKM": { | ||||
|             "59e6658b86f77411d949b250": 20, | ||||
|             "59e6542b86f77411dc52a77a": 25, | ||||
|             "59e655cb86f77411dc52a77b": 8 | ||||
|         }, | ||||
|         "Caliber40mmRU": { | ||||
|             "5656eb674bdc2d35148b457c": 1 | ||||
|         }, | ||||
|         "Caliber40x46": { | ||||
|             "5ede4739e0350d05467f73e8": 1, | ||||
|             "5ede47405b097655935d7d16": 1, | ||||
|             "5ede474b0c226a66f5402622": 1, | ||||
|             "5ede475339ee016e8c534742": 1, | ||||
|             "5ede475b549eed7c6d5c18fb": 1, | ||||
|             "5f0c892565703e5c461894e9": 1 | ||||
|         }, | ||||
|         "Caliber46x30": { | ||||
|             "5ba26812d4351e003201fef1": 50, | ||||
|             "5ba26844d4351e00334c9475": 50 | ||||
|         }, | ||||
|         "Caliber545x39": { | ||||
|             "56dff216d2720bbd668b4568": 1, | ||||
|             "56dff338d2720bbd668b4569": 10, | ||||
|             "56dff421d2720b5f5a8b4567": 10, | ||||
|             "56dff4ecd2720b5f5a8b4568": 15, | ||||
|             "56dff4a2d2720bbd668b456a": 15, | ||||
|             "56dff0bed2720bb0668b4567": 35, | ||||
|             "56dff3afd2720bba668b4567": 45 | ||||
|         }, | ||||
|         "Caliber556x45NATO": { | ||||
|             "59e6927d86f77411da468256": 10, | ||||
|             "59e6918f86f7746c9f75e849": 20, | ||||
|             "59e68f6f86f7746c9f75e846": 45, | ||||
|             "59e6920f86f77411d82aa167": 50, | ||||
|             "54527a984bdc2d4e668b4567": 20 | ||||
|         }, | ||||
|         "Caliber57x28": { | ||||
|             "5cc86832d7f00c000d3a6e6c": 10, | ||||
|             "5cc80f79e4a949033c7343b2": 19, | ||||
|             "5cc86840d7f00c002412c56c": 24, | ||||
|             "5cc80f8fe4a949033b0224a2": 13, | ||||
|             "5cc80f53e4a949000e1ea4f8": 9 | ||||
|         }, | ||||
|         "Caliber68x51": { | ||||
|             "6529302b8c26af6326029fb7": 1 | ||||
|         }, | ||||
|         "Caliber762x25TT": { | ||||
|             "573602322459776445391df1": 6, | ||||
|             "573601b42459776410737435": 10, | ||||
|             "5735fdcd2459776445391d61": 18, | ||||
|             "5736026a245977644601dc61": 10, | ||||
|             "573603c924597764442bd9cb": 4, | ||||
|             "573603562459776430731618": 1 | ||||
|         }, | ||||
|         "Caliber762x35": { | ||||
|             "6196365d58ef8c428c287da1": 9, | ||||
|             "6196364158ef8c428c287d9f": 19, | ||||
|             "5fbe3ffdf8b6a877a729ea82": 14 | ||||
|         }, | ||||
|         "Caliber762x39": { | ||||
|             "59e4d3d286f774176a36250a": 3, | ||||
|             "64b7af734b75259c590fa895": 10, | ||||
|             "64b7af5a8532cf95ee0a0dbd": 20, | ||||
|             "59e4d24686f7741776641ac7": 25, | ||||
|             "59e4cf5286f7741778269d8a": 35, | ||||
|             "5656d7c34bdc2d9d198b4587": 15 | ||||
|         }, | ||||
|         "Caliber762x51": { | ||||
|             "5e023e88277cce2b522ff2b1": 10, | ||||
|             "5e023e6e34d52a55c3304f71": 40, | ||||
|             "5e023e53d4353e3302577c4c": 50 | ||||
|         }, | ||||
|         "Caliber762x54R": { | ||||
|             "64b8f7c241772715af0f9c3d": 9, | ||||
|             "64b8f7b5389d7ffd620ccba2": 14, | ||||
|             "64b8f7968532cf95ee0a0dbf": 16, | ||||
|             "5e023cf8186a883be655e54f": 20, | ||||
|             "5887431f2459777e1612938f": 14 | ||||
|         }, | ||||
|         "Caliber86x70": { | ||||
|             "5fc382b6d6fa9c00c571bbc3": 95, | ||||
|             "5fc382c1016cce60e8341b20": 5 | ||||
|         }, | ||||
|         "Caliber9x18PM": { | ||||
|             "5737218f245977612125ba51": 2, | ||||
|             "57372140245977611f70ee91": 6, | ||||
|             "5737207f24597760ff7b25f2": 6, | ||||
|             "573719762459775a626ccbc1": 6, | ||||
|             "57371f8d24597761006c6a81": 9, | ||||
|             "57371f2b24597761224311f1": 9, | ||||
|             "57371eb62459776125652ac1": 9, | ||||
|             "57371b192459775a9f58a5e0": 18, | ||||
|             "57371e4124597760ff7b25f1": 23, | ||||
|             "5737201124597760fc4431f1": 18, | ||||
|             "573720e02459776143012541": 9, | ||||
|             "573718ba2459775a75491131": 6 | ||||
|         }, | ||||
|         "Caliber9x19PARA": { | ||||
|             "5c0d56a986f774449d5de529": 1, | ||||
|             "5efb0e16aeb21837e749c7ff": 7, | ||||
|             "58864a4f2459770fcc257101": 20, | ||||
|             "5a3c16fe86f77452b62de32a": 30, | ||||
|             "5c3df7d588a4501f290594e5": 40, | ||||
|             "64b7bbb74b75259c590fa897": 40, | ||||
|             "56d59d3ad2720bdb418b4577": 25 | ||||
|         }, | ||||
|         "Caliber9x21": { | ||||
|             "5a26ac06c4a282000c5a90a8": 9, | ||||
|             "5a26abfac4a28232980eabff": 22, | ||||
|             "5a269f97c4a282000b151807": 17 | ||||
|         }, | ||||
|         "Caliber9x33R": { | ||||
|             "62330c40bdd19b369e1e53d1": 15, | ||||
|             "62330bfadc5883093563729b": 12 | ||||
|         }, | ||||
|         "Caliber9x39": { | ||||
|             "6576f96220d53a5b8f3e395e": 19, | ||||
|             "57a0dfb82459774d3078b56c": 27, | ||||
|             "5c0d668f86f7747ccb7f13b2": 13 | ||||
|         }, | ||||
|         "Caliber127x33": { | ||||
|             "66a0d1c87d0d369e270bb9de": 50, | ||||
|             "66a0d1f88486c69fce00fdf6": 30 | ||||
|         } | ||||
|     }, | ||||
|     "bossAmmo": { | ||||
|         "Caliber1143x23ACP": { | ||||
|             "5ea2a8e200685063ec28c05a": 4, | ||||
|             "5efb0fc6aeb21837e749c801": 1, | ||||
|             "5efb0d4f4bc50b58e81710f3": 10, | ||||
|             "5e81f423763d9f754677bf2e": 18, | ||||
|             "5efb0cabfb3e451d70735af5": 10 | ||||
|         }, | ||||
|         "Caliber127x55": { | ||||
|             "5cadf6e5ae921500113bb973": 3, | ||||
|             "5cadf6ddae9215051e1c23b2": 12, | ||||
|             "5cadf6eeae921500134b2799": 8 | ||||
|         }, | ||||
|         "Caliber12g": { | ||||
|             "5d6e6806a4b936088465b17e": 7, | ||||
|             "64b8ee384b75259c590fa89b": 4, | ||||
|             "5d6e6911a4b9361bd5780d52": 3, | ||||
|             "5c0d591486f7744c505b416f": 5, | ||||
|             "5d6e6891a4b9361bd473feea": 2, | ||||
|             "5d6e68e6a4b9361c140bcfe0": 6, | ||||
|             "5d6e689ca4b9361bc8618956": 8, | ||||
|             "5d6e68c4a4b9361b93413f79": 8, | ||||
|             "5d6e68a8a4b9360b6c0d54e2": 3 | ||||
|         }, | ||||
|         "Caliber20g": { | ||||
|             "5d6e69c7a4b9360b6c0d54e4": 1, | ||||
|             "5d6e6a53a4b9361bd473feec": 4, | ||||
|             "5d6e6a05a4b93618084f58d0": 5, | ||||
|             "5d6e6a42a4b9364f07165f52": 5 | ||||
|         }, | ||||
|         "Caliber23x75": { | ||||
|             "5f647f31b6238e5dd066e196": 2, | ||||
|             "5e85a9a6eacf8c039e4e2ac1": 4, | ||||
|             "5e85aa1a988a8701445df1f5": 4 | ||||
|         }, | ||||
|         "Caliber366TKM": { | ||||
|             "59e6658b86f77411d949b250": 1, | ||||
|             "59e6542b86f77411dc52a77a": 2, | ||||
|             "59e655cb86f77411dc52a77b": 10, | ||||
|             "5f0596629e22f464da6bbdd9": 8 | ||||
|         }, | ||||
|         "Caliber40mmRU": { | ||||
|             "5656eb674bdc2d35148b457c": 1 | ||||
|         }, | ||||
|         "Caliber40x46": { | ||||
|             "5ede4739e0350d05467f73e8": 1, | ||||
|             "5ede47405b097655935d7d16": 1, | ||||
|             "5ede474b0c226a66f5402622": 1, | ||||
|             "5ede475339ee016e8c534742": 1, | ||||
|             "5ede475b549eed7c6d5c18fb": 1, | ||||
|             "5f0c892565703e5c461894e9": 1 | ||||
|         }, | ||||
|         "Caliber46x30": { | ||||
|             "5ba26812d4351e003201fef1": 2, | ||||
|             "5ba26844d4351e00334c9475": 4, | ||||
|             "5ba2678ad4351e44f824b344": 15, | ||||
|             "64b6979341772715af0f9c39": 15, | ||||
|             "5ba26835d4351e0035628ff5": 8 | ||||
|         }, | ||||
|         "Caliber545x39": { | ||||
|             "56dff3afd2720bba668b4567": 6, | ||||
|             "56dff2ced2720bb4668b4567": 12, | ||||
|             "56dff061d2720bb5668b4567": 20, | ||||
|             "61962b617c6c7b169525f168": 12, | ||||
|             "56dfef82d2720bbd668b4567": 9, | ||||
|             "56dff026d2720bb8668b4567": 8, | ||||
|             "5c0d5e4486f77478390952fe": 4 | ||||
|         }, | ||||
|         "Caliber556x45NATO": { | ||||
|             "5c0d5ae286f7741e46554302": 1, | ||||
|             "54527a984bdc2d4e668b4567": 7, | ||||
|             "60194943740c5d77f6705eea": 20, | ||||
|             "59e6906286f7746c9f75e847": 26, | ||||
|             "54527ac44bdc2d36668b4567": 30, | ||||
|             "59e690b686f7746c9f75e848": 7, | ||||
|             "601949593ae8f707c4608daa": 5 | ||||
|         }, | ||||
|         "Caliber57x28": { | ||||
|             "5cc80f8fe4a949033b0224a2": 5, | ||||
|             "5cc80f53e4a949000e1ea4f8": 21, | ||||
|             "5cc80f67e4a949035e43bbba": 15, | ||||
|             "5cc80f38e4a949001152b560": 12 | ||||
|         }, | ||||
|         "Caliber68x51": { | ||||
|             "6529302b8c26af6326029fb7": 10, | ||||
|             "6529243824cbe3c74a05e5c1": 5 | ||||
|         }, | ||||
|         "Caliber762x25TT": { | ||||
|             "5736026a245977644601dc61": 5, | ||||
|             "573603c924597764442bd9cb": 10, | ||||
|             "573603562459776430731618": 10 | ||||
|         }, | ||||
|         "Caliber762x35": { | ||||
|             "6196365d58ef8c428c287da1": 7, | ||||
|             "5fbe3ffdf8b6a877a729ea82": 6, | ||||
|             "619636be6db0f2477964e710": 23, | ||||
|             "64b8725c4b75259c590fa899": 20, | ||||
|             "5fd20ff893a8961fc660a954": 9 | ||||
|         }, | ||||
|         "Caliber762x39": { | ||||
|             "59e4cf5286f7741778269d8a": 4, | ||||
|             "5656d7c34bdc2d9d198b4587": 28, | ||||
|             "64b7af434b75259c590fa893": 33, | ||||
|             "59e0d99486f7744a32234762": 20, | ||||
|             "601aa3d2b2bcb34913271e6d": 12 | ||||
|         }, | ||||
|         "Caliber762x51": { | ||||
|             "5e023e53d4353e3302577c4c": 6, | ||||
|             "58dd3ad986f77403051cba8f": 27, | ||||
|             "5a608bf24f39f98ffc77720e": 19, | ||||
|             "5a6086ea4f39f99cd479502f": 9, | ||||
|             "5efb0c1bd79ff02a1f5e68d9": 2 | ||||
|         }, | ||||
|         "Caliber762x54R": { | ||||
|             "5e023cf8186a883be655e54f": 3, | ||||
|             "5887431f2459777e1612938f": 20, | ||||
|             "59e77a2386f7742ee578960a": 25, | ||||
|             "5e023d34e8a400319a28ed44": 22, | ||||
|             "560d61e84bdc2da74d8b4571": 15, | ||||
|             "5e023d48186a883be655e551": 10 | ||||
|         }, | ||||
|         "Caliber86x70": { | ||||
|             "5fc382b6d6fa9c00c571bbc3": 5, | ||||
|             "5fc382c1016cce60e8341b20": 8, | ||||
|             "5fc275cf85fd526b824a571a": 8, | ||||
|             "5fc382a9d724d907e2077dab": 5 | ||||
|         }, | ||||
|         "Caliber9x18PM": { | ||||
|             "57371e4124597760ff7b25f1": 3, | ||||
|             "5737201124597760fc4431f1": 5, | ||||
|             "573720e02459776143012541": 12, | ||||
|             "573718ba2459775a75491131": 18, | ||||
|             "57371aab2459775a77142f22": 12, | ||||
|             "573719df2459775a626ccbc2": 10 | ||||
|         }, | ||||
|         "Caliber9x19PARA": { | ||||
|             "5c0d56a986f774449d5de529": 9, | ||||
|             "5efb0e16aeb21837e749c7ff": 5, | ||||
|             "5a3c16fe86f77452b62de32a": 4, | ||||
|             "56d59d3ad2720bdb418b4577": 18, | ||||
|             "5c925fa22e221601da359b7b": 22, | ||||
|             "5efb0da7a29a85116f6ea05f": 9 | ||||
|         }, | ||||
|         "Caliber9x21": { | ||||
|             "5a269f97c4a282000b151807": 8, | ||||
|             "6576f93989f0062e741ba952": 18, | ||||
|             "5a26ac0ec4a28200741e1e18": 18, | ||||
|             "6576f4708ca9c4381d16cd9d": 8 | ||||
|         }, | ||||
|         "Caliber9x33R": { | ||||
|             "62330c18744e5e31df12f516": 9, | ||||
|             "62330b3ed4dc74626d570b95": 6 | ||||
|         }, | ||||
|         "Caliber9x39": { | ||||
|             "5c0d668f86f7747ccb7f13b2": 9, | ||||
|             "61962d879bb3d20b0946d385": 25, | ||||
|             "57a0e5022459774d1673f889": 25, | ||||
|             "5c0d688c86f77413ae3407b2": 12 | ||||
|         }, | ||||
|         "Caliber127x33": { | ||||
|             "66a0d1c87d0d369e270bb9de": 3, | ||||
|             "66a0d1f88486c69fce00fdf6": 30, | ||||
|             "66a0d1e0ed648d72fe064d06": 25,  | ||||
|             "668fe62ac62660a5d8071446": 12 | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,411 @@ | |||
| { | ||||
|     "pmcUSEC": { | ||||
|         "appearance": { | ||||
|             "body": { | ||||
|                 "5cde95d97d6c8b647a3769b0": 5, | ||||
|                 "66546f823b51a4d21e0d17d7": 1, | ||||
|                 "5d1f56a686f7744bce0ee9eb": 2 | ||||
|             }, | ||||
|             "feet": { | ||||
|                 "5cde95ef7d6c8b04713c4f2d": 5, | ||||
|                 "5d1f58ed86f7744bcb0acd1c": 1 | ||||
|             }, | ||||
|             "hands": { | ||||
|                 "5cde95fa7d6c8b04737c2d13": 1 | ||||
|             }, | ||||
|             "head": { | ||||
|                 "5cde96047d6c8b20b577f016": 1, | ||||
|                 "5fdb4139e4ed5b5ea251e4ed": 1, | ||||
|                 "5fdb5950f5264a66150d1c6e": 1, | ||||
|                 "60a6aa8fd559ae040d0d951f": 1, | ||||
|                 "619f9e338858a474c8685cc9": 1, | ||||
|                 "62aca6a1310e67685a2fc2e7": 1, | ||||
|                 "6574aabee0423b9ebe0c79cf": 1 | ||||
|             } | ||||
|         } | ||||
|     }, | ||||
|     "pmcBEAR": { | ||||
|         "appearance": { | ||||
|             "body": { | ||||
|                 "5cc0858d14c02e000c6bea66": 5, | ||||
|                 "66546f823b51a4d21e0d17d7": 1, | ||||
|                 "5d1f565786f7743f8362bcd5": 2 | ||||
|             }, | ||||
|             "feet": { | ||||
|                 "5cc085bb14c02e000e67a5c5": 5, | ||||
|                 "5d1f58bd86f7744bce0ee9ef": 1 | ||||
|             }, | ||||
|             "hands": { | ||||
|                 "5cc0876314c02e000c6bea6b": 1 | ||||
|             }, | ||||
|             "head": { | ||||
|                 "5cc084dd14c02e000b0550a3": 1, | ||||
|                 "5fdb50bb2b730a787b3f78cf": 1, | ||||
|                 "5fdb7571e4ed5b5ea251e529": 1, | ||||
|                 "60a6aaad42fd2735e4589978": 1, | ||||
|                 "619f94f5b90286142b59d45f": 1, | ||||
|                 "62a9e7d15ea3b87d6f642a28": 1, | ||||
|                 "6574aa9a1b144de18c0fba45": 1 | ||||
|             } | ||||
|         } | ||||
|     }, | ||||
|     "springEarly": { | ||||
|         "pmcUSEC": { | ||||
|             "appearance": { | ||||
|                 "body": { | ||||
|                     "5d1f56c686f7744bcd13459c": 1, | ||||
|                     "5fd3e9f71b735718c25cd9f8": 1, | ||||
|                     "66043728333907134309d647": 1, | ||||
|                     "66acbe49dc61999a6a03d4d6": 1, | ||||
|                     "660437e57502eca33a08caca": 1, | ||||
|                     "5d1f56f186f7744bcb0acd1a": 1, | ||||
|                     "5d1f56ff86f7743f8362bcd7": 1, | ||||
|                     "5d1f56a686f7744bce0ee9eb": 2, | ||||
|                     "5e9da17386f774054b6f79a3": 2, | ||||
|                     "5e4bb35286f77406a511c9bc": 2, | ||||
|                     "5d1f56e486f7744bce0ee9ed": 2 | ||||
|                 }, | ||||
|                 "feet": { | ||||
|                     "642d4d8eb6b75d4c89077cf9": 1, | ||||
|                     "5fcf940bce1ba36a513bb9cc": 1, | ||||
|                     "66acc8f719271bd6d00dec0b": 1, | ||||
|                     "6295e944e9de5e7b3751c4da": 1, | ||||
|                     "5d1f592286f7743f8362bcdb": 1, | ||||
|                     "5e4bb3b586f77406812bd579": 1, | ||||
|                     "5d1f590486f7744bcd13459e": 3, | ||||
|                     "5d1f58ed86f7744bcb0acd1c": 3 | ||||
|                 }, | ||||
|                 "hands": { | ||||
|                     "5cde95fa7d6c8b04737c2d13": 1 | ||||
|                 }, | ||||
|                 "head": { | ||||
|                     "5cde96047d6c8b20b577f016": 1, | ||||
|                     "5fdb4139e4ed5b5ea251e4ed": 1, | ||||
|                     "5fdb5950f5264a66150d1c6e": 1, | ||||
|                     "60a6aa8fd559ae040d0d951f": 1, | ||||
|                     "619f9e338858a474c8685cc9": 1, | ||||
|                     "62aca6a1310e67685a2fc2e7": 1, | ||||
|                     "6574aabee0423b9ebe0c79cf": 1 | ||||
|                 } | ||||
|             } | ||||
|         }, | ||||
|         "pmcBEAR": { | ||||
|             "appearance": { | ||||
|                 "body": { | ||||
|                     "657058fddf9b3231400e9188": 1, | ||||
|                     "6033a31e9ec839204e6a2f3e": 1, | ||||
|                     "5d1f567786f7744bcc04874f": 1, | ||||
|                     "5e9d9fa986f774054d6b89f2": 1, | ||||
|                     "5f5e401747344c2e4f6c42c5": 1, | ||||
|                     "642e8ae07e17c882400c4f87": 2, | ||||
|                     "5d1f568486f7744bca3f0b98": 2, | ||||
|                     "66acec1dc94f4bf5bc063a16": 2, | ||||
|                     "5e4bb31586f7740695730568": 2 | ||||
|                 }, | ||||
|                 "feet": { | ||||
|                     "5d1f58bd86f7744bce0ee9ef": 1, | ||||
|                     "6377315993a3b4967208e437": 1, | ||||
|                     "66043cf87502eca33a08cad2": 1, | ||||
|                     "5d1f58cb86f7744bca3f0b9a": 1, | ||||
|                     "5d1f58a086f7743f8362bcd9": 1, | ||||
|                     "617be9e4e02b3b3fa50fa8f2": 1, | ||||
|                     "5f5e40400bc58666c37e7819": 1, | ||||
|                     "66acebd4ede86671bb09584b": 3, | ||||
|                     "5d1f58ab86f7743014162042": 3 | ||||
|                 }, | ||||
|                 "hands": { | ||||
|                     "5cc0876314c02e000c6bea6b": 1 | ||||
|                 }, | ||||
|                 "head": { | ||||
|                     "5cc084dd14c02e000b0550a3": 1, | ||||
|                     "5fdb50bb2b730a787b3f78cf": 1, | ||||
|                     "5fdb7571e4ed5b5ea251e529": 1, | ||||
|                     "60a6aaad42fd2735e4589978": 1, | ||||
|                     "619f94f5b90286142b59d45f": 1, | ||||
|                     "62a9e7d15ea3b87d6f642a28": 1, | ||||
|                     "6574aa9a1b144de18c0fba45": 1 | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     }, | ||||
|     "spring": { | ||||
|         "pmcUSEC": { | ||||
|             "appearance": { | ||||
|                 "body": { | ||||
|                     "5cde95d97d6c8b647a3769b0": 1, | ||||
|                     "5fd3e9f71b735718c25cd9f8": 1, | ||||
|                     "66043728333907134309d647": 1, | ||||
|                     "5d4da0cb86f77450fe0a6629": 1, | ||||
|                     "5d1f56f186f7744bcb0acd1a": 1, | ||||
|                     "5f5e4075df4f3100376a8138": 1 | ||||
|                 }, | ||||
|                 "feet": { | ||||
|                     "5cde95ef7d6c8b04713c4f2d": 1, | ||||
|                     "6033a3fee29c9f6c9b14e74e": 1, | ||||
|                     "660436487502eca33a08cac8": 1, | ||||
|                     "6571cad4c8673f00290f5657": 1, | ||||
|                     "66acc8f719271bd6d00dec0b": 1, | ||||
|                     "5d1f592286f7743f8362bcdb": 1, | ||||
|                     "642d6941ff5ecad7810a8a61": 1, | ||||
|                     "5e9dcadd86f7743e20652f23": 1 | ||||
|                 }, | ||||
|                 "hands": { | ||||
|                     "5cde95fa7d6c8b04737c2d13": 1 | ||||
|                 }, | ||||
|                 "head": { | ||||
|                     "5cde96047d6c8b20b577f016": 1, | ||||
|                     "5fdb4139e4ed5b5ea251e4ed": 1, | ||||
|                     "5fdb5950f5264a66150d1c6e": 1, | ||||
|                     "60a6aa8fd559ae040d0d951f": 1, | ||||
|                     "619f9e338858a474c8685cc9": 1, | ||||
|                     "62aca6a1310e67685a2fc2e7": 1, | ||||
|                     "6574aabee0423b9ebe0c79cf": 1 | ||||
|                 } | ||||
|             } | ||||
|         }, | ||||
|         "pmcBEAR": { | ||||
|             "appearance": { | ||||
|                 "body": { | ||||
|                     "5cc0858d14c02e000c6bea66": 1, | ||||
|                     "5d1f564b86f7744bcb0acd16": 1, | ||||
|                     "6295e698e9de5e7b3751c47a": 1, | ||||
|                     "6033a31e9ec839204e6a2f3e": 1, | ||||
|                     "5fce3e47fe40296c1d5fd784": 1, | ||||
|                     "617bca4b4013b06b0b78df2a": 1, | ||||
|                     "5df89f1f86f77412631087ea": 1 | ||||
|                 }, | ||||
|                 "feet": { | ||||
|                     "5cc085bb14c02e000e67a5c5": 1, | ||||
|                     "5d1f588e86f7744bcc048753": 1, | ||||
|                     "66043cf87502eca33a08cad2": 1, | ||||
|                     "6033a3d8ed2e0509b15f9031": 1, | ||||
|                     "642e71620a69698d1b049f0a": 1, | ||||
|                     "617be9e4e02b3b3fa50fa8f2": 1, | ||||
|                     "642eea6f881906a7fe086841": 1, | ||||
|                     "5df89f8f86f77412672a1e38": 1, | ||||
|                     "5e9dc97c86f774054c19ac9a": 1, | ||||
|                     "5e4bb39386f774067f79de05": 1 | ||||
|                 }, | ||||
|                 "hands": { | ||||
|                     "5cc0876314c02e000c6bea6b": 1 | ||||
|                 }, | ||||
|                 "head": { | ||||
|                     "5cc084dd14c02e000b0550a3": 1, | ||||
|                     "5fdb50bb2b730a787b3f78cf": 1, | ||||
|                     "5fdb7571e4ed5b5ea251e529": 1, | ||||
|                     "60a6aaad42fd2735e4589978": 1, | ||||
|                     "619f94f5b90286142b59d45f": 1, | ||||
|                     "62a9e7d15ea3b87d6f642a28": 1, | ||||
|                     "6574aa9a1b144de18c0fba45": 1 | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     }, | ||||
|     "summer": { | ||||
|         "pmcUSEC": { | ||||
|             "appearance": { | ||||
|                 "body": { | ||||
|                     "5cde95d97d6c8b647a3769b0": 1, | ||||
|                     "5d1f56c686f7744bcd13459c": 1, | ||||
|                     "5fd3e9f71b735718c25cd9f8": 1, | ||||
|                     "66043728333907134309d647": 1, | ||||
|                     "5d4da0cb86f77450fe0a6629": 1, | ||||
|                     "66acbe49dc61999a6a03d4d6": 1, | ||||
|                     "64ef3efdb63b74469b6c1499": 1, | ||||
|                     "642c18b8a6a0660b560fb31c": 1, | ||||
|                     "5d1f56f186f7744bcb0acd1a": 1, | ||||
|                     "5f5e4075df4f3100376a8138": 1 | ||||
|                 }, | ||||
|                 "feet": { | ||||
|                     "5cde95ef7d6c8b04713c4f2d": 1, | ||||
|                     "6033a3fee29c9f6c9b14e74e": 1, | ||||
|                     "660436487502eca33a08cac8": 1, | ||||
|                     "6571cad4c8673f00290f5657": 1, | ||||
|                     "66acc8f719271bd6d00dec0b": 1, | ||||
|                     "5d1f593286f7743014162044": 1, | ||||
|                     "5d1f592286f7743f8362bcdb": 1, | ||||
|                     "642d6941ff5ecad7810a8a61": 1, | ||||
|                     "5e9dcadd86f7743e20652f23": 1 | ||||
|                 }, | ||||
|                 "hands": { | ||||
|                     "5cde95fa7d6c8b04737c2d13": 1 | ||||
|                 }, | ||||
|                 "head": { | ||||
|                     "5cde96047d6c8b20b577f016": 1, | ||||
|                     "5fdb4139e4ed5b5ea251e4ed": 1, | ||||
|                     "5fdb5950f5264a66150d1c6e": 1, | ||||
|                     "60a6aa8fd559ae040d0d951f": 1, | ||||
|                     "619f9e338858a474c8685cc9": 1, | ||||
|                     "62aca6a1310e67685a2fc2e7": 1, | ||||
|                     "6574aabee0423b9ebe0c79cf": 1 | ||||
|                 } | ||||
|             } | ||||
|         }, | ||||
|         "pmcBEAR": { | ||||
|             "appearance": { | ||||
|                 "body": { | ||||
|                     "5cc0858d14c02e000c6bea66": 1, | ||||
|                     "5d1f564b86f7744bcb0acd16": 1, | ||||
|                     "6295e698e9de5e7b3751c47a": 1, | ||||
|                     "6033a31e9ec839204e6a2f3e": 1, | ||||
|                     "5fce3e47fe40296c1d5fd784": 1, | ||||
|                     "617bca4b4013b06b0b78df2a": 1, | ||||
|                     "64ef3efdb63b74469b6c1499": 1, | ||||
|                     "5df89f1f86f77412631087ea": 1, | ||||
|                     "5e9d9fa986f774054d6b89f2": 1 | ||||
|                 }, | ||||
|                 "feet": { | ||||
|                     "5cc085bb14c02e000e67a5c5": 1, | ||||
|                     "5d1f588e86f7744bcc048753": 1, | ||||
|                     "66043cf87502eca33a08cad2": 1, | ||||
|                     "6033a3d8ed2e0509b15f9031": 1, | ||||
|                     "642e71620a69698d1b049f0a": 1, | ||||
|                     "617be9e4e02b3b3fa50fa8f2": 1, | ||||
|                     "642eea6f881906a7fe086841": 1, | ||||
|                     "5df89f8f86f77412672a1e38": 1, | ||||
|                     "5e9dc97c86f774054c19ac9a": 1, | ||||
|                     "5e4bb39386f774067f79de05": 1 | ||||
|                 }, | ||||
|                 "hands": { | ||||
|                     "5cc0876314c02e000c6bea6b": 1 | ||||
|                 }, | ||||
|                 "head": { | ||||
|                     "5cc084dd14c02e000b0550a3": 1, | ||||
|                     "5fdb50bb2b730a787b3f78cf": 1, | ||||
|                     "5fdb7571e4ed5b5ea251e529": 1, | ||||
|                     "60a6aaad42fd2735e4589978": 1, | ||||
|                     "619f94f5b90286142b59d45f": 1, | ||||
|                     "62a9e7d15ea3b87d6f642a28": 1, | ||||
|                     "6574aa9a1b144de18c0fba45": 1 | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     }, | ||||
|     "autumn": { | ||||
|         "pmcUSEC": { | ||||
|             "appearance": { | ||||
|                 "body": { | ||||
|                     "5d1f56c686f7744bcd13459c": 1, | ||||
|                     "637b945722e2a933ed0e33c8": 1, | ||||
|                     "6571cb0923aa6d72760a7f8f": 1, | ||||
|                     "6033a35f80ae5e2f970ba6bb": 1, | ||||
|                     "5d1f56e486f7744bce0ee9ed": 1, | ||||
|                     "66acbe49dc61999a6a03d4d6": 1, | ||||
|                     "660437e57502eca33a08caca": 1, | ||||
|                     "64ef3efdb63b74469b6c1499": 1, | ||||
|                     "5d1f56ff86f7743f8362bcd7": 1 | ||||
|                 }, | ||||
|                 "feet": { | ||||
|                     "642d4d8eb6b75d4c89077cf9": 1, | ||||
|                     "5fcf940bce1ba36a513bb9cc": 1, | ||||
|                     "637ba17aa10a96c2b605dbc2": 1, | ||||
|                     "6295e944e9de5e7b3751c4da": 1, | ||||
|                     "5e4bb3b586f77406812bd579": 1, | ||||
|                     "5f5e40a06760b4138443b341": 1 | ||||
|                 }, | ||||
|                 "hands": { | ||||
|                     "5cde95fa7d6c8b04737c2d13": 1 | ||||
|                 }, | ||||
|                 "head": { | ||||
|                     "5cde96047d6c8b20b577f016": 1, | ||||
|                     "5fdb4139e4ed5b5ea251e4ed": 1, | ||||
|                     "5fdb5950f5264a66150d1c6e": 1, | ||||
|                     "60a6aa8fd559ae040d0d951f": 1, | ||||
|                     "619f9e338858a474c8685cc9": 1, | ||||
|                     "62aca6a1310e67685a2fc2e7": 1, | ||||
|                     "6574aabee0423b9ebe0c79cf": 1 | ||||
|                 } | ||||
|             } | ||||
|         }, | ||||
|         "pmcBEAR": { | ||||
|             "appearance": { | ||||
|                 "body": { | ||||
|                     "6377266693a3b4967208e42b": 1, | ||||
|                     "5d1f568486f7744bca3f0b98": 1, | ||||
|                     "657058fddf9b3231400e9188": 1, | ||||
|                     "642ed297ac11c9eaf10d87e8": 1, | ||||
|                     "5d1f567786f7744bcc04874f": 1, | ||||
|                     "64ef3efdb63b74469b6c1499": 1, | ||||
|                     "6430119aac11c9eaf10d881b": 1, | ||||
|                     "5f5e401747344c2e4f6c42c5": 1 | ||||
|                 }, | ||||
|                 "feet": { | ||||
|                     "5d1f58bd86f7744bce0ee9ef": 1, | ||||
|                     "6377315993a3b4967208e437": 1, | ||||
|                     "642ed40af5bdf1c04e01952e": 1, | ||||
|                     "6295e63de08ed747e64ae991": 1, | ||||
|                     "5d1f58a086f7743f8362bcd9": 1, | ||||
|                     "66043d7ac8949a435906e434": 1, | ||||
|                     "5d1f58ab86f7743014162042": 1, | ||||
|                     "5f5e40400bc58666c37e7819": 1 | ||||
|                 }, | ||||
|                 "hands": { | ||||
|                     "5cc0876314c02e000c6bea6b": 1 | ||||
|                 }, | ||||
|                 "head": { | ||||
|                     "5cc084dd14c02e000b0550a3": 1, | ||||
|                     "5fdb50bb2b730a787b3f78cf": 1, | ||||
|                     "5fdb7571e4ed5b5ea251e529": 1, | ||||
|                     "60a6aaad42fd2735e4589978": 1, | ||||
|                     "619f94f5b90286142b59d45f": 1, | ||||
|                     "62a9e7d15ea3b87d6f642a28": 1, | ||||
|                     "6574aa9a1b144de18c0fba45": 1 | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     }, | ||||
|     "winter": { | ||||
|         "pmcUSEC": { | ||||
|             "appearance": { | ||||
|                 "body": { | ||||
|                     "5d1f56a686f7744bce0ee9eb": 1, | ||||
|                     "5e9da17386f774054b6f79a3": 1, | ||||
|                     "5e4bb35286f77406a511c9bc": 1, | ||||
|                     "5d1f56e486f7744bce0ee9ed": 1 | ||||
|                 }, | ||||
|                 "feet": { | ||||
|                     "5d1f590486f7744bcd13459e": 1, | ||||
|                     "5d1f58ed86f7744bcb0acd1c": 1 | ||||
|                 }, | ||||
|                 "hands": { | ||||
|                     "5cde95fa7d6c8b04737c2d13": 1 | ||||
|                 }, | ||||
|                 "head": { | ||||
|                     "5cde96047d6c8b20b577f016": 1, | ||||
|                     "5fdb4139e4ed5b5ea251e4ed": 1, | ||||
|                     "5fdb5950f5264a66150d1c6e": 1, | ||||
|                     "60a6aa8fd559ae040d0d951f": 1, | ||||
|                     "619f9e338858a474c8685cc9": 1, | ||||
|                     "62aca6a1310e67685a2fc2e7": 1, | ||||
|                     "6574aabee0423b9ebe0c79cf": 1 | ||||
|                 } | ||||
|             } | ||||
|         }, | ||||
|         "pmcBEAR": { | ||||
|             "appearance": { | ||||
|                 "body": { | ||||
|                     "642e8ae07e17c882400c4f87": 1, | ||||
|                     "5d1f568486f7744bca3f0b98": 1, | ||||
|                     "66acec1dc94f4bf5bc063a16": 1, | ||||
|                     "5e4bb31586f7740695730568": 1 | ||||
|                 }, | ||||
|                 "feet": { | ||||
|                     "66acebd4ede86671bb09584b": 1, | ||||
|                     "5d1f58ab86f7743014162042": 1 | ||||
|                 }, | ||||
|                 "hands": { | ||||
|                     "5cc0876314c02e000c6bea6b": 1 | ||||
|                 }, | ||||
|                 "head": { | ||||
|                     "5cc084dd14c02e000b0550a3": 1, | ||||
|                     "5fdb50bb2b730a787b3f78cf": 1, | ||||
|                     "5fdb7571e4ed5b5ea251e529": 1, | ||||
|                     "60a6aaad42fd2735e4589978": 1, | ||||
|                     "619f94f5b90286142b59d45f": 1, | ||||
|                     "62a9e7d15ea3b87d6f642a28": 1, | ||||
|                     "6574aa9a1b144de18c0fba45": 1 | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							|  | @ -0,0 +1,476 @@ | |||
| {     | ||||
|     "scavAmmo": { | ||||
|         "Caliber1143x23ACP": { | ||||
|             "5efb0fc6aeb21837e749c801": 1, | ||||
|             "5efb0d4f4bc50b58e81710f3": 3 | ||||
|         }, | ||||
|         "Caliber127x55": { | ||||
|             "5cadf6e5ae921500113bb973": 1 | ||||
|         }, | ||||
|         "Caliber12g": { | ||||
|             "5d6e6772a4b936088465b17c": 2, | ||||
|             "5d6e6806a4b936088465b17e": 2, | ||||
|             "5d6e67fba4b9361bc73bc779": 2, | ||||
|             "560d5e524bdc2d25448b4571": 2, | ||||
|             "5d6e6869a4b9361c140bcfde": 1, | ||||
|             "5d6e68b3a4b9361bca7e50b5": 1, | ||||
|             "58820d1224597753c90aeb13": 1, | ||||
|             "5d6e68dea4b9361bcc29e659": 1, | ||||
|             "5d6e6891a4b9361bd473feea": 1, | ||||
|             "5d6e68e6a4b9361c140bcfe0": 1, | ||||
|             "5d6e689ca4b9361bc8618956": 1 | ||||
|         }, | ||||
|         "Caliber20g": { | ||||
|             "5d6e695fa4b936359b35d852": 2, | ||||
|             "5d6e69b9a4b9361bc8618958": 2, | ||||
|             "5a38ebd9c4a282000d722a5b": 2, | ||||
|             "5d6e69c7a4b9360b6c0d54e4": 1, | ||||
|             "5d6e6a53a4b9361bd473feec": 1 | ||||
|         }, | ||||
|         "Caliber23x75": { | ||||
|             "5f647f31b6238e5dd066e196": 3, | ||||
|             "5e85a9a6eacf8c039e4e2ac1": 1 | ||||
|         }, | ||||
|         "Caliber366TKM": { | ||||
|             "59e6658b86f77411d949b250": 3, | ||||
|             "59e6542b86f77411dc52a77a": 1 | ||||
|         }, | ||||
|         "Caliber40mmRU": { | ||||
|             "5656eb674bdc2d35148b457c": 1 | ||||
|         }, | ||||
|         "Caliber40x46": { | ||||
|             "5ede4739e0350d05467f73e8": 1, | ||||
|             "5ede47405b097655935d7d16": 1, | ||||
|             "5ede474b0c226a66f5402622": 1, | ||||
|             "5ede475339ee016e8c534742": 1, | ||||
|             "5ede475b549eed7c6d5c18fb": 1, | ||||
|             "5f0c892565703e5c461894e9": 1 | ||||
|         }, | ||||
|         "Caliber46x30": { | ||||
|             "5ba26812d4351e003201fef1": 3, | ||||
|             "5ba26844d4351e00334c9475": 1 | ||||
|         }, | ||||
|         "Caliber545x39": { | ||||
|             "56dff216d2720bbd668b4568": 1, | ||||
|             "56dff338d2720bbd668b4569": 4, | ||||
|             "56dff421d2720b5f5a8b4567": 4, | ||||
|             "56dff4ecd2720b5f5a8b4568": 2, | ||||
|             "56dff4a2d2720bbd668b456a": 4, | ||||
|             "56dff0bed2720bb0668b4567": 3, | ||||
|             "56dff3afd2720bba668b4567": 1 | ||||
|         }, | ||||
|         "Caliber556x45NATO": { | ||||
|             "59e6927d86f77411da468256": 2, | ||||
|             "59e6918f86f7746c9f75e849": 2, | ||||
|             "59e68f6f86f7746c9f75e846": 4, | ||||
|             "59e6920f86f77411d82aa167": 5, | ||||
|             "54527a984bdc2d4e668b4567": 1 | ||||
|         }, | ||||
|         "Caliber57x28": { | ||||
|             "5cc86832d7f00c000d3a6e6c": 2, | ||||
|             "5cc80f79e4a949033c7343b2": 3, | ||||
|             "5cc86840d7f00c002412c56c": 3, | ||||
|             "5cc80f8fe4a949033b0224a2": 1, | ||||
|             "5cc80f53e4a949000e1ea4f8": 1 | ||||
|         }, | ||||
|         "Caliber68x51": { | ||||
|             "6529302b8c26af6326029fb7": 1 | ||||
|         }, | ||||
|         "Caliber762x25TT": { | ||||
|             "573602322459776445391df1": 2, | ||||
|             "573601b42459776410737435": 2, | ||||
|             "5735fdcd2459776445391d61": 1, | ||||
|             "5736026a245977644601dc61": 1 | ||||
|         }, | ||||
|         "Caliber762x35": { | ||||
|             "6196365d58ef8c428c287da1": 1, | ||||
|             "6196364158ef8c428c287d9f": 6, | ||||
|             "5fbe3ffdf8b6a877a729ea82": 3 | ||||
|         }, | ||||
|         "Caliber762x39": { | ||||
|             "59e4d3d286f774176a36250a": 2, | ||||
|             "64b7af734b75259c590fa895": 2, | ||||
|             "64b7af5a8532cf95ee0a0dbd": 6, | ||||
|             "59e4d24686f7741776641ac7": 4, | ||||
|             "59e4cf5286f7741778269d8a": 2, | ||||
|             "5656d7c34bdc2d9d198b4587": 1 | ||||
|         }, | ||||
|         "Caliber762x51": { | ||||
|             "5e023e88277cce2b522ff2b1": 2, | ||||
|             "5e023e6e34d52a55c3304f71": 2, | ||||
|             "5e023e53d4353e3302577c4c": 1 | ||||
|         }, | ||||
|         "Caliber762x54R": { | ||||
|             "64b8f7c241772715af0f9c3d": 2, | ||||
|             "64b8f7b5389d7ffd620ccba2": 2, | ||||
|             "64b8f7968532cf95ee0a0dbf": 2, | ||||
|             "5e023cf8186a883be655e54f": 2, | ||||
|             "5887431f2459777e1612938f": 1 | ||||
|         }, | ||||
|         "Caliber86x70": { | ||||
|             "5fc382b6d6fa9c00c571bbc3": 2, | ||||
|             "5fc382c1016cce60e8341b20": 1 | ||||
|         }, | ||||
|         "Caliber9x18PM": { | ||||
|             "5737218f245977612125ba51": 5, | ||||
|             "57372140245977611f70ee91": 5, | ||||
|             "5737207f24597760ff7b25f2": 2, | ||||
|             "573719762459775a626ccbc1": 3, | ||||
|             "57371f8d24597761006c6a81": 3, | ||||
|             "57371f2b24597761224311f1": 5, | ||||
|             "57371eb62459776125652ac1": 1, | ||||
|             "57371b192459775a9f58a5e0": 1, | ||||
|             "57371e4124597760ff7b25f1": 1 | ||||
|         }, | ||||
|         "Caliber9x19PARA": { | ||||
|             "5efb0e16aeb21837e749c7ff": 1, | ||||
|             "58864a4f2459770fcc257101": 7, | ||||
|             "5a3c16fe86f77452b62de32a": 12, | ||||
|             "5c3df7d588a4501f290594e5": 6, | ||||
|             "64b7bbb74b75259c590fa897": 4, | ||||
|             "56d59d3ad2720bdb418b4577": 2 | ||||
|         }, | ||||
|         "Caliber9x21": { | ||||
|             "5a26ac06c4a282000c5a90a8": 5, | ||||
|             "5a26abfac4a28232980eabff": 3, | ||||
|             "5a269f97c4a282000b151807": 1 | ||||
|         }, | ||||
|         "Caliber9x33R": { | ||||
|             "62330c40bdd19b369e1e53d1": 5, | ||||
|             "62330bfadc5883093563729b": 3, | ||||
|             "62330c18744e5e31df12f516": 1 | ||||
|         }, | ||||
|         "Caliber9x39": { | ||||
|             "6576f96220d53a5b8f3e395e": 7, | ||||
|             "57a0dfb82459774d3078b56c": 5, | ||||
|             "5c0d668f86f7747ccb7f13b2": 1 | ||||
|         }, | ||||
|         "Caliber127x33": { | ||||
|             "66a0d1c87d0d369e270bb9de": 10, | ||||
|             "66a0d1f88486c69fce00fdf6": 1 | ||||
|         } | ||||
|     }, | ||||
|     "pmcAmmo": { | ||||
|         "Caliber1143x23ACP": { | ||||
|             "5ea2a8e200685063ec28c05a": 1, | ||||
|             "5efb0fc6aeb21837e749c801": 8, | ||||
|             "5efb0d4f4bc50b58e81710f3": 40, | ||||
|             "5e81f423763d9f754677bf2e": 25 | ||||
|         }, | ||||
|         "Caliber127x55": { | ||||
|             "5cadf6e5ae921500113bb973": 45 | ||||
|         }, | ||||
|         "Caliber12g": { | ||||
|             "5d6e6806a4b936088465b17e": 10, | ||||
|             "5c0d591486f7744c505b416f": 3, | ||||
|             "5d6e68d1a4b93622fe60e845": 3, | ||||
|             "5d6e6869a4b9361c140bcfde": 2, | ||||
|             "5d6e68b3a4b9361bca7e50b5": 2, | ||||
|             "58820d1224597753c90aeb13": 2, | ||||
|             "5d6e68dea4b9361bcc29e659": 2, | ||||
|             "5d6e6891a4b9361bd473feea": 9, | ||||
|             "5d6e68e6a4b9361c140bcfe0": 15, | ||||
|             "5d6e689ca4b9361bc8618956": 9 | ||||
|         }, | ||||
|         "Caliber20g": { | ||||
|             "5d6e695fa4b936359b35d852": 3, | ||||
|             "5d6e69b9a4b9361bc8618958": 3, | ||||
|             "5a38ebd9c4a282000d722a5b": 5, | ||||
|             "5d6e69c7a4b9360b6c0d54e4": 10, | ||||
| 
 | ||||
|             "5d6e6a5fa4b93614ec501745": 3, | ||||
|             "5d6e6a53a4b9361bd473feec": 3 | ||||
|         }, | ||||
|         "Caliber23x75": { | ||||
|             "5f647f31b6238e5dd066e196": 8, | ||||
|             "5e85a9a6eacf8c039e4e2ac1": 2 | ||||
|         }, | ||||
|         "Caliber366TKM": { | ||||
|             "59e6658b86f77411d949b250": 12, | ||||
|             "59e6542b86f77411dc52a77a": 35, | ||||
|             "59e655cb86f77411dc52a77b": 20 | ||||
|         }, | ||||
|         "Caliber40mmRU": { | ||||
|             "5656eb674bdc2d35148b457c": 1 | ||||
|         }, | ||||
|         "Caliber40x46": { | ||||
|             "5ede4739e0350d05467f73e8": 1, | ||||
|             "5ede47405b097655935d7d16": 1, | ||||
|             "5ede474b0c226a66f5402622": 1, | ||||
|             "5ede475339ee016e8c534742": 1, | ||||
|             "5ede475b549eed7c6d5c18fb": 1, | ||||
|             "5f0c892565703e5c461894e9": 1 | ||||
|         }, | ||||
|         "Caliber46x30": { | ||||
|             "5ba26812d4351e003201fef1": 40, | ||||
|             "5ba26844d4351e00334c9475": 60 | ||||
|         }, | ||||
|         "Caliber545x39": { | ||||
|             "56dff338d2720bbd668b4569": 5, | ||||
|             "56dff4a2d2720bbd668b456a": 7, | ||||
|             "56dff0bed2720bb0668b4567": 10, | ||||
|             "56dff3afd2720bba668b4567": 60, | ||||
|             "56dff2ced2720bb4668b4567": 5, | ||||
|             "56dff061d2720bb5668b4567": 1 | ||||
|         }, | ||||
|         "Caliber556x45NATO": { | ||||
|             "59e6918f86f7746c9f75e849": 10, | ||||
|             "59e68f6f86f7746c9f75e846": 40, | ||||
|             "59e6920f86f77411d82aa167": 50, | ||||
|             "54527a984bdc2d4e668b4567": 30, | ||||
|             "60194943740c5d77f6705eea": 10, | ||||
|             "59e6906286f7746c9f75e847": 5 | ||||
|         }, | ||||
|         "Caliber57x28": { | ||||
|             "5cc86832d7f00c000d3a6e6c": 4, | ||||
|             "5cc80f79e4a949033c7343b2": 11, | ||||
|             "5cc86840d7f00c002412c56c": 21, | ||||
|             "5cc80f8fe4a949033b0224a2": 21, | ||||
|             "5cc80f53e4a949000e1ea4f8": 12, | ||||
|             "5cc80f67e4a949035e43bbba": 4 | ||||
|         }, | ||||
|         "Caliber68x51": { | ||||
|             "6529302b8c26af6326029fb7": 1 | ||||
|         }, | ||||
|         "Caliber762x25TT": { | ||||
|             "573601b42459776410737435": 8, | ||||
|             "5735fdcd2459776445391d61": 12, | ||||
|             "5736026a245977644601dc61": 18, | ||||
|             "573603c924597764442bd9cb": 13, | ||||
|             "573603562459776430731618": 3 | ||||
|         }, | ||||
|         "Caliber762x35": { | ||||
|             "6196365d58ef8c428c287da1": 9, | ||||
|             "6196364158ef8c428c287d9f": 18, | ||||
|             "5fbe3ffdf8b6a877a729ea82": 18 | ||||
|         }, | ||||
|         "Caliber762x39": { | ||||
|             "64b7af5a8532cf95ee0a0dbd": 5, | ||||
|             "59e4d24686f7741776641ac7": 15, | ||||
|             "59e4cf5286f7741778269d8a": 40, | ||||
|             "5656d7c34bdc2d9d198b4587": 45, | ||||
|             "64b7af434b75259c590fa893": 10 | ||||
|         }, | ||||
|         "Caliber762x51": { | ||||
|             "5e023e88277cce2b522ff2b1": 10, | ||||
|             "5e023e6e34d52a55c3304f71": 30, | ||||
|             "5e023e53d4353e3302577c4c": 50, | ||||
|             "58dd3ad986f77403051cba8f": 10 | ||||
|         }, | ||||
|         "Caliber762x54R": { | ||||
|             "64b8f7b5389d7ffd620ccba2": 5, | ||||
|             "64b8f7968532cf95ee0a0dbf": 9, | ||||
|             "5e023cf8186a883be655e54f": 16, | ||||
|             "5887431f2459777e1612938f": 22, | ||||
|             "59e77a2386f7742ee578960a": 10 | ||||
|         }, | ||||
|         "Caliber86x70": { | ||||
|             "5fc382b6d6fa9c00c571bbc3": 90, | ||||
|             "5fc382c1016cce60e8341b20": 5, | ||||
|             "5fc275cf85fd526b824a571a": 5 | ||||
|         }, | ||||
|         "Caliber9x18PM": { | ||||
|             "57371f8d24597761006c6a81": 3, | ||||
|             "57371f2b24597761224311f1": 3, | ||||
|             "57371eb62459776125652ac1": 3, | ||||
|             "57371b192459775a9f58a5e0": 9, | ||||
|             "57371e4124597760ff7b25f1": 13, | ||||
|             "5737201124597760fc4431f1": 21, | ||||
|             "573720e02459776143012541": 14, | ||||
|             "573718ba2459775a75491131": 8 | ||||
|         }, | ||||
|         "Caliber9x19PARA": { | ||||
|             "5efb0e16aeb21837e749c7ff": 7, | ||||
|             "58864a4f2459770fcc257101": 1, | ||||
|             "5a3c16fe86f77452b62de32a": 15, | ||||
|             "5c3df7d588a4501f290594e5": 20, | ||||
|             "64b7bbb74b75259c590fa897": 30, | ||||
|             "56d59d3ad2720bdb418b4577": 55 | ||||
|         }, | ||||
|         "Caliber9x21": { | ||||
|             "5a26ac06c4a282000c5a90a8": 1, | ||||
|             "5a26abfac4a28232980eabff": 20, | ||||
|             "5a269f97c4a282000b151807": 27 | ||||
|         }, | ||||
|         "Caliber9x33R": { | ||||
|             "62330c40bdd19b369e1e53d1": 7, | ||||
|             "62330bfadc5883093563729b": 8, | ||||
|             "62330c18744e5e31df12f516": 4 | ||||
|         }, | ||||
|         "Caliber9x39": { | ||||
|             "6576f96220d53a5b8f3e395e": 10, | ||||
|             "57a0dfb82459774d3078b56c": 50, | ||||
|             "5c0d668f86f7747ccb7f13b2": 40 | ||||
|         }, | ||||
|         "Caliber127x33": { | ||||
|             "66a0d1c87d0d369e270bb9de": 30, | ||||
|             "66a0d1f88486c69fce00fdf6": 50 | ||||
|         } | ||||
|     }, | ||||
|     "bossAmmo": { | ||||
|         "Caliber1143x23ACP": { | ||||
|             "5ea2a8e200685063ec28c05a": 4, | ||||
|             "5efb0fc6aeb21837e749c801": 1, | ||||
|             "5efb0d4f4bc50b58e81710f3": 10, | ||||
|             "5e81f423763d9f754677bf2e": 18, | ||||
|             "5efb0cabfb3e451d70735af5": 10 | ||||
|         }, | ||||
|         "Caliber127x55": { | ||||
|             "5cadf6e5ae921500113bb973": 3, | ||||
|             "5cadf6ddae9215051e1c23b2": 12, | ||||
|             "5cadf6eeae921500134b2799": 8 | ||||
|         }, | ||||
|         "Caliber12g": { | ||||
|             "5d6e6806a4b936088465b17e": 7, | ||||
|             "64b8ee384b75259c590fa89b": 4, | ||||
|             "5d6e6911a4b9361bd5780d52": 3, | ||||
|             "5c0d591486f7744c505b416f": 5, | ||||
|             "5d6e6891a4b9361bd473feea": 2, | ||||
|             "5d6e68e6a4b9361c140bcfe0": 6, | ||||
|             "5d6e689ca4b9361bc8618956": 8, | ||||
|             "5d6e68c4a4b9361b93413f79": 8, | ||||
|             "5d6e68a8a4b9360b6c0d54e2": 3 | ||||
|         }, | ||||
|         "Caliber20g": { | ||||
|             "5d6e69c7a4b9360b6c0d54e4": 1, | ||||
|             "5d6e6a53a4b9361bd473feec": 4, | ||||
|             "5d6e6a05a4b93618084f58d0": 5, | ||||
|             "5d6e6a42a4b9364f07165f52": 5 | ||||
|         }, | ||||
|         "Caliber23x75": { | ||||
|             "5f647f31b6238e5dd066e196": 2, | ||||
|             "5e85a9a6eacf8c039e4e2ac1": 4, | ||||
|             "5e85aa1a988a8701445df1f5": 4 | ||||
|         }, | ||||
|         "Caliber366TKM": { | ||||
|             "59e6658b86f77411d949b250": 1, | ||||
|             "59e6542b86f77411dc52a77a": 2, | ||||
|             "59e655cb86f77411dc52a77b": 10, | ||||
|             "5f0596629e22f464da6bbdd9": 8 | ||||
|         }, | ||||
|         "Caliber40mmRU": { | ||||
|             "5656eb674bdc2d35148b457c": 1 | ||||
|         }, | ||||
|         "Caliber40x46": { | ||||
|             "5ede4739e0350d05467f73e8": 1, | ||||
|             "5ede47405b097655935d7d16": 1, | ||||
|             "5ede474b0c226a66f5402622": 1, | ||||
|             "5ede475339ee016e8c534742": 1, | ||||
|             "5ede475b549eed7c6d5c18fb": 1, | ||||
|             "5f0c892565703e5c461894e9": 1 | ||||
|         }, | ||||
|         "Caliber46x30": { | ||||
|             "5ba26812d4351e003201fef1": 2, | ||||
|             "5ba26844d4351e00334c9475": 4, | ||||
|             "5ba2678ad4351e44f824b344": 15, | ||||
|             "64b6979341772715af0f9c39": 15, | ||||
|             "5ba26835d4351e0035628ff5": 8 | ||||
|         }, | ||||
|         "Caliber545x39": { | ||||
|             "56dff3afd2720bba668b4567": 6, | ||||
|             "56dff2ced2720bb4668b4567": 12, | ||||
|             "56dff061d2720bb5668b4567": 20, | ||||
|             "61962b617c6c7b169525f168": 12, | ||||
|             "56dfef82d2720bbd668b4567": 9, | ||||
|             "56dff026d2720bb8668b4567": 8, | ||||
|             "5c0d5e4486f77478390952fe": 4 | ||||
|         }, | ||||
|         "Caliber556x45NATO": { | ||||
|             "5c0d5ae286f7741e46554302": 1, | ||||
|             "54527a984bdc2d4e668b4567": 7, | ||||
|             "60194943740c5d77f6705eea": 20, | ||||
|             "59e6906286f7746c9f75e847": 26, | ||||
|             "54527ac44bdc2d36668b4567": 30, | ||||
|             "59e690b686f7746c9f75e848": 7, | ||||
|             "601949593ae8f707c4608daa": 5 | ||||
|         }, | ||||
|         "Caliber57x28": { | ||||
|             "5cc80f8fe4a949033b0224a2": 5, | ||||
|             "5cc80f53e4a949000e1ea4f8": 21, | ||||
|             "5cc80f67e4a949035e43bbba": 15, | ||||
|             "5cc80f38e4a949001152b560": 12 | ||||
|         }, | ||||
|         "Caliber68x51": { | ||||
|             "6529302b8c26af6326029fb7": 10, | ||||
|             "6529243824cbe3c74a05e5c1": 5 | ||||
|         }, | ||||
|         "Caliber762x25TT": { | ||||
|             "5736026a245977644601dc61": 5, | ||||
|             "573603c924597764442bd9cb": 10, | ||||
|             "573603562459776430731618": 10 | ||||
|         }, | ||||
|         "Caliber762x35": { | ||||
|             "6196365d58ef8c428c287da1": 7, | ||||
|             "5fbe3ffdf8b6a877a729ea82": 6, | ||||
|             "619636be6db0f2477964e710": 23, | ||||
|             "64b8725c4b75259c590fa899": 20, | ||||
|             "5fd20ff893a8961fc660a954": 9 | ||||
|         }, | ||||
|         "Caliber762x39": { | ||||
|             "59e4cf5286f7741778269d8a": 4, | ||||
|             "5656d7c34bdc2d9d198b4587": 28, | ||||
|             "64b7af434b75259c590fa893": 33, | ||||
|             "59e0d99486f7744a32234762": 20, | ||||
|             "601aa3d2b2bcb34913271e6d": 12 | ||||
|         }, | ||||
|         "Caliber762x51": { | ||||
|             "5e023e53d4353e3302577c4c": 6, | ||||
|             "58dd3ad986f77403051cba8f": 27, | ||||
|             "5a608bf24f39f98ffc77720e": 19, | ||||
|             "5a6086ea4f39f99cd479502f": 9, | ||||
|             "5efb0c1bd79ff02a1f5e68d9": 2 | ||||
|         }, | ||||
|         "Caliber762x54R": { | ||||
|             "5e023cf8186a883be655e54f": 3, | ||||
|             "5887431f2459777e1612938f": 20, | ||||
|             "59e77a2386f7742ee578960a": 25, | ||||
|             "5e023d34e8a400319a28ed44": 22, | ||||
|             "560d61e84bdc2da74d8b4571": 15, | ||||
|             "5e023d48186a883be655e551": 10 | ||||
|         }, | ||||
|         "Caliber86x70": { | ||||
|             "5fc382b6d6fa9c00c571bbc3": 5, | ||||
|             "5fc382c1016cce60e8341b20": 8, | ||||
|             "5fc275cf85fd526b824a571a": 8, | ||||
|             "5fc382a9d724d907e2077dab": 5 | ||||
|         }, | ||||
|         "Caliber9x18PM": { | ||||
|             "57371e4124597760ff7b25f1": 3, | ||||
|             "5737201124597760fc4431f1": 5, | ||||
|             "573720e02459776143012541": 12, | ||||
|             "573718ba2459775a75491131": 18, | ||||
|             "57371aab2459775a77142f22": 12, | ||||
|             "573719df2459775a626ccbc2": 10 | ||||
|         }, | ||||
|         "Caliber9x19PARA": { | ||||
|             "5c0d56a986f774449d5de529": 9, | ||||
|             "5efb0e16aeb21837e749c7ff": 5, | ||||
|             "5a3c16fe86f77452b62de32a": 4, | ||||
|             "56d59d3ad2720bdb418b4577": 18, | ||||
|             "5c925fa22e221601da359b7b": 22, | ||||
|             "5efb0da7a29a85116f6ea05f": 9 | ||||
|         }, | ||||
|         "Caliber9x21": { | ||||
|             "5a269f97c4a282000b151807": 8, | ||||
|             "6576f93989f0062e741ba952": 18, | ||||
|             "5a26ac0ec4a28200741e1e18": 18, | ||||
|             "6576f4708ca9c4381d16cd9d": 8 | ||||
|         }, | ||||
|         "Caliber9x33R": { | ||||
|             "62330c18744e5e31df12f516": 9, | ||||
|             "62330b3ed4dc74626d570b95": 6 | ||||
|         }, | ||||
|         "Caliber9x39": { | ||||
|             "5c0d668f86f7747ccb7f13b2": 9, | ||||
|             "61962d879bb3d20b0946d385": 25, | ||||
|             "57a0e5022459774d1673f889": 25, | ||||
|             "5c0d688c86f77413ae3407b2": 12 | ||||
|         }, | ||||
|         "Caliber127x33": { | ||||
|             "66a0d1c87d0d369e270bb9de": 3, | ||||
|             "66a0d1f88486c69fce00fdf6": 30, | ||||
|             "66a0d1e0ed648d72fe064d06": 25,  | ||||
|             "668fe62ac62660a5d8071446": 12 | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,430 @@ | |||
| { | ||||
|     "pmcUSEC": { | ||||
|         "appearance": { | ||||
|             "body": { | ||||
|                 "5cde95d97d6c8b647a3769b0": 5, | ||||
|                 "66546f823b51a4d21e0d17d7": 1, | ||||
|                 "5d1f56a686f7744bce0ee9eb": 2, | ||||
|                 "5d1f56c686f7744bcd13459c": 3, | ||||
|                 "637b945722e2a933ed0e33c8": 3, | ||||
|                 "6571cb0923aa6d72760a7f8f": 3, | ||||
|                 "5fd3e9f71b735718c25cd9f8": 3, | ||||
|                 "642d9bbf6c06444bf7033855": 3 | ||||
|             }, | ||||
|             "feet": { | ||||
|                 "5cde95ef7d6c8b04713c4f2d": 5, | ||||
|                 "5d1f58ed86f7744bcb0acd1c": 2, | ||||
|                 "5d1f590486f7744bcd13459e": 3, | ||||
|                 "642d4d8eb6b75d4c89077cf9": 3, | ||||
|                 "6033a3fee29c9f6c9b14e74e": 3 | ||||
|             }, | ||||
|             "hands": { | ||||
|                 "5cde95fa7d6c8b04737c2d13": 1 | ||||
|             }, | ||||
|             "head": { | ||||
|                 "5cde96047d6c8b20b577f016": 1, | ||||
|                 "5fdb4139e4ed5b5ea251e4ed": 1, | ||||
|                 "5fdb5950f5264a66150d1c6e": 1, | ||||
|                 "60a6aa8fd559ae040d0d951f": 1, | ||||
|                 "619f9e338858a474c8685cc9": 1, | ||||
|                 "62aca6a1310e67685a2fc2e7": 1, | ||||
|                 "6574aabee0423b9ebe0c79cf": 1 | ||||
|             } | ||||
|         } | ||||
|     }, | ||||
|     "pmcBEAR": { | ||||
|         "appearance": { | ||||
|             "body": { | ||||
|                 "5cc0858d14c02e000c6bea66": 5, | ||||
|                 "66546f823b51a4d21e0d17d7": 1, | ||||
|                 "5d1f565786f7743f8362bcd5": 2, | ||||
|                 "5fce3e0cfe40296c1d5fd782": 3, | ||||
|                 "6377266693a3b4967208e42b": 3, | ||||
|                 "5d1f564b86f7744bcb0acd16": 3, | ||||
|                 "6295e698e9de5e7b3751c47a": 3, | ||||
|                 "642e8ae07e17c882400c4f87": 3, | ||||
|                 "5d1f568486f7744bca3f0b98": 3 | ||||
|             }, | ||||
|             "feet": { | ||||
|                 "5cc085bb14c02e000e67a5c5": 5, | ||||
|                 "5d1f58bd86f7744bce0ee9ef": 2, | ||||
|                 "6377315993a3b4967208e437": 3, | ||||
|                 "5d1f588e86f7744bcc048753": 3, | ||||
|                 "65707a89f5a6f1412f0c5f7b": 3, | ||||
|                 "642ed40af5bdf1c04e01952e": 3, | ||||
|                 "5fce3e965a9f8c40685693bc": 3 | ||||
|             }, | ||||
|             "hands": { | ||||
|                 "5cc0876314c02e000c6bea6b": 1 | ||||
|             }, | ||||
|             "head": { | ||||
|                 "5cc084dd14c02e000b0550a3": 1, | ||||
|                 "5fdb50bb2b730a787b3f78cf": 1, | ||||
|                 "5fdb7571e4ed5b5ea251e529": 1, | ||||
|                 "60a6aaad42fd2735e4589978": 1, | ||||
|                 "619f94f5b90286142b59d45f": 1, | ||||
|                 "62a9e7d15ea3b87d6f642a28": 1, | ||||
|                 "6574aa9a1b144de18c0fba45": 1 | ||||
|             } | ||||
|         } | ||||
|     }, | ||||
|     "springEarly": { | ||||
|         "pmcUSEC": { | ||||
|             "appearance": { | ||||
|                 "body": { | ||||
|                     "5d1f56c686f7744bcd13459c": 1, | ||||
|                     "5fd3e9f71b735718c25cd9f8": 1, | ||||
|                     "66043728333907134309d647": 1, | ||||
|                     "66acbe49dc61999a6a03d4d6": 1, | ||||
|                     "660437e57502eca33a08caca": 1, | ||||
|                     "5d1f56f186f7744bcb0acd1a": 1, | ||||
|                     "5d1f56ff86f7743f8362bcd7": 1, | ||||
|                     "5d1f56a686f7744bce0ee9eb": 2, | ||||
|                     "5e9da17386f774054b6f79a3": 2, | ||||
|                     "5e4bb35286f77406a511c9bc": 2, | ||||
|                     "5d1f56e486f7744bce0ee9ed": 2 | ||||
|                 }, | ||||
|                 "feet": { | ||||
|                     "642d4d8eb6b75d4c89077cf9": 1, | ||||
|                     "5fcf940bce1ba36a513bb9cc": 1, | ||||
|                     "66acc8f719271bd6d00dec0b": 1, | ||||
|                     "6295e944e9de5e7b3751c4da": 1, | ||||
|                     "5d1f592286f7743f8362bcdb": 1, | ||||
|                     "5e4bb3b586f77406812bd579": 1, | ||||
|                     "5d1f590486f7744bcd13459e": 3, | ||||
|                     "5d1f58ed86f7744bcb0acd1c": 3 | ||||
|                 }, | ||||
|                 "hands": { | ||||
|                     "5cde95fa7d6c8b04737c2d13": 1 | ||||
|                 }, | ||||
|                 "head": { | ||||
|                     "5cde96047d6c8b20b577f016": 1, | ||||
|                     "5fdb4139e4ed5b5ea251e4ed": 1, | ||||
|                     "5fdb5950f5264a66150d1c6e": 1, | ||||
|                     "60a6aa8fd559ae040d0d951f": 1, | ||||
|                     "619f9e338858a474c8685cc9": 1, | ||||
|                     "62aca6a1310e67685a2fc2e7": 1, | ||||
|                     "6574aabee0423b9ebe0c79cf": 1 | ||||
|                 } | ||||
|             } | ||||
|         }, | ||||
|         "pmcBEAR": { | ||||
|             "appearance": { | ||||
|                 "body": { | ||||
|                     "657058fddf9b3231400e9188": 1, | ||||
|                     "6033a31e9ec839204e6a2f3e": 1, | ||||
|                     "5d1f567786f7744bcc04874f": 1, | ||||
|                     "5e9d9fa986f774054d6b89f2": 1, | ||||
|                     "5f5e401747344c2e4f6c42c5": 1, | ||||
|                     "642e8ae07e17c882400c4f87": 2, | ||||
|                     "5d1f568486f7744bca3f0b98": 2, | ||||
|                     "66acec1dc94f4bf5bc063a16": 2, | ||||
|                     "5e4bb31586f7740695730568": 2 | ||||
|                 }, | ||||
|                 "feet": { | ||||
|                     "5d1f58bd86f7744bce0ee9ef": 1, | ||||
|                     "6377315993a3b4967208e437": 1, | ||||
|                     "66043cf87502eca33a08cad2": 1, | ||||
|                     "5d1f58cb86f7744bca3f0b9a": 1, | ||||
|                     "5d1f58a086f7743f8362bcd9": 1, | ||||
|                     "617be9e4e02b3b3fa50fa8f2": 1, | ||||
|                     "5f5e40400bc58666c37e7819": 1, | ||||
|                     "66acebd4ede86671bb09584b": 3, | ||||
|                     "5d1f58ab86f7743014162042": 3 | ||||
|                 }, | ||||
|                 "hands": { | ||||
|                     "5cc0876314c02e000c6bea6b": 1 | ||||
|                 }, | ||||
|                 "head": { | ||||
|                     "5cc084dd14c02e000b0550a3": 1, | ||||
|                     "5fdb50bb2b730a787b3f78cf": 1, | ||||
|                     "5fdb7571e4ed5b5ea251e529": 1, | ||||
|                     "60a6aaad42fd2735e4589978": 1, | ||||
|                     "619f94f5b90286142b59d45f": 1, | ||||
|                     "62a9e7d15ea3b87d6f642a28": 1, | ||||
|                     "6574aa9a1b144de18c0fba45": 1 | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     }, | ||||
|     "spring": { | ||||
|         "pmcUSEC": { | ||||
|             "appearance": { | ||||
|                 "body": { | ||||
|                     "5cde95d97d6c8b647a3769b0": 1, | ||||
|                     "5fd3e9f71b735718c25cd9f8": 1, | ||||
|                     "66043728333907134309d647": 1, | ||||
|                     "5d4da0cb86f77450fe0a6629": 1, | ||||
|                     "5d1f56f186f7744bcb0acd1a": 1, | ||||
|                     "5f5e4075df4f3100376a8138": 1 | ||||
|                 }, | ||||
|                 "feet": { | ||||
|                     "5cde95ef7d6c8b04713c4f2d": 1, | ||||
|                     "6033a3fee29c9f6c9b14e74e": 1, | ||||
|                     "660436487502eca33a08cac8": 1, | ||||
|                     "6571cad4c8673f00290f5657": 1, | ||||
|                     "66acc8f719271bd6d00dec0b": 1, | ||||
|                     "5d1f592286f7743f8362bcdb": 1, | ||||
|                     "642d6941ff5ecad7810a8a61": 1, | ||||
|                     "5e9dcadd86f7743e20652f23": 1 | ||||
|                 }, | ||||
|                 "hands": { | ||||
|                     "5cde95fa7d6c8b04737c2d13": 1 | ||||
|                 }, | ||||
|                 "head": { | ||||
|                     "5cde96047d6c8b20b577f016": 1, | ||||
|                     "5fdb4139e4ed5b5ea251e4ed": 1, | ||||
|                     "5fdb5950f5264a66150d1c6e": 1, | ||||
|                     "60a6aa8fd559ae040d0d951f": 1, | ||||
|                     "619f9e338858a474c8685cc9": 1, | ||||
|                     "62aca6a1310e67685a2fc2e7": 1, | ||||
|                     "6574aabee0423b9ebe0c79cf": 1 | ||||
|                 } | ||||
|             } | ||||
|         }, | ||||
|         "pmcBEAR": { | ||||
|             "appearance": { | ||||
|                 "body": { | ||||
|                     "5cc0858d14c02e000c6bea66": 1, | ||||
|                     "5d1f564b86f7744bcb0acd16": 1, | ||||
|                     "6295e698e9de5e7b3751c47a": 1, | ||||
|                     "6033a31e9ec839204e6a2f3e": 1, | ||||
|                     "5fce3e47fe40296c1d5fd784": 1, | ||||
|                     "617bca4b4013b06b0b78df2a": 1, | ||||
|                     "5df89f1f86f77412631087ea": 1 | ||||
|                 }, | ||||
|                 "feet": { | ||||
|                     "5cc085bb14c02e000e67a5c5": 1, | ||||
|                     "5d1f588e86f7744bcc048753": 1, | ||||
|                     "66043cf87502eca33a08cad2": 1, | ||||
|                     "6033a3d8ed2e0509b15f9031": 1, | ||||
|                     "642e71620a69698d1b049f0a": 1, | ||||
|                     "617be9e4e02b3b3fa50fa8f2": 1, | ||||
|                     "642eea6f881906a7fe086841": 1, | ||||
|                     "5df89f8f86f77412672a1e38": 1, | ||||
|                     "5e9dc97c86f774054c19ac9a": 1, | ||||
|                     "5e4bb39386f774067f79de05": 1 | ||||
|                 }, | ||||
|                 "hands": { | ||||
|                     "5cc0876314c02e000c6bea6b": 1 | ||||
|                 }, | ||||
|                 "head": { | ||||
|                     "5cc084dd14c02e000b0550a3": 1, | ||||
|                     "5fdb50bb2b730a787b3f78cf": 1, | ||||
|                     "5fdb7571e4ed5b5ea251e529": 1, | ||||
|                     "60a6aaad42fd2735e4589978": 1, | ||||
|                     "619f94f5b90286142b59d45f": 1, | ||||
|                     "62a9e7d15ea3b87d6f642a28": 1, | ||||
|                     "6574aa9a1b144de18c0fba45": 1 | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     }, | ||||
|     "summer": { | ||||
|         "pmcUSEC": { | ||||
|             "appearance": { | ||||
|                 "body": { | ||||
|                     "5cde95d97d6c8b647a3769b0": 1, | ||||
|                     "5d1f56c686f7744bcd13459c": 1, | ||||
|                     "5fd3e9f71b735718c25cd9f8": 1, | ||||
|                     "66043728333907134309d647": 1, | ||||
|                     "5d4da0cb86f77450fe0a6629": 1, | ||||
|                     "66acbe49dc61999a6a03d4d6": 1, | ||||
|                     "64ef3efdb63b74469b6c1499": 1, | ||||
|                     "642c18b8a6a0660b560fb31c": 1, | ||||
|                     "5d1f56f186f7744bcb0acd1a": 1, | ||||
|                     "5f5e4075df4f3100376a8138": 1 | ||||
|                 }, | ||||
|                 "feet": { | ||||
|                     "5cde95ef7d6c8b04713c4f2d": 1, | ||||
|                     "6033a3fee29c9f6c9b14e74e": 1, | ||||
|                     "660436487502eca33a08cac8": 1, | ||||
|                     "6571cad4c8673f00290f5657": 1, | ||||
|                     "66acc8f719271bd6d00dec0b": 1, | ||||
|                     "5d1f593286f7743014162044": 1, | ||||
|                     "5d1f592286f7743f8362bcdb": 1, | ||||
|                     "642d6941ff5ecad7810a8a61": 1, | ||||
|                     "5e9dcadd86f7743e20652f23": 1 | ||||
|                 }, | ||||
|                 "hands": { | ||||
|                     "5cde95fa7d6c8b04737c2d13": 1 | ||||
|                 }, | ||||
|                 "head": { | ||||
|                     "5cde96047d6c8b20b577f016": 1, | ||||
|                     "5fdb4139e4ed5b5ea251e4ed": 1, | ||||
|                     "5fdb5950f5264a66150d1c6e": 1, | ||||
|                     "60a6aa8fd559ae040d0d951f": 1, | ||||
|                     "619f9e338858a474c8685cc9": 1, | ||||
|                     "62aca6a1310e67685a2fc2e7": 1, | ||||
|                     "6574aabee0423b9ebe0c79cf": 1 | ||||
|                 } | ||||
|             } | ||||
|         }, | ||||
|         "pmcBEAR": { | ||||
|             "appearance": { | ||||
|                 "body": { | ||||
|                     "5cc0858d14c02e000c6bea66": 1, | ||||
|                     "5d1f564b86f7744bcb0acd16": 1, | ||||
|                     "6295e698e9de5e7b3751c47a": 1, | ||||
|                     "6033a31e9ec839204e6a2f3e": 1, | ||||
|                     "5fce3e47fe40296c1d5fd784": 1, | ||||
|                     "617bca4b4013b06b0b78df2a": 1, | ||||
|                     "64ef3efdb63b74469b6c1499": 1, | ||||
|                     "5df89f1f86f77412631087ea": 1, | ||||
|                     "5e9d9fa986f774054d6b89f2": 1 | ||||
|                 }, | ||||
|                 "feet": { | ||||
|                     "5cc085bb14c02e000e67a5c5": 1, | ||||
|                     "5d1f588e86f7744bcc048753": 1, | ||||
|                     "66043cf87502eca33a08cad2": 1, | ||||
|                     "6033a3d8ed2e0509b15f9031": 1, | ||||
|                     "642e71620a69698d1b049f0a": 1, | ||||
|                     "617be9e4e02b3b3fa50fa8f2": 1, | ||||
|                     "642eea6f881906a7fe086841": 1, | ||||
|                     "5df89f8f86f77412672a1e38": 1, | ||||
|                     "5e9dc97c86f774054c19ac9a": 1, | ||||
|                     "5e4bb39386f774067f79de05": 1 | ||||
|                 }, | ||||
|                 "hands": { | ||||
|                     "5cc0876314c02e000c6bea6b": 1 | ||||
|                 }, | ||||
|                 "head": { | ||||
|                     "5cc084dd14c02e000b0550a3": 1, | ||||
|                     "5fdb50bb2b730a787b3f78cf": 1, | ||||
|                     "5fdb7571e4ed5b5ea251e529": 1, | ||||
|                     "60a6aaad42fd2735e4589978": 1, | ||||
|                     "619f94f5b90286142b59d45f": 1, | ||||
|                     "62a9e7d15ea3b87d6f642a28": 1, | ||||
|                     "6574aa9a1b144de18c0fba45": 1 | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     }, | ||||
|     "autumn": { | ||||
|         "pmcUSEC": { | ||||
|             "appearance": { | ||||
|                 "body": { | ||||
|                     "5d1f56c686f7744bcd13459c": 1, | ||||
|                     "637b945722e2a933ed0e33c8": 1, | ||||
|                     "6571cb0923aa6d72760a7f8f": 1, | ||||
|                     "6033a35f80ae5e2f970ba6bb": 1, | ||||
|                     "5d1f56e486f7744bce0ee9ed": 1, | ||||
|                     "66acbe49dc61999a6a03d4d6": 1, | ||||
|                     "660437e57502eca33a08caca": 1, | ||||
|                     "64ef3efdb63b74469b6c1499": 1, | ||||
|                     "5d1f56ff86f7743f8362bcd7": 1 | ||||
|                 }, | ||||
|                 "feet": { | ||||
|                     "642d4d8eb6b75d4c89077cf9": 1, | ||||
|                     "5fcf940bce1ba36a513bb9cc": 1, | ||||
|                     "637ba17aa10a96c2b605dbc2": 1, | ||||
|                     "6295e944e9de5e7b3751c4da": 1, | ||||
|                     "5e4bb3b586f77406812bd579": 1, | ||||
|                     "5f5e40a06760b4138443b341": 1 | ||||
|                 }, | ||||
|                 "hands": { | ||||
|                     "5cde95fa7d6c8b04737c2d13": 1 | ||||
|                 }, | ||||
|                 "head": { | ||||
|                     "5cde96047d6c8b20b577f016": 1, | ||||
|                     "5fdb4139e4ed5b5ea251e4ed": 1, | ||||
|                     "5fdb5950f5264a66150d1c6e": 1, | ||||
|                     "60a6aa8fd559ae040d0d951f": 1, | ||||
|                     "619f9e338858a474c8685cc9": 1, | ||||
|                     "62aca6a1310e67685a2fc2e7": 1, | ||||
|                     "6574aabee0423b9ebe0c79cf": 1 | ||||
|                 } | ||||
|             } | ||||
|         }, | ||||
|         "pmcBEAR": { | ||||
|             "appearance": { | ||||
|                 "body": { | ||||
|                     "6377266693a3b4967208e42b": 1, | ||||
|                     "5d1f568486f7744bca3f0b98": 1, | ||||
|                     "657058fddf9b3231400e9188": 1, | ||||
|                     "642ed297ac11c9eaf10d87e8": 1, | ||||
|                     "5d1f567786f7744bcc04874f": 1, | ||||
|                     "64ef3efdb63b74469b6c1499": 1, | ||||
|                     "6430119aac11c9eaf10d881b": 1, | ||||
|                     "5f5e401747344c2e4f6c42c5": 1 | ||||
|                 }, | ||||
|                 "feet": { | ||||
|                     "5d1f58bd86f7744bce0ee9ef": 1, | ||||
|                     "6377315993a3b4967208e437": 1, | ||||
|                     "642ed40af5bdf1c04e01952e": 1, | ||||
|                     "6295e63de08ed747e64ae991": 1, | ||||
|                     "5d1f58a086f7743f8362bcd9": 1, | ||||
|                     "66043d7ac8949a435906e434": 1, | ||||
|                     "5d1f58ab86f7743014162042": 1, | ||||
|                     "5f5e40400bc58666c37e7819": 1 | ||||
|                 }, | ||||
|                 "hands": { | ||||
|                     "5cc0876314c02e000c6bea6b": 1 | ||||
|                 }, | ||||
|                 "head": { | ||||
|                     "5cc084dd14c02e000b0550a3": 1, | ||||
|                     "5fdb50bb2b730a787b3f78cf": 1, | ||||
|                     "5fdb7571e4ed5b5ea251e529": 1, | ||||
|                     "60a6aaad42fd2735e4589978": 1, | ||||
|                     "619f94f5b90286142b59d45f": 1, | ||||
|                     "62a9e7d15ea3b87d6f642a28": 1, | ||||
|                     "6574aa9a1b144de18c0fba45": 1 | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     }, | ||||
|     "winter": { | ||||
|         "pmcUSEC": { | ||||
|             "appearance": { | ||||
|                 "body": { | ||||
|                     "5d1f56a686f7744bce0ee9eb": 1, | ||||
|                     "5e9da17386f774054b6f79a3": 1, | ||||
|                     "5e4bb35286f77406a511c9bc": 1, | ||||
|                     "5d1f56e486f7744bce0ee9ed": 1 | ||||
|                 }, | ||||
|                 "feet": { | ||||
|                     "5d1f590486f7744bcd13459e": 1, | ||||
|                     "5d1f58ed86f7744bcb0acd1c": 1 | ||||
|                 }, | ||||
|                 "hands": { | ||||
|                     "5cde95fa7d6c8b04737c2d13": 1 | ||||
|                 }, | ||||
|                 "head": { | ||||
|                     "5cde96047d6c8b20b577f016": 1, | ||||
|                     "5fdb4139e4ed5b5ea251e4ed": 1, | ||||
|                     "5fdb5950f5264a66150d1c6e": 1, | ||||
|                     "60a6aa8fd559ae040d0d951f": 1, | ||||
|                     "619f9e338858a474c8685cc9": 1, | ||||
|                     "62aca6a1310e67685a2fc2e7": 1, | ||||
|                     "6574aabee0423b9ebe0c79cf": 1 | ||||
|                 } | ||||
|             } | ||||
|         }, | ||||
|         "pmcBEAR": { | ||||
|             "appearance": { | ||||
|                 "body": { | ||||
|                     "642e8ae07e17c882400c4f87": 1, | ||||
|                     "5d1f568486f7744bca3f0b98": 1, | ||||
|                     "66acec1dc94f4bf5bc063a16": 1, | ||||
|                     "5e4bb31586f7740695730568": 1 | ||||
|                 }, | ||||
|                 "feet": { | ||||
|                     "66acebd4ede86671bb09584b": 1, | ||||
|                     "5d1f58ab86f7743014162042": 1 | ||||
|                 }, | ||||
|                 "hands": { | ||||
|                     "5cc0876314c02e000c6bea6b": 1 | ||||
|                 }, | ||||
|                 "head": { | ||||
|                     "5cc084dd14c02e000b0550a3": 1, | ||||
|                     "5fdb50bb2b730a787b3f78cf": 1, | ||||
|                     "5fdb7571e4ed5b5ea251e529": 1, | ||||
|                     "60a6aaad42fd2735e4589978": 1, | ||||
|                     "619f94f5b90286142b59d45f": 1, | ||||
|                     "62a9e7d15ea3b87d6f642a28": 1, | ||||
|                     "6574aa9a1b144de18c0fba45": 1 | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							|  | @ -0,0 +1,464 @@ | |||
| {     | ||||
|     "scavAmmo": { | ||||
|         "Caliber1143x23ACP": { | ||||
|             "5efb0fc6aeb21837e749c801": 1, | ||||
|             "5efb0d4f4bc50b58e81710f3": 3 | ||||
|         }, | ||||
|         "Caliber127x55": { | ||||
|             "5cadf6e5ae921500113bb973": 1 | ||||
|         }, | ||||
|         "Caliber12g": { | ||||
|             "5d6e6772a4b936088465b17c": 2, | ||||
|             "5d6e6806a4b936088465b17e": 2, | ||||
|             "5d6e67fba4b9361bc73bc779": 2, | ||||
|             "560d5e524bdc2d25448b4571": 2, | ||||
|             "5d6e6869a4b9361c140bcfde": 1, | ||||
|             "5d6e68b3a4b9361bca7e50b5": 1, | ||||
|             "58820d1224597753c90aeb13": 1, | ||||
|             "5d6e68dea4b9361bcc29e659": 1, | ||||
|             "5d6e6891a4b9361bd473feea": 1, | ||||
|             "5d6e68e6a4b9361c140bcfe0": 1, | ||||
|             "5d6e689ca4b9361bc8618956": 1 | ||||
|         }, | ||||
|         "Caliber20g": { | ||||
|             "5d6e695fa4b936359b35d852": 2, | ||||
|             "5d6e69b9a4b9361bc8618958": 2, | ||||
|             "5a38ebd9c4a282000d722a5b": 2, | ||||
|             "5d6e69c7a4b9360b6c0d54e4": 1, | ||||
|             "5d6e6a53a4b9361bd473feec": 1 | ||||
|         }, | ||||
|         "Caliber23x75": { | ||||
|             "5f647f31b6238e5dd066e196": 3, | ||||
|             "5e85a9a6eacf8c039e4e2ac1": 1 | ||||
|         }, | ||||
|         "Caliber366TKM": { | ||||
|             "59e6658b86f77411d949b250": 3, | ||||
|             "59e6542b86f77411dc52a77a": 1 | ||||
|         }, | ||||
|         "Caliber40mmRU": { | ||||
|             "5656eb674bdc2d35148b457c": 1 | ||||
|         }, | ||||
|         "Caliber40x46": { | ||||
|             "5ede4739e0350d05467f73e8": 1, | ||||
|             "5ede47405b097655935d7d16": 1, | ||||
|             "5ede474b0c226a66f5402622": 1, | ||||
|             "5ede475339ee016e8c534742": 1, | ||||
|             "5ede475b549eed7c6d5c18fb": 1, | ||||
|             "5f0c892565703e5c461894e9": 1 | ||||
|         }, | ||||
|         "Caliber46x30": { | ||||
|             "5ba26812d4351e003201fef1": 3, | ||||
|             "5ba26844d4351e00334c9475": 1 | ||||
|         }, | ||||
|         "Caliber545x39": { | ||||
|             "56dff216d2720bbd668b4568": 1, | ||||
|             "56dff338d2720bbd668b4569": 4, | ||||
|             "56dff421d2720b5f5a8b4567": 4, | ||||
|             "56dff4ecd2720b5f5a8b4568": 2, | ||||
|             "56dff4a2d2720bbd668b456a": 4, | ||||
|             "56dff0bed2720bb0668b4567": 3, | ||||
|             "56dff3afd2720bba668b4567": 1 | ||||
|         }, | ||||
|         "Caliber556x45NATO": { | ||||
|             "59e6927d86f77411da468256": 2, | ||||
|             "59e6918f86f7746c9f75e849": 2, | ||||
|             "59e68f6f86f7746c9f75e846": 4, | ||||
|             "59e6920f86f77411d82aa167": 5, | ||||
|             "54527a984bdc2d4e668b4567": 1 | ||||
|         }, | ||||
|         "Caliber57x28": { | ||||
|             "5cc86832d7f00c000d3a6e6c": 2, | ||||
|             "5cc80f79e4a949033c7343b2": 3, | ||||
|             "5cc86840d7f00c002412c56c": 3, | ||||
|             "5cc80f8fe4a949033b0224a2": 1, | ||||
|             "5cc80f53e4a949000e1ea4f8": 1 | ||||
|         }, | ||||
|         "Caliber68x51": { | ||||
|             "6529302b8c26af6326029fb7": 1 | ||||
|         }, | ||||
|         "Caliber762x25TT": { | ||||
|             "573602322459776445391df1": 2, | ||||
|             "573601b42459776410737435": 2, | ||||
|             "5735fdcd2459776445391d61": 1, | ||||
|             "5736026a245977644601dc61": 1 | ||||
|         }, | ||||
|         "Caliber762x35": { | ||||
|             "6196365d58ef8c428c287da1": 1, | ||||
|             "6196364158ef8c428c287d9f": 6, | ||||
|             "5fbe3ffdf8b6a877a729ea82": 3 | ||||
|         }, | ||||
|         "Caliber762x39": { | ||||
|             "59e4d3d286f774176a36250a": 2, | ||||
|             "64b7af734b75259c590fa895": 2, | ||||
|             "64b7af5a8532cf95ee0a0dbd": 6, | ||||
|             "59e4d24686f7741776641ac7": 4, | ||||
|             "59e4cf5286f7741778269d8a": 2, | ||||
|             "5656d7c34bdc2d9d198b4587": 1 | ||||
|         }, | ||||
|         "Caliber762x51": { | ||||
|             "5e023e88277cce2b522ff2b1": 2, | ||||
|             "5e023e6e34d52a55c3304f71": 2, | ||||
|             "5e023e53d4353e3302577c4c": 1 | ||||
|         }, | ||||
|         "Caliber762x54R": { | ||||
|             "64b8f7c241772715af0f9c3d": 2, | ||||
|             "64b8f7b5389d7ffd620ccba2": 2, | ||||
|             "64b8f7968532cf95ee0a0dbf": 2, | ||||
|             "5e023cf8186a883be655e54f": 2, | ||||
|             "5887431f2459777e1612938f": 1 | ||||
|         }, | ||||
|         "Caliber86x70": { | ||||
|             "5fc382b6d6fa9c00c571bbc3": 2, | ||||
|             "5fc382c1016cce60e8341b20": 1 | ||||
|         }, | ||||
|         "Caliber9x18PM": { | ||||
|             "5737218f245977612125ba51": 5, | ||||
|             "57372140245977611f70ee91": 5, | ||||
|             "5737207f24597760ff7b25f2": 2, | ||||
|             "573719762459775a626ccbc1": 3, | ||||
|             "57371f8d24597761006c6a81": 3, | ||||
|             "57371f2b24597761224311f1": 5, | ||||
|             "57371eb62459776125652ac1": 1, | ||||
|             "57371b192459775a9f58a5e0": 1, | ||||
|             "57371e4124597760ff7b25f1": 1 | ||||
|         }, | ||||
|         "Caliber9x19PARA": { | ||||
|             "5efb0e16aeb21837e749c7ff": 1, | ||||
|             "58864a4f2459770fcc257101": 7, | ||||
|             "5a3c16fe86f77452b62de32a": 12, | ||||
|             "5c3df7d588a4501f290594e5": 6, | ||||
|             "64b7bbb74b75259c590fa897": 4, | ||||
|             "56d59d3ad2720bdb418b4577": 2 | ||||
|         }, | ||||
|         "Caliber9x21": { | ||||
|             "5a26ac06c4a282000c5a90a8": 5, | ||||
|             "5a26abfac4a28232980eabff": 3, | ||||
|             "5a269f97c4a282000b151807": 1 | ||||
|         }, | ||||
|         "Caliber9x33R": { | ||||
|             "62330c40bdd19b369e1e53d1": 5, | ||||
|             "62330bfadc5883093563729b": 3, | ||||
|             "62330c18744e5e31df12f516": 1 | ||||
|         }, | ||||
|         "Caliber9x39": { | ||||
|             "6576f96220d53a5b8f3e395e": 7, | ||||
|             "57a0dfb82459774d3078b56c": 5, | ||||
|             "5c0d668f86f7747ccb7f13b2": 1 | ||||
|         }, | ||||
|         "Caliber127x33": { | ||||
|             "66a0d1c87d0d369e270bb9de": 10, | ||||
|             "66a0d1f88486c69fce00fdf6": 1 | ||||
|         } | ||||
|     }, | ||||
|     "pmcAmmo": { | ||||
|         "Caliber1143x23ACP": { | ||||
|             "5ea2a8e200685063ec28c05a": 10, | ||||
|             "5efb0fc6aeb21837e749c801": 5, | ||||
|             "5efb0d4f4bc50b58e81710f3": 30, | ||||
|             "5e81f423763d9f754677bf2e": 50, | ||||
|             "5efb0cabfb3e451d70735af5": 10 | ||||
|         }, | ||||
|         "Caliber127x55": { | ||||
|             "5cadf6e5ae921500113bb973": 80, | ||||
|             "5cadf6ddae9215051e1c23b2": 20 | ||||
|         }, | ||||
|         "Caliber12g": { | ||||
|             "5d6e6806a4b936088465b17e": 15, | ||||
|             "64b8ee384b75259c590fa89b": 6, | ||||
|             "5c0d591486f7744c505b416f": 5, | ||||
|             "5d6e68e6a4b9361c140bcfe0": 15, | ||||
|             "5d6e689ca4b9361bc8618956": 13, | ||||
|             "5d6e68c4a4b9361b93413f79": 9 | ||||
|         }, | ||||
|         "Caliber20g": { | ||||
|             "5d6e69c7a4b9360b6c0d54e4": 8, | ||||
|             "5d6e6a5fa4b93614ec501745": 6, | ||||
|             "5d6e6a53a4b9361bd473feec": 6, | ||||
|             "5d6e6a05a4b93618084f58d0": 3, | ||||
|             "5d6e6a42a4b9364f07165f52": 2 | ||||
|         }, | ||||
|         "Caliber23x75": { | ||||
|             "5f647f31b6238e5dd066e196": 60, | ||||
|             "5e85a9a6eacf8c039e4e2ac1": 30, | ||||
|             "5e85aa1a988a8701445df1f5": 10 | ||||
|         }, | ||||
|         "Caliber366TKM": { | ||||
|             "59e6542b86f77411dc52a77a": 5, | ||||
|             "59e655cb86f77411dc52a77b": 65, | ||||
|             "5f0596629e22f464da6bbdd9": 30 | ||||
|         }, | ||||
|         "Caliber40mmRU": { | ||||
|             "5656eb674bdc2d35148b457c": 1 | ||||
|         }, | ||||
|         "Caliber40x46": { | ||||
|             "5ede4739e0350d05467f73e8": 1, | ||||
|             "5ede47405b097655935d7d16": 1, | ||||
|             "5ede474b0c226a66f5402622": 1, | ||||
|             "5ede475339ee016e8c534742": 1, | ||||
|             "5ede475b549eed7c6d5c18fb": 1, | ||||
|             "5f0c892565703e5c461894e9": 1 | ||||
|         }, | ||||
|         "Caliber46x30": { | ||||
|             "5ba26844d4351e00334c9475": 70, | ||||
|             "64b6979341772715af0f9c39": 15, | ||||
|             "5ba2678ad4351e44f824b344": 10, | ||||
|             "5ba26835d4351e0035628ff5": 5 | ||||
|         }, | ||||
|         "Caliber545x39": { | ||||
|             "56dff0bed2720bb0668b4567": 5, | ||||
|             "56dff3afd2720bba668b4567": 40, | ||||
|             "56dff2ced2720bb4668b4567": 30, | ||||
|             "56dff061d2720bb5668b4567": 15, | ||||
|             "61962b617c6c7b169525f168": 5, | ||||
|             "56dfef82d2720bbd668b4567": 5 | ||||
|         }, | ||||
|         "Caliber556x45NATO": { | ||||
|             "5c0d5ae286f7741e46554302": 5, | ||||
|             "59e6920f86f77411d82aa167": 10, | ||||
|             "54527a984bdc2d4e668b4567": 50, | ||||
|             "60194943740c5d77f6705eea": 30, | ||||
|             "59e6906286f7746c9f75e847": 10, | ||||
|             "54527ac44bdc2d36668b4567": 5 | ||||
|         }, | ||||
|         "Caliber57x28": { | ||||
|             "5cc86840d7f00c002412c56c": 10, | ||||
|             "5cc80f8fe4a949033b0224a2": 15, | ||||
|             "5cc80f53e4a949000e1ea4f8": 28, | ||||
|             "5cc80f67e4a949035e43bbba": 7 | ||||
|         }, | ||||
|         "Caliber68x51": { | ||||
|             "6529302b8c26af6326029fb7": 1 | ||||
|         }, | ||||
|         "Caliber762x25TT": { | ||||
|             "5736026a245977644601dc61": 5, | ||||
|             "573603c924597764442bd9cb": 10, | ||||
|             "573603562459776430731618": 10 | ||||
|         }, | ||||
|         "Caliber762x35": { | ||||
|             "6196365d58ef8c428c287da1": 5, | ||||
|             "5fbe3ffdf8b6a877a729ea82": 55, | ||||
|             "619636be6db0f2477964e710": 30, | ||||
|             "64b8725c4b75259c590fa899": 10 | ||||
|         }, | ||||
|         "Caliber762x39": { | ||||
|             "5656d7c34bdc2d9d198b4587": 60, | ||||
|             "64b7af434b75259c590fa893": 35, | ||||
|             "59e0d99486f7744a32234762": 5 | ||||
|         }, | ||||
|         "Caliber762x51": { | ||||
|             "5e023e53d4353e3302577c4c": 60, | ||||
|             "58dd3ad986f77403051cba8f": 35, | ||||
|             "5a608bf24f39f98ffc77720e": 5 | ||||
|         }, | ||||
|         "Caliber762x54R": { | ||||
|             "5887431f2459777e1612938f": 50, | ||||
|             "59e77a2386f7742ee578960a": 25, | ||||
|             "5e023d34e8a400319a28ed44": 5 | ||||
|         }, | ||||
|         "Caliber86x70": { | ||||
|             "5fc382b6d6fa9c00c571bbc3": 75, | ||||
|             "5fc382c1016cce60e8341b20": 20, | ||||
|             "5fc275cf85fd526b824a571a": 5 | ||||
|         }, | ||||
|         "Caliber9x18PM": { | ||||
|             "5737201124597760fc4431f1": 35, | ||||
|             "573720e02459776143012541": 25, | ||||
|             "573718ba2459775a75491131": 25, | ||||
|             "57371aab2459775a77142f22": 10 | ||||
|         }, | ||||
|         "Caliber9x19PARA": { | ||||
|             "5c0d56a986f774449d5de529": 5, | ||||
|             "5efb0e16aeb21837e749c7ff": 25, | ||||
|             "56d59d3ad2720bdb418b4577": 65, | ||||
|             "5c925fa22e221601da359b7b": 5 | ||||
|         }, | ||||
|         "Caliber9x21": { | ||||
|             "5a26abfac4a28232980eabff": 12, | ||||
|             "5a269f97c4a282000b151807": 30, | ||||
|             "6576f93989f0062e741ba952": 12, | ||||
|             "5a26ac0ec4a28200741e1e18": 8 | ||||
|         }, | ||||
|         "Caliber9x33R": { | ||||
|             "62330bfadc5883093563729b": 8, | ||||
|             "62330c18744e5e31df12f516": 8, | ||||
|             "62330b3ed4dc74626d570b95": 2 | ||||
|         }, | ||||
|         "Caliber9x39": { | ||||
|             "57a0dfb82459774d3078b56c": 25, | ||||
|             "5c0d668f86f7747ccb7f13b2": 60, | ||||
|             "61962d879bb3d20b0946d385": 10, | ||||
|             "57a0e5022459774d1673f889": 5 | ||||
|         }, | ||||
|         "Caliber127x33": { | ||||
|             "66a0d1c87d0d369e270bb9de": 30, | ||||
|             "66a0d1f88486c69fce00fdf6": 60, | ||||
|             "66a0d1e0ed648d72fe064d06": 10 | ||||
|         } | ||||
|     }, | ||||
|     "bossAmmo": { | ||||
|         "Caliber1143x23ACP": { | ||||
|             "5ea2a8e200685063ec28c05a": 4, | ||||
|             "5efb0fc6aeb21837e749c801": 1, | ||||
|             "5efb0d4f4bc50b58e81710f3": 10, | ||||
|             "5e81f423763d9f754677bf2e": 18, | ||||
|             "5efb0cabfb3e451d70735af5": 10 | ||||
|         }, | ||||
|         "Caliber127x55": { | ||||
|             "5cadf6e5ae921500113bb973": 3, | ||||
|             "5cadf6ddae9215051e1c23b2": 12, | ||||
|             "5cadf6eeae921500134b2799": 8 | ||||
|         }, | ||||
|         "Caliber12g": { | ||||
|             "5d6e6806a4b936088465b17e": 7, | ||||
|             "64b8ee384b75259c590fa89b": 4, | ||||
|             "5d6e6911a4b9361bd5780d52": 3, | ||||
|             "5c0d591486f7744c505b416f": 5, | ||||
|             "5d6e6891a4b9361bd473feea": 2, | ||||
|             "5d6e68e6a4b9361c140bcfe0": 6, | ||||
|             "5d6e689ca4b9361bc8618956": 8, | ||||
|             "5d6e68c4a4b9361b93413f79": 8, | ||||
|             "5d6e68a8a4b9360b6c0d54e2": 3 | ||||
|         }, | ||||
|         "Caliber20g": { | ||||
|             "5d6e69c7a4b9360b6c0d54e4": 1, | ||||
|             "5d6e6a53a4b9361bd473feec": 4, | ||||
|             "5d6e6a05a4b93618084f58d0": 5, | ||||
|             "5d6e6a42a4b9364f07165f52": 5 | ||||
|         }, | ||||
|         "Caliber23x75": { | ||||
|             "5f647f31b6238e5dd066e196": 2, | ||||
|             "5e85a9a6eacf8c039e4e2ac1": 4, | ||||
|             "5e85aa1a988a8701445df1f5": 4 | ||||
|         }, | ||||
|         "Caliber366TKM": { | ||||
|             "59e6658b86f77411d949b250": 1, | ||||
|             "59e6542b86f77411dc52a77a": 2, | ||||
|             "59e655cb86f77411dc52a77b": 10, | ||||
|             "5f0596629e22f464da6bbdd9": 8 | ||||
|         }, | ||||
|         "Caliber40mmRU": { | ||||
|             "5656eb674bdc2d35148b457c": 1 | ||||
|         }, | ||||
|         "Caliber40x46": { | ||||
|             "5ede4739e0350d05467f73e8": 1, | ||||
|             "5ede47405b097655935d7d16": 1, | ||||
|             "5ede474b0c226a66f5402622": 1, | ||||
|             "5ede475339ee016e8c534742": 1, | ||||
|             "5ede475b549eed7c6d5c18fb": 1, | ||||
|             "5f0c892565703e5c461894e9": 1 | ||||
|         }, | ||||
|         "Caliber46x30": { | ||||
|             "5ba26812d4351e003201fef1": 2, | ||||
|             "5ba26844d4351e00334c9475": 4, | ||||
|             "5ba2678ad4351e44f824b344": 15, | ||||
|             "64b6979341772715af0f9c39": 15, | ||||
|             "5ba26835d4351e0035628ff5": 8 | ||||
|         }, | ||||
|         "Caliber545x39": { | ||||
|             "56dff3afd2720bba668b4567": 6, | ||||
|             "56dff2ced2720bb4668b4567": 12, | ||||
|             "56dff061d2720bb5668b4567": 20, | ||||
|             "61962b617c6c7b169525f168": 12, | ||||
|             "56dfef82d2720bbd668b4567": 9, | ||||
|             "56dff026d2720bb8668b4567": 8, | ||||
|             "5c0d5e4486f77478390952fe": 4 | ||||
|         }, | ||||
|         "Caliber556x45NATO": { | ||||
|             "5c0d5ae286f7741e46554302": 1, | ||||
|             "54527a984bdc2d4e668b4567": 7, | ||||
|             "60194943740c5d77f6705eea": 20, | ||||
|             "59e6906286f7746c9f75e847": 26, | ||||
|             "54527ac44bdc2d36668b4567": 30, | ||||
|             "59e690b686f7746c9f75e848": 7, | ||||
|             "601949593ae8f707c4608daa": 5 | ||||
|         }, | ||||
|         "Caliber57x28": { | ||||
|             "5cc80f8fe4a949033b0224a2": 5, | ||||
|             "5cc80f53e4a949000e1ea4f8": 21, | ||||
|             "5cc80f67e4a949035e43bbba": 15, | ||||
|             "5cc80f38e4a949001152b560": 12 | ||||
|         }, | ||||
|         "Caliber68x51": { | ||||
|             "6529302b8c26af6326029fb7": 10, | ||||
|             "6529243824cbe3c74a05e5c1": 5 | ||||
|         }, | ||||
|         "Caliber762x25TT": { | ||||
|             "5736026a245977644601dc61": 5, | ||||
|             "573603c924597764442bd9cb": 10, | ||||
|             "573603562459776430731618": 10 | ||||
|         }, | ||||
|         "Caliber762x35": { | ||||
|             "6196365d58ef8c428c287da1": 7, | ||||
|             "5fbe3ffdf8b6a877a729ea82": 6, | ||||
|             "619636be6db0f2477964e710": 23, | ||||
|             "64b8725c4b75259c590fa899": 20, | ||||
|             "5fd20ff893a8961fc660a954": 9 | ||||
|         }, | ||||
|         "Caliber762x39": { | ||||
|             "59e4cf5286f7741778269d8a": 4, | ||||
|             "5656d7c34bdc2d9d198b4587": 28, | ||||
|             "64b7af434b75259c590fa893": 33, | ||||
|             "59e0d99486f7744a32234762": 20, | ||||
|             "601aa3d2b2bcb34913271e6d": 12 | ||||
|         }, | ||||
|         "Caliber762x51": { | ||||
|             "5e023e53d4353e3302577c4c": 6, | ||||
|             "58dd3ad986f77403051cba8f": 27, | ||||
|             "5a608bf24f39f98ffc77720e": 19, | ||||
|             "5a6086ea4f39f99cd479502f": 9, | ||||
|             "5efb0c1bd79ff02a1f5e68d9": 2 | ||||
|         }, | ||||
|         "Caliber762x54R": { | ||||
|             "5e023cf8186a883be655e54f": 3, | ||||
|             "5887431f2459777e1612938f": 20, | ||||
|             "59e77a2386f7742ee578960a": 25, | ||||
|             "5e023d34e8a400319a28ed44": 22, | ||||
|             "560d61e84bdc2da74d8b4571": 15, | ||||
|             "5e023d48186a883be655e551": 10 | ||||
|         }, | ||||
|         "Caliber86x70": { | ||||
|             "5fc382b6d6fa9c00c571bbc3": 5, | ||||
|             "5fc382c1016cce60e8341b20": 8, | ||||
|             "5fc275cf85fd526b824a571a": 8, | ||||
|             "5fc382a9d724d907e2077dab": 5 | ||||
|         }, | ||||
|         "Caliber9x18PM": { | ||||
|             "57371e4124597760ff7b25f1": 3, | ||||
|             "5737201124597760fc4431f1": 5, | ||||
|             "573720e02459776143012541": 12, | ||||
|             "573718ba2459775a75491131": 18, | ||||
|             "57371aab2459775a77142f22": 12, | ||||
|             "573719df2459775a626ccbc2": 10 | ||||
|         }, | ||||
|         "Caliber9x19PARA": { | ||||
|             "5c0d56a986f774449d5de529": 9, | ||||
|             "5efb0e16aeb21837e749c7ff": 5, | ||||
|             "5a3c16fe86f77452b62de32a": 4, | ||||
|             "56d59d3ad2720bdb418b4577": 18, | ||||
|             "5c925fa22e221601da359b7b": 22, | ||||
|             "5efb0da7a29a85116f6ea05f": 9 | ||||
|         }, | ||||
|         "Caliber9x21": { | ||||
|             "5a269f97c4a282000b151807": 8, | ||||
|             "6576f93989f0062e741ba952": 18, | ||||
|             "5a26ac0ec4a28200741e1e18": 18, | ||||
|             "6576f4708ca9c4381d16cd9d": 8 | ||||
|         }, | ||||
|         "Caliber9x33R": { | ||||
|             "62330c18744e5e31df12f516": 9, | ||||
|             "62330b3ed4dc74626d570b95": 6 | ||||
|         }, | ||||
|         "Caliber9x39": { | ||||
|             "5c0d668f86f7747ccb7f13b2": 9, | ||||
|             "61962d879bb3d20b0946d385": 25, | ||||
|             "57a0e5022459774d1673f889": 25, | ||||
|             "5c0d688c86f77413ae3407b2": 12 | ||||
|         }, | ||||
|         "Caliber127x33": { | ||||
|             "66a0d1c87d0d369e270bb9de": 3, | ||||
|             "66a0d1f88486c69fce00fdf6": 30, | ||||
|             "66a0d1e0ed648d72fe064d06": 25,  | ||||
|             "668fe62ac62660a5d8071446": 12 | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,457 @@ | |||
| { | ||||
|     "pmcUSEC": { | ||||
|         "appearance": { | ||||
|             "body": { | ||||
|                 "5cde95d97d6c8b647a3769b0": 1, | ||||
|                 "66546f823b51a4d21e0d17d7": 1, | ||||
|                 "5d1f56a686f7744bce0ee9eb": 1, | ||||
|                 "5d1f56c686f7744bcd13459c": 3, | ||||
|                 "637b945722e2a933ed0e33c8": 3, | ||||
|                 "6571cb0923aa6d72760a7f8f": 3, | ||||
|                 "5fd3e9f71b735718c25cd9f8": 3, | ||||
|                 "642d9bbf6c06444bf7033855": 3, | ||||
|                 "6033a35f80ae5e2f970ba6bb": 5, | ||||
|                 "66043728333907134309d647": 5, | ||||
|                 "5d1f56e486f7744bce0ee9ed": 5, | ||||
|                 "6295e8c3e08ed747e64aea00": 5, | ||||
|                 "642c18b8a6a0660b560fb31c": 5, | ||||
|                 "66acbe49dc61999a6a03d4d6": 5 | ||||
|             }, | ||||
|             "feet": { | ||||
|                 "5cde95ef7d6c8b04713c4f2d": 1, | ||||
|                 "5d1f58ed86f7744bcb0acd1c": 1, | ||||
|                 "5d1f590486f7744bcd13459e": 3, | ||||
|                 "642d4d8eb6b75d4c89077cf9": 3, | ||||
|                 "6033a3fee29c9f6c9b14e74e": 3, | ||||
|                 "5fcf940bce1ba36a513bb9cc": 5, | ||||
|                 "660436487502eca33a08cac8": 5, | ||||
|                 "6571cad4c8673f00290f5657": 5, | ||||
|                 "637ba17aa10a96c2b605dbc2": 5, | ||||
|                 "5d1f591186f7744bcc048755": 5, | ||||
|                 "6295e944e9de5e7b3751c4da": 5, | ||||
|                 "642c19360a69698d1b049e12": 5, | ||||
|                 "66acc8f719271bd6d00dec0b": 5 | ||||
|             }, | ||||
|             "hands": { | ||||
|                 "5cde95fa7d6c8b04737c2d13": 1 | ||||
|             }, | ||||
|             "head": { | ||||
|                 "5cde96047d6c8b20b577f016": 1, | ||||
|                 "5fdb4139e4ed5b5ea251e4ed": 1, | ||||
|                 "5fdb5950f5264a66150d1c6e": 1, | ||||
|                 "60a6aa8fd559ae040d0d951f": 1, | ||||
|                 "619f9e338858a474c8685cc9": 1, | ||||
|                 "62aca6a1310e67685a2fc2e7": 1, | ||||
|                 "6574aabee0423b9ebe0c79cf": 1 | ||||
|             } | ||||
|         } | ||||
|     }, | ||||
|     "pmcBEAR": { | ||||
|         "appearance": { | ||||
|             "body": { | ||||
|                 "5cc0858d14c02e000c6bea66": 1, | ||||
|                 "66546f823b51a4d21e0d17d7": 1, | ||||
|                 "5d1f565786f7743f8362bcd5": 1, | ||||
|                 "5fce3e0cfe40296c1d5fd782": 3, | ||||
|                 "6377266693a3b4967208e42b": 3, | ||||
|                 "5d1f564b86f7744bcb0acd16": 3, | ||||
|                 "6295e698e9de5e7b3751c47a": 3, | ||||
|                 "642e8ae07e17c882400c4f87": 3, | ||||
|                 "5d1f568486f7744bca3f0b98": 3, | ||||
|                 "657058fddf9b3231400e9188": 5, | ||||
|                 "6033a31e9ec839204e6a2f3e": 5, | ||||
|                 "66043cc27502eca33a08cad0": 5, | ||||
|                 "5fce3e47fe40296c1d5fd784": 5, | ||||
|                 "642ed297ac11c9eaf10d87e8": 5, | ||||
|                 "66acec1dc94f4bf5bc063a16": 5 | ||||
|             }, | ||||
|             "feet": { | ||||
|                 "5cc085bb14c02e000e67a5c5": 1, | ||||
|                 "5d1f58bd86f7744bce0ee9ef": 1, | ||||
|                 "6377315993a3b4967208e437": 3, | ||||
|                 "5d1f588e86f7744bcc048753": 3, | ||||
|                 "65707a89f5a6f1412f0c5f7b": 3, | ||||
|                 "642ed40af5bdf1c04e01952e": 3, | ||||
|                 "5fce3e965a9f8c40685693bc": 3, | ||||
|                 "6295e63de08ed747e64ae991": 5, | ||||
|                 "66043cf87502eca33a08cad2": 5, | ||||
|                 "6033a3d8ed2e0509b15f9031": 5, | ||||
|                 "5d1f58cb86f7744bca3f0b9a": 5, | ||||
|                 "5d1f58a086f7743f8362bcd9": 5, | ||||
|                 "642e71620a69698d1b049f0a": 5, | ||||
|                 "66acebd4ede86671bb09584b": 5 | ||||
|             }, | ||||
|             "hands": { | ||||
|                 "5cc0876314c02e000c6bea6b": 1 | ||||
|             }, | ||||
|             "head": { | ||||
|                 "5cc084dd14c02e000b0550a3": 1, | ||||
|                 "5fdb50bb2b730a787b3f78cf": 1, | ||||
|                 "5fdb7571e4ed5b5ea251e529": 1, | ||||
|                 "60a6aaad42fd2735e4589978": 1, | ||||
|                 "619f94f5b90286142b59d45f": 1, | ||||
|                 "62a9e7d15ea3b87d6f642a28": 1, | ||||
|                 "6574aa9a1b144de18c0fba45": 1 | ||||
|             } | ||||
|         } | ||||
|     }, | ||||
|     "springEarly": { | ||||
|         "pmcUSEC": { | ||||
|             "appearance": { | ||||
|                 "body": { | ||||
|                     "5d1f56c686f7744bcd13459c": 1, | ||||
|                     "5fd3e9f71b735718c25cd9f8": 1, | ||||
|                     "66043728333907134309d647": 1, | ||||
|                     "66acbe49dc61999a6a03d4d6": 1, | ||||
|                     "660437e57502eca33a08caca": 1, | ||||
|                     "5d1f56f186f7744bcb0acd1a": 1, | ||||
|                     "5d1f56ff86f7743f8362bcd7": 1, | ||||
|                     "5d1f56a686f7744bce0ee9eb": 2, | ||||
|                     "5e9da17386f774054b6f79a3": 2, | ||||
|                     "5e4bb35286f77406a511c9bc": 2, | ||||
|                     "5d1f56e486f7744bce0ee9ed": 2 | ||||
|                 }, | ||||
|                 "feet": { | ||||
|                     "642d4d8eb6b75d4c89077cf9": 1, | ||||
|                     "5fcf940bce1ba36a513bb9cc": 1, | ||||
|                     "66acc8f719271bd6d00dec0b": 1, | ||||
|                     "6295e944e9de5e7b3751c4da": 1, | ||||
|                     "5d1f592286f7743f8362bcdb": 1, | ||||
|                     "5e4bb3b586f77406812bd579": 1, | ||||
|                     "5d1f590486f7744bcd13459e": 3, | ||||
|                     "5d1f58ed86f7744bcb0acd1c": 3 | ||||
|                 }, | ||||
|                 "hands": { | ||||
|                     "5cde95fa7d6c8b04737c2d13": 1 | ||||
|                 }, | ||||
|                 "head": { | ||||
|                     "5cde96047d6c8b20b577f016": 1, | ||||
|                     "5fdb4139e4ed5b5ea251e4ed": 1, | ||||
|                     "5fdb5950f5264a66150d1c6e": 1, | ||||
|                     "60a6aa8fd559ae040d0d951f": 1, | ||||
|                     "619f9e338858a474c8685cc9": 1, | ||||
|                     "62aca6a1310e67685a2fc2e7": 1, | ||||
|                     "6574aabee0423b9ebe0c79cf": 1 | ||||
|                 } | ||||
|             } | ||||
|         }, | ||||
|         "pmcBEAR": { | ||||
|             "appearance": { | ||||
|                 "body": { | ||||
|                     "657058fddf9b3231400e9188": 1, | ||||
|                     "6033a31e9ec839204e6a2f3e": 1, | ||||
|                     "5d1f567786f7744bcc04874f": 1, | ||||
|                     "5e9d9fa986f774054d6b89f2": 1, | ||||
|                     "5f5e401747344c2e4f6c42c5": 1, | ||||
|                     "642e8ae07e17c882400c4f87": 2, | ||||
|                     "5d1f568486f7744bca3f0b98": 2, | ||||
|                     "66acec1dc94f4bf5bc063a16": 2, | ||||
|                     "5e4bb31586f7740695730568": 2 | ||||
|                 }, | ||||
|                 "feet": { | ||||
|                     "5d1f58bd86f7744bce0ee9ef": 1, | ||||
|                     "6377315993a3b4967208e437": 1, | ||||
|                     "66043cf87502eca33a08cad2": 1, | ||||
|                     "5d1f58cb86f7744bca3f0b9a": 1, | ||||
|                     "5d1f58a086f7743f8362bcd9": 1, | ||||
|                     "617be9e4e02b3b3fa50fa8f2": 1, | ||||
|                     "5f5e40400bc58666c37e7819": 1, | ||||
|                     "66acebd4ede86671bb09584b": 3, | ||||
|                     "5d1f58ab86f7743014162042": 3 | ||||
|                 }, | ||||
|                 "hands": { | ||||
|                     "5cc0876314c02e000c6bea6b": 1 | ||||
|                 }, | ||||
|                 "head": { | ||||
|                     "5cc084dd14c02e000b0550a3": 1, | ||||
|                     "5fdb50bb2b730a787b3f78cf": 1, | ||||
|                     "5fdb7571e4ed5b5ea251e529": 1, | ||||
|                     "60a6aaad42fd2735e4589978": 1, | ||||
|                     "619f94f5b90286142b59d45f": 1, | ||||
|                     "62a9e7d15ea3b87d6f642a28": 1, | ||||
|                     "6574aa9a1b144de18c0fba45": 1 | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     }, | ||||
|     "spring": { | ||||
|         "pmcUSEC": { | ||||
|             "appearance": { | ||||
|                 "body": { | ||||
|                     "5cde95d97d6c8b647a3769b0": 1, | ||||
|                     "5fd3e9f71b735718c25cd9f8": 1, | ||||
|                     "66043728333907134309d647": 1, | ||||
|                     "5d4da0cb86f77450fe0a6629": 1, | ||||
|                     "5d1f56f186f7744bcb0acd1a": 1, | ||||
|                     "5f5e4075df4f3100376a8138": 1 | ||||
|                 }, | ||||
|                 "feet": { | ||||
|                     "5cde95ef7d6c8b04713c4f2d": 1, | ||||
|                     "6033a3fee29c9f6c9b14e74e": 1, | ||||
|                     "660436487502eca33a08cac8": 1, | ||||
|                     "6571cad4c8673f00290f5657": 1, | ||||
|                     "66acc8f719271bd6d00dec0b": 1, | ||||
|                     "5d1f592286f7743f8362bcdb": 1, | ||||
|                     "642d6941ff5ecad7810a8a61": 1, | ||||
|                     "5e9dcadd86f7743e20652f23": 1 | ||||
|                 }, | ||||
|                 "hands": { | ||||
|                     "5cde95fa7d6c8b04737c2d13": 1 | ||||
|                 }, | ||||
|                 "head": { | ||||
|                     "5cde96047d6c8b20b577f016": 1, | ||||
|                     "5fdb4139e4ed5b5ea251e4ed": 1, | ||||
|                     "5fdb5950f5264a66150d1c6e": 1, | ||||
|                     "60a6aa8fd559ae040d0d951f": 1, | ||||
|                     "619f9e338858a474c8685cc9": 1, | ||||
|                     "62aca6a1310e67685a2fc2e7": 1, | ||||
|                     "6574aabee0423b9ebe0c79cf": 1 | ||||
|                 } | ||||
|             } | ||||
|         }, | ||||
|         "pmcBEAR": { | ||||
|             "appearance": { | ||||
|                 "body": { | ||||
|                     "5cc0858d14c02e000c6bea66": 1, | ||||
|                     "5d1f564b86f7744bcb0acd16": 1, | ||||
|                     "6295e698e9de5e7b3751c47a": 1, | ||||
|                     "6033a31e9ec839204e6a2f3e": 1, | ||||
|                     "5fce3e47fe40296c1d5fd784": 1, | ||||
|                     "617bca4b4013b06b0b78df2a": 1, | ||||
|                     "5df89f1f86f77412631087ea": 1 | ||||
|                 }, | ||||
|                 "feet": { | ||||
|                     "5cc085bb14c02e000e67a5c5": 1, | ||||
|                     "5d1f588e86f7744bcc048753": 1, | ||||
|                     "66043cf87502eca33a08cad2": 1, | ||||
|                     "6033a3d8ed2e0509b15f9031": 1, | ||||
|                     "642e71620a69698d1b049f0a": 1, | ||||
|                     "617be9e4e02b3b3fa50fa8f2": 1, | ||||
|                     "642eea6f881906a7fe086841": 1, | ||||
|                     "5df89f8f86f77412672a1e38": 1, | ||||
|                     "5e9dc97c86f774054c19ac9a": 1, | ||||
|                     "5e4bb39386f774067f79de05": 1 | ||||
|                 }, | ||||
|                 "hands": { | ||||
|                     "5cc0876314c02e000c6bea6b": 1 | ||||
|                 }, | ||||
|                 "head": { | ||||
|                     "5cc084dd14c02e000b0550a3": 1, | ||||
|                     "5fdb50bb2b730a787b3f78cf": 1, | ||||
|                     "5fdb7571e4ed5b5ea251e529": 1, | ||||
|                     "60a6aaad42fd2735e4589978": 1, | ||||
|                     "619f94f5b90286142b59d45f": 1, | ||||
|                     "62a9e7d15ea3b87d6f642a28": 1, | ||||
|                     "6574aa9a1b144de18c0fba45": 1 | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     }, | ||||
|     "summer": { | ||||
|         "pmcUSEC": { | ||||
|             "appearance": { | ||||
|                 "body": { | ||||
|                     "5cde95d97d6c8b647a3769b0": 1, | ||||
|                     "5d1f56c686f7744bcd13459c": 1, | ||||
|                     "5fd3e9f71b735718c25cd9f8": 1, | ||||
|                     "66043728333907134309d647": 1, | ||||
|                     "5d4da0cb86f77450fe0a6629": 1, | ||||
|                     "66acbe49dc61999a6a03d4d6": 1, | ||||
|                     "64ef3efdb63b74469b6c1499": 1, | ||||
|                     "642c18b8a6a0660b560fb31c": 1, | ||||
|                     "5d1f56f186f7744bcb0acd1a": 1, | ||||
|                     "5f5e4075df4f3100376a8138": 1 | ||||
|                 }, | ||||
|                 "feet": { | ||||
|                     "5cde95ef7d6c8b04713c4f2d": 1, | ||||
|                     "6033a3fee29c9f6c9b14e74e": 1, | ||||
|                     "660436487502eca33a08cac8": 1, | ||||
|                     "6571cad4c8673f00290f5657": 1, | ||||
|                     "66acc8f719271bd6d00dec0b": 1, | ||||
|                     "5d1f593286f7743014162044": 1, | ||||
|                     "5d1f592286f7743f8362bcdb": 1, | ||||
|                     "642d6941ff5ecad7810a8a61": 1, | ||||
|                     "5e9dcadd86f7743e20652f23": 1 | ||||
|                 }, | ||||
|                 "hands": { | ||||
|                     "5cde95fa7d6c8b04737c2d13": 1 | ||||
|                 }, | ||||
|                 "head": { | ||||
|                     "5cde96047d6c8b20b577f016": 1, | ||||
|                     "5fdb4139e4ed5b5ea251e4ed": 1, | ||||
|                     "5fdb5950f5264a66150d1c6e": 1, | ||||
|                     "60a6aa8fd559ae040d0d951f": 1, | ||||
|                     "619f9e338858a474c8685cc9": 1, | ||||
|                     "62aca6a1310e67685a2fc2e7": 1, | ||||
|                     "6574aabee0423b9ebe0c79cf": 1 | ||||
|                 } | ||||
|             } | ||||
|         }, | ||||
|         "pmcBEAR": { | ||||
|             "appearance": { | ||||
|                 "body": { | ||||
|                     "5cc0858d14c02e000c6bea66": 1, | ||||
|                     "5d1f564b86f7744bcb0acd16": 1, | ||||
|                     "6295e698e9de5e7b3751c47a": 1, | ||||
|                     "6033a31e9ec839204e6a2f3e": 1, | ||||
|                     "5fce3e47fe40296c1d5fd784": 1, | ||||
|                     "617bca4b4013b06b0b78df2a": 1, | ||||
|                     "64ef3efdb63b74469b6c1499": 1, | ||||
|                     "5df89f1f86f77412631087ea": 1, | ||||
|                     "5e9d9fa986f774054d6b89f2": 1 | ||||
|                 }, | ||||
|                 "feet": { | ||||
|                     "5cc085bb14c02e000e67a5c5": 1, | ||||
|                     "5d1f588e86f7744bcc048753": 1, | ||||
|                     "66043cf87502eca33a08cad2": 1, | ||||
|                     "6033a3d8ed2e0509b15f9031": 1, | ||||
|                     "642e71620a69698d1b049f0a": 1, | ||||
|                     "617be9e4e02b3b3fa50fa8f2": 1, | ||||
|                     "642eea6f881906a7fe086841": 1, | ||||
|                     "5df89f8f86f77412672a1e38": 1, | ||||
|                     "5e9dc97c86f774054c19ac9a": 1, | ||||
|                     "5e4bb39386f774067f79de05": 1 | ||||
|                 }, | ||||
|                 "hands": { | ||||
|                     "5cc0876314c02e000c6bea6b": 1 | ||||
|                 }, | ||||
|                 "head": { | ||||
|                     "5cc084dd14c02e000b0550a3": 1, | ||||
|                     "5fdb50bb2b730a787b3f78cf": 1, | ||||
|                     "5fdb7571e4ed5b5ea251e529": 1, | ||||
|                     "60a6aaad42fd2735e4589978": 1, | ||||
|                     "619f94f5b90286142b59d45f": 1, | ||||
|                     "62a9e7d15ea3b87d6f642a28": 1, | ||||
|                     "6574aa9a1b144de18c0fba45": 1 | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     }, | ||||
|     "autumn": { | ||||
|         "pmcUSEC": { | ||||
|             "appearance": { | ||||
|                 "body": { | ||||
|                     "5d1f56c686f7744bcd13459c": 1, | ||||
|                     "637b945722e2a933ed0e33c8": 1, | ||||
|                     "6571cb0923aa6d72760a7f8f": 1, | ||||
|                     "6033a35f80ae5e2f970ba6bb": 1, | ||||
|                     "5d1f56e486f7744bce0ee9ed": 1, | ||||
|                     "66acbe49dc61999a6a03d4d6": 1, | ||||
|                     "660437e57502eca33a08caca": 1, | ||||
|                     "64ef3efdb63b74469b6c1499": 1, | ||||
|                     "5d1f56ff86f7743f8362bcd7": 1 | ||||
|                 }, | ||||
|                 "feet": { | ||||
|                     "642d4d8eb6b75d4c89077cf9": 1, | ||||
|                     "5fcf940bce1ba36a513bb9cc": 1, | ||||
|                     "637ba17aa10a96c2b605dbc2": 1, | ||||
|                     "6295e944e9de5e7b3751c4da": 1, | ||||
|                     "5e4bb3b586f77406812bd579": 1, | ||||
|                     "5f5e40a06760b4138443b341": 1 | ||||
|                 }, | ||||
|                 "hands": { | ||||
|                     "5cde95fa7d6c8b04737c2d13": 1 | ||||
|                 }, | ||||
|                 "head": { | ||||
|                     "5cde96047d6c8b20b577f016": 1, | ||||
|                     "5fdb4139e4ed5b5ea251e4ed": 1, | ||||
|                     "5fdb5950f5264a66150d1c6e": 1, | ||||
|                     "60a6aa8fd559ae040d0d951f": 1, | ||||
|                     "619f9e338858a474c8685cc9": 1, | ||||
|                     "62aca6a1310e67685a2fc2e7": 1, | ||||
|                     "6574aabee0423b9ebe0c79cf": 1 | ||||
|                 } | ||||
|             } | ||||
|         }, | ||||
|         "pmcBEAR": { | ||||
|             "appearance": { | ||||
|                 "body": { | ||||
|                     "6377266693a3b4967208e42b": 1, | ||||
|                     "5d1f568486f7744bca3f0b98": 1, | ||||
|                     "657058fddf9b3231400e9188": 1, | ||||
|                     "642ed297ac11c9eaf10d87e8": 1, | ||||
|                     "5d1f567786f7744bcc04874f": 1, | ||||
|                     "64ef3efdb63b74469b6c1499": 1, | ||||
|                     "6430119aac11c9eaf10d881b": 1, | ||||
|                     "5f5e401747344c2e4f6c42c5": 1 | ||||
|                 }, | ||||
|                 "feet": { | ||||
|                     "5d1f58bd86f7744bce0ee9ef": 1, | ||||
|                     "6377315993a3b4967208e437": 1, | ||||
|                     "642ed40af5bdf1c04e01952e": 1, | ||||
|                     "6295e63de08ed747e64ae991": 1, | ||||
|                     "5d1f58a086f7743f8362bcd9": 1, | ||||
|                     "66043d7ac8949a435906e434": 1, | ||||
|                     "5d1f58ab86f7743014162042": 1, | ||||
|                     "5f5e40400bc58666c37e7819": 1 | ||||
|                 }, | ||||
|                 "hands": { | ||||
|                     "5cc0876314c02e000c6bea6b": 1 | ||||
|                 }, | ||||
|                 "head": { | ||||
|                     "5cc084dd14c02e000b0550a3": 1, | ||||
|                     "5fdb50bb2b730a787b3f78cf": 1, | ||||
|                     "5fdb7571e4ed5b5ea251e529": 1, | ||||
|                     "60a6aaad42fd2735e4589978": 1, | ||||
|                     "619f94f5b90286142b59d45f": 1, | ||||
|                     "62a9e7d15ea3b87d6f642a28": 1, | ||||
|                     "6574aa9a1b144de18c0fba45": 1 | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     }, | ||||
|     "winter": { | ||||
|         "pmcUSEC": { | ||||
|             "appearance": { | ||||
|                 "body": { | ||||
|                     "5d1f56a686f7744bce0ee9eb": 1, | ||||
|                     "5e9da17386f774054b6f79a3": 1, | ||||
|                     "5e4bb35286f77406a511c9bc": 1, | ||||
|                     "5d1f56e486f7744bce0ee9ed": 1 | ||||
|                 }, | ||||
|                 "feet": { | ||||
|                     "5d1f590486f7744bcd13459e": 1, | ||||
|                     "5d1f58ed86f7744bcb0acd1c": 1 | ||||
|                 }, | ||||
|                 "hands": { | ||||
|                     "5cde95fa7d6c8b04737c2d13": 1 | ||||
|                 }, | ||||
|                 "head": { | ||||
|                     "5cde96047d6c8b20b577f016": 1, | ||||
|                     "5fdb4139e4ed5b5ea251e4ed": 1, | ||||
|                     "5fdb5950f5264a66150d1c6e": 1, | ||||
|                     "60a6aa8fd559ae040d0d951f": 1, | ||||
|                     "619f9e338858a474c8685cc9": 1, | ||||
|                     "62aca6a1310e67685a2fc2e7": 1, | ||||
|                     "6574aabee0423b9ebe0c79cf": 1 | ||||
|                 } | ||||
|             } | ||||
|         }, | ||||
|         "pmcBEAR": { | ||||
|             "appearance": { | ||||
|                 "body": { | ||||
|                     "642e8ae07e17c882400c4f87": 1, | ||||
|                     "5d1f568486f7744bca3f0b98": 1, | ||||
|                     "66acec1dc94f4bf5bc063a16": 1, | ||||
|                     "5e4bb31586f7740695730568": 1 | ||||
|                 }, | ||||
|                 "feet": { | ||||
|                     "66acebd4ede86671bb09584b": 1, | ||||
|                     "5d1f58ab86f7743014162042": 1 | ||||
|                 }, | ||||
|                 "hands": { | ||||
|                     "5cc0876314c02e000c6bea6b": 1 | ||||
|                 }, | ||||
|                 "head": { | ||||
|                     "5cc084dd14c02e000b0550a3": 1, | ||||
|                     "5fdb50bb2b730a787b3f78cf": 1, | ||||
|                     "5fdb7571e4ed5b5ea251e529": 1, | ||||
|                     "60a6aaad42fd2735e4589978": 1, | ||||
|                     "619f94f5b90286142b59d45f": 1, | ||||
|                     "62a9e7d15ea3b87d6f642a28": 1, | ||||
|                     "6574aa9a1b144de18c0fba45": 1 | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							|  | @ -0,0 +1,471 @@ | |||
| {     | ||||
|     "scavAmmo": { | ||||
|         "Caliber1143x23ACP": { | ||||
|             "5efb0fc6aeb21837e749c801": 1, | ||||
|             "5efb0d4f4bc50b58e81710f3": 3 | ||||
|         }, | ||||
|         "Caliber127x55": { | ||||
|             "5cadf6e5ae921500113bb973": 1 | ||||
|         }, | ||||
|         "Caliber12g": { | ||||
|             "5d6e6772a4b936088465b17c": 2, | ||||
|             "5d6e6806a4b936088465b17e": 2, | ||||
|             "5d6e67fba4b9361bc73bc779": 2, | ||||
|             "560d5e524bdc2d25448b4571": 2, | ||||
|             "5d6e6869a4b9361c140bcfde": 1, | ||||
|             "5d6e68b3a4b9361bca7e50b5": 1, | ||||
|             "58820d1224597753c90aeb13": 1, | ||||
|             "5d6e68dea4b9361bcc29e659": 1, | ||||
|             "5d6e6891a4b9361bd473feea": 1, | ||||
|             "5d6e68e6a4b9361c140bcfe0": 1, | ||||
|             "5d6e689ca4b9361bc8618956": 1 | ||||
|         }, | ||||
|         "Caliber20g": { | ||||
|             "5d6e695fa4b936359b35d852": 2, | ||||
|             "5d6e69b9a4b9361bc8618958": 2, | ||||
|             "5a38ebd9c4a282000d722a5b": 2, | ||||
|             "5d6e69c7a4b9360b6c0d54e4": 1, | ||||
|             "5d6e6a53a4b9361bd473feec": 1 | ||||
|         }, | ||||
|         "Caliber23x75": { | ||||
|             "5f647f31b6238e5dd066e196": 3, | ||||
|             "5e85a9a6eacf8c039e4e2ac1": 1 | ||||
|         }, | ||||
|         "Caliber366TKM": { | ||||
|             "59e6658b86f77411d949b250": 3, | ||||
|             "59e6542b86f77411dc52a77a": 1 | ||||
|         }, | ||||
|         "Caliber40mmRU": { | ||||
|             "5656eb674bdc2d35148b457c": 1 | ||||
|         }, | ||||
|         "Caliber40x46": { | ||||
|             "5ede4739e0350d05467f73e8": 1, | ||||
|             "5ede47405b097655935d7d16": 1, | ||||
|             "5ede474b0c226a66f5402622": 1, | ||||
|             "5ede475339ee016e8c534742": 1, | ||||
|             "5ede475b549eed7c6d5c18fb": 1, | ||||
|             "5f0c892565703e5c461894e9": 1 | ||||
|         }, | ||||
|         "Caliber46x30": { | ||||
|             "5ba26812d4351e003201fef1": 3, | ||||
|             "5ba26844d4351e00334c9475": 1 | ||||
|         }, | ||||
|         "Caliber545x39": { | ||||
|             "56dff216d2720bbd668b4568": 1, | ||||
|             "56dff338d2720bbd668b4569": 4, | ||||
|             "56dff421d2720b5f5a8b4567": 4, | ||||
|             "56dff4ecd2720b5f5a8b4568": 2, | ||||
|             "56dff4a2d2720bbd668b456a": 4, | ||||
|             "56dff0bed2720bb0668b4567": 3, | ||||
|             "56dff3afd2720bba668b4567": 1 | ||||
|         }, | ||||
|         "Caliber556x45NATO": { | ||||
|             "59e6927d86f77411da468256": 2, | ||||
|             "59e6918f86f7746c9f75e849": 2, | ||||
|             "59e68f6f86f7746c9f75e846": 4, | ||||
|             "59e6920f86f77411d82aa167": 5, | ||||
|             "54527a984bdc2d4e668b4567": 1 | ||||
|         }, | ||||
|         "Caliber57x28": { | ||||
|             "5cc86832d7f00c000d3a6e6c": 2, | ||||
|             "5cc80f79e4a949033c7343b2": 3, | ||||
|             "5cc86840d7f00c002412c56c": 3, | ||||
|             "5cc80f8fe4a949033b0224a2": 1, | ||||
|             "5cc80f53e4a949000e1ea4f8": 1 | ||||
|         }, | ||||
|         "Caliber68x51": { | ||||
|             "6529302b8c26af6326029fb7": 1 | ||||
|         }, | ||||
|         "Caliber762x25TT": { | ||||
|             "573602322459776445391df1": 2, | ||||
|             "573601b42459776410737435": 2, | ||||
|             "5735fdcd2459776445391d61": 1, | ||||
|             "5736026a245977644601dc61": 1 | ||||
|         }, | ||||
|         "Caliber762x35": { | ||||
|             "6196365d58ef8c428c287da1": 1, | ||||
|             "6196364158ef8c428c287d9f": 6, | ||||
|             "5fbe3ffdf8b6a877a729ea82": 3 | ||||
|         }, | ||||
|         "Caliber762x39": { | ||||
|             "59e4d3d286f774176a36250a": 2, | ||||
|             "64b7af734b75259c590fa895": 2, | ||||
|             "64b7af5a8532cf95ee0a0dbd": 6, | ||||
|             "59e4d24686f7741776641ac7": 4, | ||||
|             "59e4cf5286f7741778269d8a": 2, | ||||
|             "5656d7c34bdc2d9d198b4587": 1 | ||||
|         }, | ||||
|         "Caliber762x51": { | ||||
|             "5e023e88277cce2b522ff2b1": 2, | ||||
|             "5e023e6e34d52a55c3304f71": 2, | ||||
|             "5e023e53d4353e3302577c4c": 1 | ||||
|         }, | ||||
|         "Caliber762x54R": { | ||||
|             "64b8f7c241772715af0f9c3d": 2, | ||||
|             "64b8f7b5389d7ffd620ccba2": 2, | ||||
|             "64b8f7968532cf95ee0a0dbf": 2, | ||||
|             "5e023cf8186a883be655e54f": 2, | ||||
|             "5887431f2459777e1612938f": 1 | ||||
|         }, | ||||
|         "Caliber86x70": { | ||||
|             "5fc382b6d6fa9c00c571bbc3": 2, | ||||
|             "5fc382c1016cce60e8341b20": 1 | ||||
|         }, | ||||
|         "Caliber9x18PM": { | ||||
|             "5737218f245977612125ba51": 5, | ||||
|             "57372140245977611f70ee91": 5, | ||||
|             "5737207f24597760ff7b25f2": 2, | ||||
|             "573719762459775a626ccbc1": 3, | ||||
|             "57371f8d24597761006c6a81": 3, | ||||
|             "57371f2b24597761224311f1": 5, | ||||
|             "57371eb62459776125652ac1": 1, | ||||
|             "57371b192459775a9f58a5e0": 1, | ||||
|             "57371e4124597760ff7b25f1": 1 | ||||
|         }, | ||||
|         "Caliber9x19PARA": { | ||||
|             "5efb0e16aeb21837e749c7ff": 1, | ||||
|             "58864a4f2459770fcc257101": 7, | ||||
|             "5a3c16fe86f77452b62de32a": 12, | ||||
|             "5c3df7d588a4501f290594e5": 6, | ||||
|             "64b7bbb74b75259c590fa897": 4, | ||||
|             "56d59d3ad2720bdb418b4577": 2 | ||||
|         }, | ||||
|         "Caliber9x21": { | ||||
|             "5a26ac06c4a282000c5a90a8": 5, | ||||
|             "5a26abfac4a28232980eabff": 3, | ||||
|             "5a269f97c4a282000b151807": 1 | ||||
|         }, | ||||
|         "Caliber9x33R": { | ||||
|             "62330c40bdd19b369e1e53d1": 5, | ||||
|             "62330bfadc5883093563729b": 3, | ||||
|             "62330c18744e5e31df12f516": 1 | ||||
|         }, | ||||
|         "Caliber9x39": { | ||||
|             "6576f96220d53a5b8f3e395e": 7, | ||||
|             "57a0dfb82459774d3078b56c": 5, | ||||
|             "5c0d668f86f7747ccb7f13b2": 1 | ||||
|         }, | ||||
|         "Caliber127x33": { | ||||
|             "66a0d1c87d0d369e270bb9de": 10, | ||||
|             "66a0d1f88486c69fce00fdf6": 1 | ||||
|         } | ||||
|     }, | ||||
|     "pmcAmmo": { | ||||
|         "Caliber1143x23ACP": { | ||||
|             "5ea2a8e200685063ec28c05a": 20, | ||||
|             "5efb0d4f4bc50b58e81710f3": 10, | ||||
|             "5e81f423763d9f754677bf2e": 30, | ||||
|             "5efb0cabfb3e451d70735af5": 20 | ||||
|         }, | ||||
|         "Caliber127x55": { | ||||
|             "5cadf6e5ae921500113bb973": 15, | ||||
|             "5cadf6ddae9215051e1c23b2": 50, | ||||
|             "5cadf6eeae921500134b2799": 35 | ||||
|         }, | ||||
|         "Caliber12g": { | ||||
|             "5d6e6806a4b936088465b17e": 10, | ||||
|             "64b8ee384b75259c590fa89b": 20, | ||||
|             "5d6e6911a4b9361bd5780d52": 20, | ||||
|             "5c0d591486f7744c505b416f": 5, | ||||
|             "5d6e68e6a4b9361c140bcfe0": 5, | ||||
|             "5d6e689ca4b9361bc8618956": 5, | ||||
|             "5d6e68c4a4b9361b93413f79": 35, | ||||
|             "5d6e68a8a4b9360b6c0d54e2": 15 | ||||
|         }, | ||||
|         "Caliber20g": { | ||||
|             "5d6e6a5fa4b93614ec501745": 15, | ||||
|             "5d6e6a53a4b9361bd473feec": 15, | ||||
|             "5d6e6a05a4b93618084f58d0": 35, | ||||
|             "5d6e6a42a4b9364f07165f52": 35 | ||||
|         }, | ||||
|         "Caliber23x75": { | ||||
|             "5f647f31b6238e5dd066e196": 40, | ||||
|             "5e85a9a6eacf8c039e4e2ac1": 35, | ||||
|             "5e85aa1a988a8701445df1f5": 25 | ||||
|         }, | ||||
|         "Caliber366TKM": { | ||||
|             "59e655cb86f77411dc52a77b": 40, | ||||
|             "5f0596629e22f464da6bbdd9": 60 | ||||
|         }, | ||||
|         "Caliber40mmRU": { | ||||
|             "5656eb674bdc2d35148b457c": 1 | ||||
|         }, | ||||
|         "Caliber40x46": { | ||||
|             "5ede4739e0350d05467f73e8": 1, | ||||
|             "5ede47405b097655935d7d16": 1, | ||||
|             "5ede474b0c226a66f5402622": 1, | ||||
|             "5ede475339ee016e8c534742": 1, | ||||
|             "5ede475b549eed7c6d5c18fb": 1, | ||||
|             "5f0c892565703e5c461894e9": 1 | ||||
|         }, | ||||
|         "Caliber46x30": { | ||||
|             "5ba26844d4351e00334c9475": 40, | ||||
|             "64b6979341772715af0f9c39": 30, | ||||
|             "5ba2678ad4351e44f824b344": 20, | ||||
|             "5ba26835d4351e0035628ff5": 10 | ||||
|         }, | ||||
|         "Caliber545x39": { | ||||
|             "56dff2ced2720bb4668b4567": 30, | ||||
|             "56dff061d2720bb5668b4567": 50, | ||||
|             "61962b617c6c7b169525f168": 10, | ||||
|             "56dfef82d2720bbd668b4567": 10, | ||||
|             "56dff026d2720bb8668b4567": 5, | ||||
|             "5c0d5e4486f77478390952fe": 5 | ||||
|         }, | ||||
|         "Caliber556x45NATO": { | ||||
|             "5c0d5ae286f7741e46554302": 10, | ||||
|             "60194943740c5d77f6705eea": 25, | ||||
|             "59e6906286f7746c9f75e847": 25, | ||||
|             "54527ac44bdc2d36668b4567": 30, | ||||
|             "59e690b686f7746c9f75e848": 5, | ||||
|             "601949593ae8f707c4608daa": 5 | ||||
|         }, | ||||
|         "Caliber57x28": { | ||||
|             "5cc80f53e4a949000e1ea4f8": 20, | ||||
|             "5cc80f67e4a949035e43bbba": 40, | ||||
|             "5cc80f38e4a949001152b560": 30 | ||||
|         }, | ||||
|         "Caliber68x51": { | ||||
|             "6529302b8c26af6326029fb7": 80, | ||||
|             "6529243824cbe3c74a05e5c1": 20 | ||||
|         }, | ||||
|         "Caliber762x25TT": { | ||||
|             "573603c924597764442bd9cb": 10, | ||||
|             "573603562459776430731618": 10 | ||||
|         }, | ||||
|         "Caliber762x35": { | ||||
|             "6196365d58ef8c428c287da1": 5, | ||||
|             "5fbe3ffdf8b6a877a729ea82": 40, | ||||
|             "619636be6db0f2477964e710": 40, | ||||
|             "64b8725c4b75259c590fa899": 10, | ||||
|             "5fd20ff893a8961fc660a954": 5 | ||||
|         }, | ||||
|         "Caliber762x39": { | ||||
|             "5656d7c34bdc2d9d198b4587": 25, | ||||
|             "64b7af434b75259c590fa893": 50, | ||||
|             "59e0d99486f7744a32234762": 20, | ||||
|             "601aa3d2b2bcb34913271e6d": 5 | ||||
|         }, | ||||
|         "Caliber762x51": { | ||||
|             "5e023e53d4353e3302577c4c": 20, | ||||
|             "58dd3ad986f77403051cba8f": 45, | ||||
|             "5a608bf24f39f98ffc77720e": 20, | ||||
|             "5a6086ea4f39f99cd479502f": 10, | ||||
|             "5efb0c1bd79ff02a1f5e68d9": 5 | ||||
|         }, | ||||
|         "Caliber762x54R": { | ||||
|             "5887431f2459777e1612938f": 30, | ||||
|             "59e77a2386f7742ee578960a": 45, | ||||
|             "5e023d34e8a400319a28ed44": 20, | ||||
|             "560d61e84bdc2da74d8b4571": 5 | ||||
|         }, | ||||
|         "Caliber86x70": { | ||||
|             "5fc382b6d6fa9c00c571bbc3": 20, | ||||
|             "5fc382c1016cce60e8341b20": 40, | ||||
|             "5fc275cf85fd526b824a571a": 25, | ||||
|             "5fc382a9d724d907e2077dab": 5 | ||||
|         }, | ||||
|         "Caliber9x18PM": { | ||||
|             "5737201124597760fc4431f1": 15, | ||||
|             "573720e02459776143012541": 20, | ||||
|             "573718ba2459775a75491131": 30, | ||||
|             "57371aab2459775a77142f22": 20, | ||||
|             "573719df2459775a626ccbc2": 15 | ||||
|         }, | ||||
|         "Caliber9x19PARA": { | ||||
|             "5c0d56a986f774449d5de529": 10, | ||||
|             "5efb0e16aeb21837e749c7ff": 15, | ||||
|             "56d59d3ad2720bdb418b4577": 50, | ||||
|             "5c925fa22e221601da359b7b": 20, | ||||
|             "5efb0da7a29a85116f6ea05f": 5 | ||||
|         }, | ||||
|         "Caliber9x21": { | ||||
|             "5a269f97c4a282000b151807": 25, | ||||
|             "6576f93989f0062e741ba952": 25, | ||||
|             "5a26ac0ec4a28200741e1e18": 12, | ||||
|             "6576f4708ca9c4381d16cd9d": 8 | ||||
|         }, | ||||
|         "Caliber9x33R": { | ||||
|             "62330c18744e5e31df12f516": 9, | ||||
|             "62330b3ed4dc74626d570b95": 6 | ||||
|         }, | ||||
|         "Caliber9x39": { | ||||
|             "5c0d668f86f7747ccb7f13b2": 20, | ||||
|             "61962d879bb3d20b0946d385": 50, | ||||
|             "57a0e5022459774d1673f889": 25, | ||||
|             "5c0d688c86f77413ae3407b2": 5 | ||||
|         }, | ||||
|         "Caliber127x33": { | ||||
|             "66a0d1c87d0d369e270bb9de": 5, | ||||
|             "66a0d1f88486c69fce00fdf6": 60, | ||||
|             "66a0d1e0ed648d72fe064d06": 30, | ||||
|             "668fe62ac62660a5d8071446": 5 | ||||
|         } | ||||
|     }, | ||||
|     "bossAmmo": { | ||||
|         "Caliber1143x23ACP": { | ||||
|             "5ea2a8e200685063ec28c05a": 4, | ||||
|             "5efb0fc6aeb21837e749c801": 1, | ||||
|             "5efb0d4f4bc50b58e81710f3": 10, | ||||
|             "5e81f423763d9f754677bf2e": 18, | ||||
|             "5efb0cabfb3e451d70735af5": 10 | ||||
|         }, | ||||
|         "Caliber127x55": { | ||||
|             "5cadf6e5ae921500113bb973": 3, | ||||
|             "5cadf6ddae9215051e1c23b2": 12, | ||||
|             "5cadf6eeae921500134b2799": 8 | ||||
|         }, | ||||
|         "Caliber12g": { | ||||
|             "5d6e6806a4b936088465b17e": 7, | ||||
|             "64b8ee384b75259c590fa89b": 4, | ||||
|             "5d6e6911a4b9361bd5780d52": 3, | ||||
|             "5c0d591486f7744c505b416f": 5, | ||||
|             "5d6e6891a4b9361bd473feea": 2, | ||||
|             "5d6e68e6a4b9361c140bcfe0": 6, | ||||
|             "5d6e689ca4b9361bc8618956": 8, | ||||
|             "5d6e68c4a4b9361b93413f79": 8, | ||||
|             "5d6e68a8a4b9360b6c0d54e2": 3 | ||||
|         }, | ||||
|         "Caliber20g": { | ||||
|             "5d6e69c7a4b9360b6c0d54e4": 1, | ||||
|             "5d6e6a53a4b9361bd473feec": 4, | ||||
|             "5d6e6a05a4b93618084f58d0": 5, | ||||
|             "5d6e6a42a4b9364f07165f52": 5 | ||||
|         }, | ||||
|         "Caliber23x75": { | ||||
|             "5f647f31b6238e5dd066e196": 2, | ||||
|             "5e85a9a6eacf8c039e4e2ac1": 4, | ||||
|             "5e85aa1a988a8701445df1f5": 4 | ||||
|         }, | ||||
|         "Caliber366TKM": { | ||||
|             "59e6658b86f77411d949b250": 1, | ||||
|             "59e6542b86f77411dc52a77a": 2, | ||||
|             "59e655cb86f77411dc52a77b": 10, | ||||
|             "5f0596629e22f464da6bbdd9": 8 | ||||
|         }, | ||||
|         "Caliber40mmRU": { | ||||
|             "5656eb674bdc2d35148b457c": 1 | ||||
|         }, | ||||
|         "Caliber40x46": { | ||||
|             "5ede4739e0350d05467f73e8": 1, | ||||
|             "5ede47405b097655935d7d16": 1, | ||||
|             "5ede474b0c226a66f5402622": 1, | ||||
|             "5ede475339ee016e8c534742": 1, | ||||
|             "5ede475b549eed7c6d5c18fb": 1, | ||||
|             "5f0c892565703e5c461894e9": 1 | ||||
|         }, | ||||
|         "Caliber46x30": { | ||||
|             "5ba26812d4351e003201fef1": 2, | ||||
|             "5ba26844d4351e00334c9475": 4, | ||||
|             "5ba2678ad4351e44f824b344": 15, | ||||
|             "64b6979341772715af0f9c39": 15, | ||||
|             "5ba26835d4351e0035628ff5": 8 | ||||
|         }, | ||||
|         "Caliber545x39": { | ||||
|             "56dff3afd2720bba668b4567": 6, | ||||
|             "56dff2ced2720bb4668b4567": 12, | ||||
|             "56dff061d2720bb5668b4567": 20, | ||||
|             "61962b617c6c7b169525f168": 12, | ||||
|             "56dfef82d2720bbd668b4567": 9, | ||||
|             "56dff026d2720bb8668b4567": 8, | ||||
|             "5c0d5e4486f77478390952fe": 4 | ||||
|         }, | ||||
|         "Caliber556x45NATO": { | ||||
|             "5c0d5ae286f7741e46554302": 1, | ||||
|             "54527a984bdc2d4e668b4567": 7, | ||||
|             "60194943740c5d77f6705eea": 20, | ||||
|             "59e6906286f7746c9f75e847": 26, | ||||
|             "54527ac44bdc2d36668b4567": 30, | ||||
|             "59e690b686f7746c9f75e848": 7, | ||||
|             "601949593ae8f707c4608daa": 5 | ||||
|         }, | ||||
|         "Caliber57x28": { | ||||
|             "5cc80f8fe4a949033b0224a2": 5, | ||||
|             "5cc80f53e4a949000e1ea4f8": 21, | ||||
|             "5cc80f67e4a949035e43bbba": 15, | ||||
|             "5cc80f38e4a949001152b560": 12 | ||||
|         }, | ||||
|         "Caliber68x51": { | ||||
|             "6529302b8c26af6326029fb7": 10, | ||||
|             "6529243824cbe3c74a05e5c1": 5 | ||||
|         }, | ||||
|         "Caliber762x25TT": { | ||||
|             "5736026a245977644601dc61": 5, | ||||
|             "573603c924597764442bd9cb": 10, | ||||
|             "573603562459776430731618": 10 | ||||
|         }, | ||||
|         "Caliber762x35": { | ||||
|             "6196365d58ef8c428c287da1": 7, | ||||
|             "5fbe3ffdf8b6a877a729ea82": 6, | ||||
|             "619636be6db0f2477964e710": 23, | ||||
|             "64b8725c4b75259c590fa899": 20, | ||||
|             "5fd20ff893a8961fc660a954": 9 | ||||
|         }, | ||||
|         "Caliber762x39": { | ||||
|             "59e4cf5286f7741778269d8a": 4, | ||||
|             "5656d7c34bdc2d9d198b4587": 28, | ||||
|             "64b7af434b75259c590fa893": 33, | ||||
|             "59e0d99486f7744a32234762": 20, | ||||
|             "601aa3d2b2bcb34913271e6d": 12 | ||||
|         }, | ||||
|         "Caliber762x51": { | ||||
|             "5e023e53d4353e3302577c4c": 6, | ||||
|             "58dd3ad986f77403051cba8f": 27, | ||||
|             "5a608bf24f39f98ffc77720e": 19, | ||||
|             "5a6086ea4f39f99cd479502f": 9, | ||||
|             "5efb0c1bd79ff02a1f5e68d9": 2 | ||||
|         }, | ||||
|         "Caliber762x54R": { | ||||
|             "5e023cf8186a883be655e54f": 3, | ||||
|             "5887431f2459777e1612938f": 20, | ||||
|             "59e77a2386f7742ee578960a": 25, | ||||
|             "5e023d34e8a400319a28ed44": 22, | ||||
|             "560d61e84bdc2da74d8b4571": 15, | ||||
|             "5e023d48186a883be655e551": 10 | ||||
|         }, | ||||
|         "Caliber86x70": { | ||||
|             "5fc382b6d6fa9c00c571bbc3": 5, | ||||
|             "5fc382c1016cce60e8341b20": 8, | ||||
|             "5fc275cf85fd526b824a571a": 8, | ||||
|             "5fc382a9d724d907e2077dab": 5 | ||||
|         }, | ||||
|         "Caliber9x18PM": { | ||||
|             "57371e4124597760ff7b25f1": 3, | ||||
|             "5737201124597760fc4431f1": 5, | ||||
|             "573720e02459776143012541": 12, | ||||
|             "573718ba2459775a75491131": 18, | ||||
|             "57371aab2459775a77142f22": 12, | ||||
|             "573719df2459775a626ccbc2": 10 | ||||
|         }, | ||||
|         "Caliber9x19PARA": { | ||||
|             "5c0d56a986f774449d5de529": 9, | ||||
|             "5efb0e16aeb21837e749c7ff": 5, | ||||
|             "5a3c16fe86f77452b62de32a": 4, | ||||
|             "56d59d3ad2720bdb418b4577": 18, | ||||
|             "5c925fa22e221601da359b7b": 22, | ||||
|             "5efb0da7a29a85116f6ea05f": 9 | ||||
|         }, | ||||
|         "Caliber9x21": { | ||||
|             "5a269f97c4a282000b151807": 8, | ||||
|             "6576f93989f0062e741ba952": 18, | ||||
|             "5a26ac0ec4a28200741e1e18": 18, | ||||
|             "6576f4708ca9c4381d16cd9d": 8 | ||||
|         }, | ||||
|         "Caliber9x33R": { | ||||
|             "62330c18744e5e31df12f516": 9, | ||||
|             "62330b3ed4dc74626d570b95": 6 | ||||
|         }, | ||||
|         "Caliber9x39": { | ||||
|             "5c0d668f86f7747ccb7f13b2": 9, | ||||
|             "61962d879bb3d20b0946d385": 25, | ||||
|             "57a0e5022459774d1673f889": 25, | ||||
|             "5c0d688c86f77413ae3407b2": 12 | ||||
|         }, | ||||
|         "Caliber127x33": { | ||||
|             "66a0d1c87d0d369e270bb9de": 3, | ||||
|             "66a0d1f88486c69fce00fdf6": 30, | ||||
|             "66a0d1e0ed648d72fe064d06": 25,  | ||||
|             "668fe62ac62660a5d8071446": 12 | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,473 @@ | |||
| { | ||||
|     "pmcUSEC": { | ||||
|         "appearance": { | ||||
|             "body": { | ||||
|                 "5cde95d97d6c8b647a3769b0": 1, | ||||
|                 "66546f823b51a4d21e0d17d7": 1, | ||||
|                 "5d1f56a686f7744bce0ee9eb": 1, | ||||
|                 "5d1f56c686f7744bcd13459c": 2, | ||||
|                 "637b945722e2a933ed0e33c8": 2, | ||||
|                 "6571cb0923aa6d72760a7f8f": 2, | ||||
|                 "5fd3e9f71b735718c25cd9f8": 2, | ||||
|                 "642d9bbf6c06444bf7033855": 2, | ||||
|                 "6033a35f80ae5e2f970ba6bb": 3, | ||||
|                 "66043728333907134309d647": 3, | ||||
|                 "5d1f56e486f7744bce0ee9ed": 3, | ||||
|                 "6295e8c3e08ed747e64aea00": 3, | ||||
|                 "642c18b8a6a0660b560fb31c": 3, | ||||
|                 "66acbe49dc61999a6a03d4d6": 3, | ||||
|                 "5d4da0cb86f77450fe0a6629": 5, | ||||
|                 "660437e57502eca33a08caca": 5, | ||||
|                 "5fcf63da5c287f01f22bf245": 5, | ||||
|                 "618109c96d7ca35d076b3363": 5, | ||||
|                 "5d1f56f186f7744bcb0acd1a": 5 | ||||
|             }, | ||||
|             "feet": { | ||||
|                 "5cde95ef7d6c8b04713c4f2d": 1, | ||||
|                 "5d1f58ed86f7744bcb0acd1c": 1, | ||||
|                 "5d1f590486f7744bcd13459e": 2, | ||||
|                 "642d4d8eb6b75d4c89077cf9": 2, | ||||
|                 "6033a3fee29c9f6c9b14e74e": 2, | ||||
|                 "5fcf940bce1ba36a513bb9cc": 3, | ||||
|                 "660436487502eca33a08cac8": 3, | ||||
|                 "6571cad4c8673f00290f5657": 3, | ||||
|                 "637ba17aa10a96c2b605dbc2": 3, | ||||
|                 "5d1f591186f7744bcc048755": 3, | ||||
|                 "6295e944e9de5e7b3751c4da": 3, | ||||
|                 "642c19360a69698d1b049e12": 3, | ||||
|                 "66acc8f719271bd6d00dec0b": 3, | ||||
|                 "660436a810bcdf80ff0e9f78": 5, | ||||
|                 "617c02e24013b06b0b78df80": 5, | ||||
|                 "5d1f593286f7743014162044": 5, | ||||
|                 "5d1f592286f7743f8362bcdb": 5 | ||||
|             }, | ||||
|             "hands": { | ||||
|                 "5cde95fa7d6c8b04737c2d13": 1 | ||||
|             }, | ||||
|             "head": { | ||||
|                 "5cde96047d6c8b20b577f016": 1, | ||||
|                 "5fdb4139e4ed5b5ea251e4ed": 1, | ||||
|                 "5fdb5950f5264a66150d1c6e": 1, | ||||
|                 "60a6aa8fd559ae040d0d951f": 1, | ||||
|                 "619f9e338858a474c8685cc9": 1, | ||||
|                 "62aca6a1310e67685a2fc2e7": 1, | ||||
|                 "6574aabee0423b9ebe0c79cf": 1 | ||||
|             } | ||||
|         } | ||||
|     }, | ||||
|     "pmcBEAR": { | ||||
|         "appearance": { | ||||
|             "body": { | ||||
|                 "5cc0858d14c02e000c6bea66": 1, | ||||
|                 "66546f823b51a4d21e0d17d7": 1, | ||||
|                 "5d1f565786f7743f8362bcd5": 1, | ||||
|                 "5fce3e0cfe40296c1d5fd782": 2, | ||||
|                 "6377266693a3b4967208e42b": 2, | ||||
|                 "5d1f564b86f7744bcb0acd16": 2, | ||||
|                 "6295e698e9de5e7b3751c47a": 2, | ||||
|                 "642e8ae07e17c882400c4f87": 2, | ||||
|                 "5d1f568486f7744bca3f0b98": 2, | ||||
|                 "657058fddf9b3231400e9188": 3, | ||||
|                 "6033a31e9ec839204e6a2f3e": 3, | ||||
|                 "66043cc27502eca33a08cad0": 3, | ||||
|                 "5fce3e47fe40296c1d5fd784": 3, | ||||
|                 "642ed297ac11c9eaf10d87e8": 3, | ||||
|                 "66acec1dc94f4bf5bc063a16": 3, | ||||
|                 "5d1f567786f7744bcc04874f": 5, | ||||
|                 "660440d2c8949a435906e43a": 5, | ||||
|                 "617bca4b4013b06b0b78df2a": 5, | ||||
|                 "5d1f566d86f7744bcd13459a": 5 | ||||
|             }, | ||||
|             "feet": { | ||||
|                 "5cc085bb14c02e000e67a5c5": 1, | ||||
|                 "5d1f58bd86f7744bce0ee9ef": 1, | ||||
|                 "6377315993a3b4967208e437": 2, | ||||
|                 "5d1f588e86f7744bcc048753": 2, | ||||
|                 "65707a89f5a6f1412f0c5f7b": 2, | ||||
|                 "642ed40af5bdf1c04e01952e": 2, | ||||
|                 "5fce3e965a9f8c40685693bc": 2, | ||||
|                 "6295e63de08ed747e64ae991": 3, | ||||
|                 "66043cf87502eca33a08cad2": 3, | ||||
|                 "6033a3d8ed2e0509b15f9031": 3, | ||||
|                 "5d1f58cb86f7744bca3f0b9a": 3, | ||||
|                 "5d1f58a086f7743f8362bcd9": 3, | ||||
|                 "642e71620a69698d1b049f0a": 3, | ||||
|                 "66acebd4ede86671bb09584b": 3, | ||||
|                 "66043d7ac8949a435906e434": 5, | ||||
|                 "5d1f58ab86f7743014162042": 5, | ||||
|                 "617be9e4e02b3b3fa50fa8f2": 5 | ||||
|             }, | ||||
|             "hands": { | ||||
|                 "5cc0876314c02e000c6bea6b": 1 | ||||
|             }, | ||||
|             "head": { | ||||
|                 "5cc084dd14c02e000b0550a3": 1, | ||||
|                 "5fdb50bb2b730a787b3f78cf": 1, | ||||
|                 "5fdb7571e4ed5b5ea251e529": 1, | ||||
|                 "60a6aaad42fd2735e4589978": 1, | ||||
|                 "619f94f5b90286142b59d45f": 1, | ||||
|                 "62a9e7d15ea3b87d6f642a28": 1, | ||||
|                 "6574aa9a1b144de18c0fba45": 1 | ||||
|             } | ||||
|         } | ||||
|     }, | ||||
|     "springEarly": { | ||||
|         "pmcUSEC": { | ||||
|             "appearance": { | ||||
|                 "body": { | ||||
|                     "5d1f56c686f7744bcd13459c": 1, | ||||
|                     "5fd3e9f71b735718c25cd9f8": 1, | ||||
|                     "66043728333907134309d647": 1, | ||||
|                     "66acbe49dc61999a6a03d4d6": 1, | ||||
|                     "660437e57502eca33a08caca": 1, | ||||
|                     "5d1f56f186f7744bcb0acd1a": 1, | ||||
|                     "5d1f56ff86f7743f8362bcd7": 1, | ||||
|                     "5d1f56a686f7744bce0ee9eb": 2, | ||||
|                     "5e9da17386f774054b6f79a3": 2, | ||||
|                     "5e4bb35286f77406a511c9bc": 2, | ||||
|                     "5d1f56e486f7744bce0ee9ed": 2 | ||||
|                 }, | ||||
|                 "feet": { | ||||
|                     "642d4d8eb6b75d4c89077cf9": 1, | ||||
|                     "5fcf940bce1ba36a513bb9cc": 1, | ||||
|                     "66acc8f719271bd6d00dec0b": 1, | ||||
|                     "6295e944e9de5e7b3751c4da": 1, | ||||
|                     "5d1f592286f7743f8362bcdb": 1, | ||||
|                     "5e4bb3b586f77406812bd579": 1, | ||||
|                     "5d1f590486f7744bcd13459e": 3, | ||||
|                     "5d1f58ed86f7744bcb0acd1c": 3 | ||||
|                 }, | ||||
|                 "hands": { | ||||
|                     "5cde95fa7d6c8b04737c2d13": 1 | ||||
|                 }, | ||||
|                 "head": { | ||||
|                     "5cde96047d6c8b20b577f016": 1, | ||||
|                     "5fdb4139e4ed5b5ea251e4ed": 1, | ||||
|                     "5fdb5950f5264a66150d1c6e": 1, | ||||
|                     "60a6aa8fd559ae040d0d951f": 1, | ||||
|                     "619f9e338858a474c8685cc9": 1, | ||||
|                     "62aca6a1310e67685a2fc2e7": 1, | ||||
|                     "6574aabee0423b9ebe0c79cf": 1 | ||||
|                 } | ||||
|             } | ||||
|         }, | ||||
|         "pmcBEAR": { | ||||
|             "appearance": { | ||||
|                 "body": { | ||||
|                     "657058fddf9b3231400e9188": 1, | ||||
|                     "6033a31e9ec839204e6a2f3e": 1, | ||||
|                     "5d1f567786f7744bcc04874f": 1, | ||||
|                     "5e9d9fa986f774054d6b89f2": 1, | ||||
|                     "5f5e401747344c2e4f6c42c5": 1, | ||||
|                     "642e8ae07e17c882400c4f87": 2, | ||||
|                     "5d1f568486f7744bca3f0b98": 2, | ||||
|                     "66acec1dc94f4bf5bc063a16": 2, | ||||
|                     "5e4bb31586f7740695730568": 2 | ||||
|                 }, | ||||
|                 "feet": { | ||||
|                     "5d1f58bd86f7744bce0ee9ef": 1, | ||||
|                     "6377315993a3b4967208e437": 1, | ||||
|                     "66043cf87502eca33a08cad2": 1, | ||||
|                     "5d1f58cb86f7744bca3f0b9a": 1, | ||||
|                     "5d1f58a086f7743f8362bcd9": 1, | ||||
|                     "617be9e4e02b3b3fa50fa8f2": 1, | ||||
|                     "5f5e40400bc58666c37e7819": 1, | ||||
|                     "66acebd4ede86671bb09584b": 3, | ||||
|                     "5d1f58ab86f7743014162042": 3 | ||||
|                 }, | ||||
|                 "hands": { | ||||
|                     "5cc0876314c02e000c6bea6b": 1 | ||||
|                 }, | ||||
|                 "head": { | ||||
|                     "5cc084dd14c02e000b0550a3": 1, | ||||
|                     "5fdb50bb2b730a787b3f78cf": 1, | ||||
|                     "5fdb7571e4ed5b5ea251e529": 1, | ||||
|                     "60a6aaad42fd2735e4589978": 1, | ||||
|                     "619f94f5b90286142b59d45f": 1, | ||||
|                     "62a9e7d15ea3b87d6f642a28": 1, | ||||
|                     "6574aa9a1b144de18c0fba45": 1 | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     }, | ||||
|     "spring": { | ||||
|         "pmcUSEC": { | ||||
|             "appearance": { | ||||
|                 "body": { | ||||
|                     "5cde95d97d6c8b647a3769b0": 1, | ||||
|                     "5fd3e9f71b735718c25cd9f8": 1, | ||||
|                     "66043728333907134309d647": 1, | ||||
|                     "5d4da0cb86f77450fe0a6629": 1, | ||||
|                     "5d1f56f186f7744bcb0acd1a": 1, | ||||
|                     "5f5e4075df4f3100376a8138": 1 | ||||
|                 }, | ||||
|                 "feet": { | ||||
|                     "5cde95ef7d6c8b04713c4f2d": 1, | ||||
|                     "6033a3fee29c9f6c9b14e74e": 1, | ||||
|                     "660436487502eca33a08cac8": 1, | ||||
|                     "6571cad4c8673f00290f5657": 1, | ||||
|                     "66acc8f719271bd6d00dec0b": 1, | ||||
|                     "5d1f592286f7743f8362bcdb": 1, | ||||
|                     "642d6941ff5ecad7810a8a61": 1, | ||||
|                     "5e9dcadd86f7743e20652f23": 1 | ||||
|                 }, | ||||
|                 "hands": { | ||||
|                     "5cde95fa7d6c8b04737c2d13": 1 | ||||
|                 }, | ||||
|                 "head": { | ||||
|                     "5cde96047d6c8b20b577f016": 1, | ||||
|                     "5fdb4139e4ed5b5ea251e4ed": 1, | ||||
|                     "5fdb5950f5264a66150d1c6e": 1, | ||||
|                     "60a6aa8fd559ae040d0d951f": 1, | ||||
|                     "619f9e338858a474c8685cc9": 1, | ||||
|                     "62aca6a1310e67685a2fc2e7": 1, | ||||
|                     "6574aabee0423b9ebe0c79cf": 1 | ||||
|                 } | ||||
|             } | ||||
|         }, | ||||
|         "pmcBEAR": { | ||||
|             "appearance": { | ||||
|                 "body": { | ||||
|                     "5cc0858d14c02e000c6bea66": 1, | ||||
|                     "5d1f564b86f7744bcb0acd16": 1, | ||||
|                     "6295e698e9de5e7b3751c47a": 1, | ||||
|                     "6033a31e9ec839204e6a2f3e": 1, | ||||
|                     "5fce3e47fe40296c1d5fd784": 1, | ||||
|                     "617bca4b4013b06b0b78df2a": 1, | ||||
|                     "5df89f1f86f77412631087ea": 1 | ||||
|                 }, | ||||
|                 "feet": { | ||||
|                     "5cc085bb14c02e000e67a5c5": 1, | ||||
|                     "5d1f588e86f7744bcc048753": 1, | ||||
|                     "66043cf87502eca33a08cad2": 1, | ||||
|                     "6033a3d8ed2e0509b15f9031": 1, | ||||
|                     "642e71620a69698d1b049f0a": 1, | ||||
|                     "617be9e4e02b3b3fa50fa8f2": 1, | ||||
|                     "642eea6f881906a7fe086841": 1, | ||||
|                     "5df89f8f86f77412672a1e38": 1, | ||||
|                     "5e9dc97c86f774054c19ac9a": 1, | ||||
|                     "5e4bb39386f774067f79de05": 1 | ||||
|                 }, | ||||
|                 "hands": { | ||||
|                     "5cc0876314c02e000c6bea6b": 1 | ||||
|                 }, | ||||
|                 "head": { | ||||
|                     "5cc084dd14c02e000b0550a3": 1, | ||||
|                     "5fdb50bb2b730a787b3f78cf": 1, | ||||
|                     "5fdb7571e4ed5b5ea251e529": 1, | ||||
|                     "60a6aaad42fd2735e4589978": 1, | ||||
|                     "619f94f5b90286142b59d45f": 1, | ||||
|                     "62a9e7d15ea3b87d6f642a28": 1, | ||||
|                     "6574aa9a1b144de18c0fba45": 1 | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     }, | ||||
|     "summer": { | ||||
|         "pmcUSEC": { | ||||
|             "appearance": { | ||||
|                 "body": { | ||||
|                     "5cde95d97d6c8b647a3769b0": 1, | ||||
|                     "5d1f56c686f7744bcd13459c": 1, | ||||
|                     "5fd3e9f71b735718c25cd9f8": 1, | ||||
|                     "66043728333907134309d647": 1, | ||||
|                     "5d4da0cb86f77450fe0a6629": 1, | ||||
|                     "66acbe49dc61999a6a03d4d6": 1, | ||||
|                     "64ef3efdb63b74469b6c1499": 1, | ||||
|                     "642c18b8a6a0660b560fb31c": 1, | ||||
|                     "5d1f56f186f7744bcb0acd1a": 1, | ||||
|                     "5f5e4075df4f3100376a8138": 1 | ||||
|                 }, | ||||
|                 "feet": { | ||||
|                     "5cde95ef7d6c8b04713c4f2d": 1, | ||||
|                     "6033a3fee29c9f6c9b14e74e": 1, | ||||
|                     "660436487502eca33a08cac8": 1, | ||||
|                     "6571cad4c8673f00290f5657": 1, | ||||
|                     "66acc8f719271bd6d00dec0b": 1, | ||||
|                     "5d1f593286f7743014162044": 1, | ||||
|                     "5d1f592286f7743f8362bcdb": 1, | ||||
|                     "642d6941ff5ecad7810a8a61": 1, | ||||
|                     "5e9dcadd86f7743e20652f23": 1 | ||||
|                 }, | ||||
|                 "hands": { | ||||
|                     "5cde95fa7d6c8b04737c2d13": 1 | ||||
|                 }, | ||||
|                 "head": { | ||||
|                     "5cde96047d6c8b20b577f016": 1, | ||||
|                     "5fdb4139e4ed5b5ea251e4ed": 1, | ||||
|                     "5fdb5950f5264a66150d1c6e": 1, | ||||
|                     "60a6aa8fd559ae040d0d951f": 1, | ||||
|                     "619f9e338858a474c8685cc9": 1, | ||||
|                     "62aca6a1310e67685a2fc2e7": 1, | ||||
|                     "6574aabee0423b9ebe0c79cf": 1 | ||||
|                 } | ||||
|             } | ||||
|         }, | ||||
|         "pmcBEAR": { | ||||
|             "appearance": { | ||||
|                 "body": { | ||||
|                     "5cc0858d14c02e000c6bea66": 1, | ||||
|                     "5d1f564b86f7744bcb0acd16": 1, | ||||
|                     "6295e698e9de5e7b3751c47a": 1, | ||||
|                     "6033a31e9ec839204e6a2f3e": 1, | ||||
|                     "5fce3e47fe40296c1d5fd784": 1, | ||||
|                     "617bca4b4013b06b0b78df2a": 1, | ||||
|                     "64ef3efdb63b74469b6c1499": 1, | ||||
|                     "5df89f1f86f77412631087ea": 1, | ||||
|                     "5e9d9fa986f774054d6b89f2": 1 | ||||
|                 }, | ||||
|                 "feet": { | ||||
|                     "5cc085bb14c02e000e67a5c5": 1, | ||||
|                     "5d1f588e86f7744bcc048753": 1, | ||||
|                     "66043cf87502eca33a08cad2": 1, | ||||
|                     "6033a3d8ed2e0509b15f9031": 1, | ||||
|                     "642e71620a69698d1b049f0a": 1, | ||||
|                     "617be9e4e02b3b3fa50fa8f2": 1, | ||||
|                     "642eea6f881906a7fe086841": 1, | ||||
|                     "5df89f8f86f77412672a1e38": 1, | ||||
|                     "5e9dc97c86f774054c19ac9a": 1, | ||||
|                     "5e4bb39386f774067f79de05": 1 | ||||
|                 }, | ||||
|                 "hands": { | ||||
|                     "5cc0876314c02e000c6bea6b": 1 | ||||
|                 }, | ||||
|                 "head": { | ||||
|                     "5cc084dd14c02e000b0550a3": 1, | ||||
|                     "5fdb50bb2b730a787b3f78cf": 1, | ||||
|                     "5fdb7571e4ed5b5ea251e529": 1, | ||||
|                     "60a6aaad42fd2735e4589978": 1, | ||||
|                     "619f94f5b90286142b59d45f": 1, | ||||
|                     "62a9e7d15ea3b87d6f642a28": 1, | ||||
|                     "6574aa9a1b144de18c0fba45": 1 | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     }, | ||||
|     "autumn": { | ||||
|         "pmcUSEC": { | ||||
|             "appearance": { | ||||
|                 "body": { | ||||
|                     "5d1f56c686f7744bcd13459c": 1, | ||||
|                     "637b945722e2a933ed0e33c8": 1, | ||||
|                     "6571cb0923aa6d72760a7f8f": 1, | ||||
|                     "6033a35f80ae5e2f970ba6bb": 1, | ||||
|                     "5d1f56e486f7744bce0ee9ed": 1, | ||||
|                     "66acbe49dc61999a6a03d4d6": 1, | ||||
|                     "660437e57502eca33a08caca": 1, | ||||
|                     "64ef3efdb63b74469b6c1499": 1, | ||||
|                     "5d1f56ff86f7743f8362bcd7": 1 | ||||
|                 }, | ||||
|                 "feet": { | ||||
|                     "642d4d8eb6b75d4c89077cf9": 1, | ||||
|                     "5fcf940bce1ba36a513bb9cc": 1, | ||||
|                     "637ba17aa10a96c2b605dbc2": 1, | ||||
|                     "6295e944e9de5e7b3751c4da": 1, | ||||
|                     "5e4bb3b586f77406812bd579": 1, | ||||
|                     "5f5e40a06760b4138443b341": 1 | ||||
|                 }, | ||||
|                 "hands": { | ||||
|                     "5cde95fa7d6c8b04737c2d13": 1 | ||||
|                 }, | ||||
|                 "head": { | ||||
|                     "5cde96047d6c8b20b577f016": 1, | ||||
|                     "5fdb4139e4ed5b5ea251e4ed": 1, | ||||
|                     "5fdb5950f5264a66150d1c6e": 1, | ||||
|                     "60a6aa8fd559ae040d0d951f": 1, | ||||
|                     "619f9e338858a474c8685cc9": 1, | ||||
|                     "62aca6a1310e67685a2fc2e7": 1, | ||||
|                     "6574aabee0423b9ebe0c79cf": 1 | ||||
|                 } | ||||
|             } | ||||
|         }, | ||||
|         "pmcBEAR": { | ||||
|             "appearance": { | ||||
|                 "body": { | ||||
|                     "6377266693a3b4967208e42b": 1, | ||||
|                     "5d1f568486f7744bca3f0b98": 1, | ||||
|                     "657058fddf9b3231400e9188": 1, | ||||
|                     "642ed297ac11c9eaf10d87e8": 1, | ||||
|                     "5d1f567786f7744bcc04874f": 1, | ||||
|                     "64ef3efdb63b74469b6c1499": 1, | ||||
|                     "6430119aac11c9eaf10d881b": 1, | ||||
|                     "5f5e401747344c2e4f6c42c5": 1 | ||||
|                 }, | ||||
|                 "feet": { | ||||
|                     "5d1f58bd86f7744bce0ee9ef": 1, | ||||
|                     "6377315993a3b4967208e437": 1, | ||||
|                     "642ed40af5bdf1c04e01952e": 1, | ||||
|                     "6295e63de08ed747e64ae991": 1, | ||||
|                     "5d1f58a086f7743f8362bcd9": 1, | ||||
|                     "66043d7ac8949a435906e434": 1, | ||||
|                     "5d1f58ab86f7743014162042": 1, | ||||
|                     "5f5e40400bc58666c37e7819": 1 | ||||
|                 }, | ||||
|                 "hands": { | ||||
|                     "5cc0876314c02e000c6bea6b": 1 | ||||
|                 }, | ||||
|                 "head": { | ||||
|                     "5cc084dd14c02e000b0550a3": 1, | ||||
|                     "5fdb50bb2b730a787b3f78cf": 1, | ||||
|                     "5fdb7571e4ed5b5ea251e529": 1, | ||||
|                     "60a6aaad42fd2735e4589978": 1, | ||||
|                     "619f94f5b90286142b59d45f": 1, | ||||
|                     "62a9e7d15ea3b87d6f642a28": 1, | ||||
|                     "6574aa9a1b144de18c0fba45": 1 | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     }, | ||||
|     "winter": { | ||||
|         "pmcUSEC": { | ||||
|             "appearance": { | ||||
|                 "body": { | ||||
|                     "5d1f56a686f7744bce0ee9eb": 1, | ||||
|                     "5e9da17386f774054b6f79a3": 1, | ||||
|                     "5e4bb35286f77406a511c9bc": 1, | ||||
|                     "5d1f56e486f7744bce0ee9ed": 1 | ||||
|                 }, | ||||
|                 "feet": { | ||||
|                     "5d1f590486f7744bcd13459e": 1, | ||||
|                     "5d1f58ed86f7744bcb0acd1c": 1 | ||||
|                 }, | ||||
|                 "hands": { | ||||
|                     "5cde95fa7d6c8b04737c2d13": 1 | ||||
|                 }, | ||||
|                 "head": { | ||||
|                     "5cde96047d6c8b20b577f016": 1, | ||||
|                     "5fdb4139e4ed5b5ea251e4ed": 1, | ||||
|                     "5fdb5950f5264a66150d1c6e": 1, | ||||
|                     "60a6aa8fd559ae040d0d951f": 1, | ||||
|                     "619f9e338858a474c8685cc9": 1, | ||||
|                     "62aca6a1310e67685a2fc2e7": 1, | ||||
|                     "6574aabee0423b9ebe0c79cf": 1 | ||||
|                 } | ||||
|             } | ||||
|         }, | ||||
|         "pmcBEAR": { | ||||
|             "appearance": { | ||||
|                 "body": { | ||||
|                     "642e8ae07e17c882400c4f87": 1, | ||||
|                     "5d1f568486f7744bca3f0b98": 1, | ||||
|                     "66acec1dc94f4bf5bc063a16": 1, | ||||
|                     "5e4bb31586f7740695730568": 1 | ||||
|                 }, | ||||
|                 "feet": { | ||||
|                     "66acebd4ede86671bb09584b": 1, | ||||
|                     "5d1f58ab86f7743014162042": 1 | ||||
|                 }, | ||||
|                 "hands": { | ||||
|                     "5cc0876314c02e000c6bea6b": 1 | ||||
|                 }, | ||||
|                 "head": { | ||||
|                     "5cc084dd14c02e000b0550a3": 1, | ||||
|                     "5fdb50bb2b730a787b3f78cf": 1, | ||||
|                     "5fdb7571e4ed5b5ea251e529": 1, | ||||
|                     "60a6aaad42fd2735e4589978": 1, | ||||
|                     "619f94f5b90286142b59d45f": 1, | ||||
|                     "62a9e7d15ea3b87d6f642a28": 1, | ||||
|                     "6574aa9a1b144de18c0fba45": 1 | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							|  | @ -0,0 +1,456 @@ | |||
| {     | ||||
|     "scavAmmo": { | ||||
|         "Caliber1143x23ACP": { | ||||
|             "5efb0fc6aeb21837e749c801": 1, | ||||
|             "5efb0d4f4bc50b58e81710f3": 3 | ||||
|         }, | ||||
|         "Caliber127x55": { | ||||
|             "5cadf6e5ae921500113bb973": 1 | ||||
|         }, | ||||
|         "Caliber12g": { | ||||
|             "5d6e6772a4b936088465b17c": 2, | ||||
|             "5d6e6806a4b936088465b17e": 2, | ||||
|             "5d6e67fba4b9361bc73bc779": 2, | ||||
|             "560d5e524bdc2d25448b4571": 2, | ||||
|             "5d6e6869a4b9361c140bcfde": 1, | ||||
|             "5d6e68b3a4b9361bca7e50b5": 1, | ||||
|             "58820d1224597753c90aeb13": 1, | ||||
|             "5d6e68dea4b9361bcc29e659": 1, | ||||
|             "5d6e6891a4b9361bd473feea": 1, | ||||
|             "5d6e68e6a4b9361c140bcfe0": 1, | ||||
|             "5d6e689ca4b9361bc8618956": 1 | ||||
|         }, | ||||
|         "Caliber20g": { | ||||
|             "5d6e695fa4b936359b35d852": 2, | ||||
|             "5d6e69b9a4b9361bc8618958": 2, | ||||
|             "5a38ebd9c4a282000d722a5b": 2, | ||||
|             "5d6e69c7a4b9360b6c0d54e4": 1, | ||||
|             "5d6e6a53a4b9361bd473feec": 1 | ||||
|         }, | ||||
|         "Caliber23x75": { | ||||
|             "5f647f31b6238e5dd066e196": 3, | ||||
|             "5e85a9a6eacf8c039e4e2ac1": 1 | ||||
|         }, | ||||
|         "Caliber366TKM": { | ||||
|             "59e6658b86f77411d949b250": 3, | ||||
|             "59e6542b86f77411dc52a77a": 1 | ||||
|         }, | ||||
|         "Caliber40mmRU": { | ||||
|             "5656eb674bdc2d35148b457c": 1 | ||||
|         }, | ||||
|         "Caliber40x46": { | ||||
|             "5ede4739e0350d05467f73e8": 1, | ||||
|             "5ede47405b097655935d7d16": 1, | ||||
|             "5ede474b0c226a66f5402622": 1, | ||||
|             "5ede475339ee016e8c534742": 1, | ||||
|             "5ede475b549eed7c6d5c18fb": 1, | ||||
|             "5f0c892565703e5c461894e9": 1 | ||||
|         }, | ||||
|         "Caliber46x30": { | ||||
|             "5ba26812d4351e003201fef1": 3, | ||||
|             "5ba26844d4351e00334c9475": 1 | ||||
|         }, | ||||
|         "Caliber545x39": { | ||||
|             "56dff216d2720bbd668b4568": 1, | ||||
|             "56dff338d2720bbd668b4569": 4, | ||||
|             "56dff421d2720b5f5a8b4567": 4, | ||||
|             "56dff4ecd2720b5f5a8b4568": 2, | ||||
|             "56dff4a2d2720bbd668b456a": 4, | ||||
|             "56dff0bed2720bb0668b4567": 3, | ||||
|             "56dff3afd2720bba668b4567": 1 | ||||
|         }, | ||||
|         "Caliber556x45NATO": { | ||||
|             "59e6927d86f77411da468256": 2, | ||||
|             "59e6918f86f7746c9f75e849": 2, | ||||
|             "59e68f6f86f7746c9f75e846": 4, | ||||
|             "59e6920f86f77411d82aa167": 5, | ||||
|             "54527a984bdc2d4e668b4567": 1 | ||||
|         }, | ||||
|         "Caliber57x28": { | ||||
|             "5cc86832d7f00c000d3a6e6c": 2, | ||||
|             "5cc80f79e4a949033c7343b2": 3, | ||||
|             "5cc86840d7f00c002412c56c": 3, | ||||
|             "5cc80f8fe4a949033b0224a2": 1, | ||||
|             "5cc80f53e4a949000e1ea4f8": 1 | ||||
|         }, | ||||
|         "Caliber68x51": { | ||||
|             "6529302b8c26af6326029fb7": 1 | ||||
|         }, | ||||
|         "Caliber762x25TT": { | ||||
|             "573602322459776445391df1": 2, | ||||
|             "573601b42459776410737435": 2, | ||||
|             "5735fdcd2459776445391d61": 1, | ||||
|             "5736026a245977644601dc61": 1 | ||||
|         }, | ||||
|         "Caliber762x35": { | ||||
|             "6196365d58ef8c428c287da1": 1, | ||||
|             "6196364158ef8c428c287d9f": 6, | ||||
|             "5fbe3ffdf8b6a877a729ea82": 3 | ||||
|         }, | ||||
|         "Caliber762x39": { | ||||
|             "59e4d3d286f774176a36250a": 2, | ||||
|             "64b7af734b75259c590fa895": 2, | ||||
|             "64b7af5a8532cf95ee0a0dbd": 6, | ||||
|             "59e4d24686f7741776641ac7": 4, | ||||
|             "59e4cf5286f7741778269d8a": 2, | ||||
|             "5656d7c34bdc2d9d198b4587": 1 | ||||
|         }, | ||||
|         "Caliber762x51": { | ||||
|             "5e023e88277cce2b522ff2b1": 2, | ||||
|             "5e023e6e34d52a55c3304f71": 2, | ||||
|             "5e023e53d4353e3302577c4c": 1 | ||||
|         }, | ||||
|         "Caliber762x54R": { | ||||
|             "64b8f7c241772715af0f9c3d": 2, | ||||
|             "64b8f7b5389d7ffd620ccba2": 2, | ||||
|             "64b8f7968532cf95ee0a0dbf": 2, | ||||
|             "5e023cf8186a883be655e54f": 2, | ||||
|             "5887431f2459777e1612938f": 1 | ||||
|         }, | ||||
|         "Caliber86x70": { | ||||
|             "5fc382b6d6fa9c00c571bbc3": 2, | ||||
|             "5fc382c1016cce60e8341b20": 1 | ||||
|         }, | ||||
|         "Caliber9x18PM": { | ||||
|             "5737218f245977612125ba51": 5, | ||||
|             "57372140245977611f70ee91": 5, | ||||
|             "5737207f24597760ff7b25f2": 2, | ||||
|             "573719762459775a626ccbc1": 3, | ||||
|             "57371f8d24597761006c6a81": 3, | ||||
|             "57371f2b24597761224311f1": 5, | ||||
|             "57371eb62459776125652ac1": 1, | ||||
|             "57371b192459775a9f58a5e0": 1, | ||||
|             "57371e4124597760ff7b25f1": 1 | ||||
|         }, | ||||
|         "Caliber9x19PARA": { | ||||
|             "5efb0e16aeb21837e749c7ff": 1, | ||||
|             "58864a4f2459770fcc257101": 7, | ||||
|             "5a3c16fe86f77452b62de32a": 12, | ||||
|             "5c3df7d588a4501f290594e5": 6, | ||||
|             "64b7bbb74b75259c590fa897": 4, | ||||
|             "56d59d3ad2720bdb418b4577": 2 | ||||
|         }, | ||||
|         "Caliber9x21": { | ||||
|             "5a26ac06c4a282000c5a90a8": 5, | ||||
|             "5a26abfac4a28232980eabff": 3, | ||||
|             "5a269f97c4a282000b151807": 1 | ||||
|         }, | ||||
|         "Caliber9x33R": { | ||||
|             "62330c40bdd19b369e1e53d1": 5, | ||||
|             "62330bfadc5883093563729b": 3, | ||||
|             "62330c18744e5e31df12f516": 1 | ||||
|         }, | ||||
|         "Caliber9x39": { | ||||
|             "6576f96220d53a5b8f3e395e": 7, | ||||
|             "57a0dfb82459774d3078b56c": 5, | ||||
|             "5c0d668f86f7747ccb7f13b2": 1 | ||||
|         }, | ||||
|         "Caliber127x33": { | ||||
|             "66a0d1c87d0d369e270bb9de": 10, | ||||
|             "66a0d1f88486c69fce00fdf6": 1 | ||||
|         } | ||||
|     }, | ||||
|     "pmcAmmo": { | ||||
|         "Caliber1143x23ACP": { | ||||
|             "5ea2a8e200685063ec28c05a": 20, | ||||
|             "5e81f423763d9f754677bf2e": 35, | ||||
|             "5efb0cabfb3e451d70735af5": 45 | ||||
|         }, | ||||
|         "Caliber127x55": { | ||||
|             "5cadf6ddae9215051e1c23b2": 45, | ||||
|             "5cadf6eeae921500134b2799": 55 | ||||
|         }, | ||||
|         "Caliber12g": { | ||||
|             "64b8ee384b75259c590fa89b": 10, | ||||
|             "5d6e6911a4b9361bd5780d52": 25, | ||||
|             "5d6e68c4a4b9361b93413f79": 25, | ||||
|             "5d6e68a8a4b9360b6c0d54e2": 25 | ||||
|         }, | ||||
|         "Caliber20g": { | ||||
|             "5d6e6a5fa4b93614ec501745": 10, | ||||
|             "5d6e6a53a4b9361bd473feec": 10, | ||||
|             "5d6e6a05a4b93618084f58d0": 40, | ||||
|             "5d6e6a42a4b9364f07165f52": 40 | ||||
|         }, | ||||
|         "Caliber23x75": { | ||||
|             "5f647f31b6238e5dd066e196": 20, | ||||
|             "5e85a9a6eacf8c039e4e2ac1": 35, | ||||
|             "5e85aa1a988a8701445df1f5": 35 | ||||
|         }, | ||||
|         "Caliber366TKM": { | ||||
|             "59e655cb86f77411dc52a77b": 10, | ||||
|             "5f0596629e22f464da6bbdd9": 90 | ||||
|         }, | ||||
|         "Caliber40mmRU": { | ||||
|             "5656eb674bdc2d35148b457c": 1 | ||||
|         }, | ||||
|         "Caliber40x46": { | ||||
|             "5ede4739e0350d05467f73e8": 1, | ||||
|             "5ede47405b097655935d7d16": 1, | ||||
|             "5ede474b0c226a66f5402622": 1, | ||||
|             "5ede475339ee016e8c534742": 1, | ||||
|             "5ede475b549eed7c6d5c18fb": 1, | ||||
|             "5f0c892565703e5c461894e9": 1 | ||||
|         }, | ||||
|         "Caliber46x30": { | ||||
|             "5ba26844d4351e00334c9475": 15, | ||||
|             "64b6979341772715af0f9c39": 30, | ||||
|             "5ba2678ad4351e44f824b344": 40, | ||||
|             "5ba26835d4351e0035628ff5": 15 | ||||
|         }, | ||||
|         "Caliber545x39": { | ||||
|             "56dff2ced2720bb4668b4567": 10, | ||||
|             "56dff061d2720bb5668b4567": 30, | ||||
|             "61962b617c6c7b169525f168": 30, | ||||
|             "56dfef82d2720bbd668b4567": 10, | ||||
|             "56dff026d2720bb8668b4567": 5, | ||||
|             "5c0d5e4486f77478390952fe": 5 | ||||
|         }, | ||||
|         "Caliber556x45NATO": { | ||||
|             "60194943740c5d77f6705eea": 5, | ||||
|             "59e6906286f7746c9f75e847": 10, | ||||
|             "54527ac44bdc2d36668b4567": 50, | ||||
|             "59e690b686f7746c9f75e848": 20, | ||||
|             "601949593ae8f707c4608daa": 15 | ||||
|         }, | ||||
|         "Caliber57x28": { | ||||
|             "5cc80f67e4a949035e43bbba": 35, | ||||
|             "5cc80f38e4a949001152b560": 65 | ||||
|         }, | ||||
|         "Caliber68x51": { | ||||
|             "6529302b8c26af6326029fb7": 50, | ||||
|             "6529243824cbe3c74a05e5c1": 50 | ||||
|         }, | ||||
|         "Caliber762x25TT": { | ||||
|             "573603562459776430731618": 10 | ||||
|         }, | ||||
|         "Caliber762x35": { | ||||
|             "5fbe3ffdf8b6a877a729ea82": 15, | ||||
|             "619636be6db0f2477964e710": 40, | ||||
|             "64b8725c4b75259c590fa899": 30, | ||||
|             "5fd20ff893a8961fc660a954": 15 | ||||
|         }, | ||||
|         "Caliber762x39": { | ||||
|             "64b7af434b75259c590fa893": 40, | ||||
|             "59e0d99486f7744a32234762": 45, | ||||
|             "601aa3d2b2bcb34913271e6d": 15 | ||||
|         }, | ||||
|         "Caliber762x51": { | ||||
|             "58dd3ad986f77403051cba8f": 40, | ||||
|             "5a608bf24f39f98ffc77720e": 35, | ||||
|             "5a6086ea4f39f99cd479502f": 20, | ||||
|             "5efb0c1bd79ff02a1f5e68d9": 5 | ||||
|         }, | ||||
|         "Caliber762x54R": { | ||||
|             "5887431f2459777e1612938f": 5, | ||||
|             "59e77a2386f7742ee578960a": 30, | ||||
|             "5e023d34e8a400319a28ed44": 40, | ||||
|             "560d61e84bdc2da74d8b4571": 20, | ||||
|             "5e023d48186a883be655e551": 5 | ||||
|         }, | ||||
|         "Caliber86x70": { | ||||
|             "5fc382b6d6fa9c00c571bbc3": 5, | ||||
|             "5fc382c1016cce60e8341b20": 25, | ||||
|             "5fc275cf85fd526b824a571a": 45, | ||||
|             "5fc382a9d724d907e2077dab": 25 | ||||
|         }, | ||||
|         "Caliber9x18PM": { | ||||
|             "573718ba2459775a75491131": 15, | ||||
|             "57371aab2459775a77142f22": 50, | ||||
|             "573719df2459775a626ccbc2": 35 | ||||
|         }, | ||||
|         "Caliber9x19PARA": { | ||||
|             "5c0d56a986f774449d5de529": 10, | ||||
|             "56d59d3ad2720bdb418b4577": 25, | ||||
|             "5c925fa22e221601da359b7b": 40, | ||||
|             "5efb0da7a29a85116f6ea05f": 25 | ||||
|         }, | ||||
|         "Caliber9x21": { | ||||
|             "5a269f97c4a282000b151807": 20, | ||||
|             "6576f93989f0062e741ba952": 20, | ||||
|             "5a26ac0ec4a28200741e1e18": 15, | ||||
|             "6576f4708ca9c4381d16cd9d": 10 | ||||
|         }, | ||||
|         "Caliber9x33R": { | ||||
|             "62330c18744e5e31df12f516": 10, | ||||
|             "62330b3ed4dc74626d570b95": 10 | ||||
|         }, | ||||
|         "Caliber9x39": { | ||||
|             "61962d879bb3d20b0946d385": 30, | ||||
|             "57a0e5022459774d1673f889": 40, | ||||
|             "5c0d688c86f77413ae3407b2": 30 | ||||
|         }, | ||||
|         "Caliber127x33": { | ||||
|             "66a0d1c87d0d369e270bb9de": 5, | ||||
|             "66a0d1f88486c69fce00fdf6": 20, | ||||
|             "66a0d1e0ed648d72fe064d06": 50, | ||||
|             "668fe62ac62660a5d8071446": 30 | ||||
|         } | ||||
|     }, | ||||
|     "bossAmmo": { | ||||
|         "Caliber1143x23ACP": { | ||||
|             "5ea2a8e200685063ec28c05a": 4, | ||||
|             "5efb0fc6aeb21837e749c801": 1, | ||||
|             "5efb0d4f4bc50b58e81710f3": 10, | ||||
|             "5e81f423763d9f754677bf2e": 18, | ||||
|             "5efb0cabfb3e451d70735af5": 10 | ||||
|         }, | ||||
|         "Caliber127x55": { | ||||
|             "5cadf6e5ae921500113bb973": 3, | ||||
|             "5cadf6ddae9215051e1c23b2": 12, | ||||
|             "5cadf6eeae921500134b2799": 8 | ||||
|         }, | ||||
|         "Caliber12g": { | ||||
|             "5d6e6806a4b936088465b17e": 7, | ||||
|             "64b8ee384b75259c590fa89b": 4, | ||||
|             "5d6e6911a4b9361bd5780d52": 3, | ||||
|             "5c0d591486f7744c505b416f": 5, | ||||
|             "5d6e6891a4b9361bd473feea": 2, | ||||
|             "5d6e68e6a4b9361c140bcfe0": 6, | ||||
|             "5d6e689ca4b9361bc8618956": 8, | ||||
|             "5d6e68c4a4b9361b93413f79": 8, | ||||
|             "5d6e68a8a4b9360b6c0d54e2": 3 | ||||
|         }, | ||||
|         "Caliber20g": { | ||||
|             "5d6e69c7a4b9360b6c0d54e4": 1, | ||||
|             "5d6e6a53a4b9361bd473feec": 4, | ||||
|             "5d6e6a05a4b93618084f58d0": 5, | ||||
|             "5d6e6a42a4b9364f07165f52": 5 | ||||
|         }, | ||||
|         "Caliber23x75": { | ||||
|             "5f647f31b6238e5dd066e196": 2, | ||||
|             "5e85a9a6eacf8c039e4e2ac1": 4, | ||||
|             "5e85aa1a988a8701445df1f5": 4 | ||||
|         }, | ||||
|         "Caliber366TKM": { | ||||
|             "59e6658b86f77411d949b250": 1, | ||||
|             "59e6542b86f77411dc52a77a": 2, | ||||
|             "59e655cb86f77411dc52a77b": 10, | ||||
|             "5f0596629e22f464da6bbdd9": 8 | ||||
|         }, | ||||
|         "Caliber40mmRU": { | ||||
|             "5656eb674bdc2d35148b457c": 1 | ||||
|         }, | ||||
|         "Caliber40x46": { | ||||
|             "5ede4739e0350d05467f73e8": 1, | ||||
|             "5ede47405b097655935d7d16": 1, | ||||
|             "5ede474b0c226a66f5402622": 1, | ||||
|             "5ede475339ee016e8c534742": 1, | ||||
|             "5ede475b549eed7c6d5c18fb": 1, | ||||
|             "5f0c892565703e5c461894e9": 1 | ||||
|         }, | ||||
|         "Caliber46x30": { | ||||
|             "5ba26812d4351e003201fef1": 2, | ||||
|             "5ba26844d4351e00334c9475": 4, | ||||
|             "5ba2678ad4351e44f824b344": 15, | ||||
|             "64b6979341772715af0f9c39": 15, | ||||
|             "5ba26835d4351e0035628ff5": 8 | ||||
|         }, | ||||
|         "Caliber545x39": { | ||||
|             "56dff3afd2720bba668b4567": 6, | ||||
|             "56dff2ced2720bb4668b4567": 12, | ||||
|             "56dff061d2720bb5668b4567": 20, | ||||
|             "61962b617c6c7b169525f168": 12, | ||||
|             "56dfef82d2720bbd668b4567": 9, | ||||
|             "56dff026d2720bb8668b4567": 8, | ||||
|             "5c0d5e4486f77478390952fe": 4 | ||||
|         }, | ||||
|         "Caliber556x45NATO": { | ||||
|             "5c0d5ae286f7741e46554302": 1, | ||||
|             "54527a984bdc2d4e668b4567": 7, | ||||
|             "60194943740c5d77f6705eea": 20, | ||||
|             "59e6906286f7746c9f75e847": 26, | ||||
|             "54527ac44bdc2d36668b4567": 30, | ||||
|             "59e690b686f7746c9f75e848": 7, | ||||
|             "601949593ae8f707c4608daa": 5 | ||||
|         }, | ||||
|         "Caliber57x28": { | ||||
|             "5cc80f8fe4a949033b0224a2": 5, | ||||
|             "5cc80f53e4a949000e1ea4f8": 21, | ||||
|             "5cc80f67e4a949035e43bbba": 15, | ||||
|             "5cc80f38e4a949001152b560": 12 | ||||
|         }, | ||||
|         "Caliber68x51": { | ||||
|             "6529302b8c26af6326029fb7": 10, | ||||
|             "6529243824cbe3c74a05e5c1": 5 | ||||
|         }, | ||||
|         "Caliber762x25TT": { | ||||
|             "5736026a245977644601dc61": 5, | ||||
|             "573603c924597764442bd9cb": 10, | ||||
|             "573603562459776430731618": 10 | ||||
|         }, | ||||
|         "Caliber762x35": { | ||||
|             "6196365d58ef8c428c287da1": 7, | ||||
|             "5fbe3ffdf8b6a877a729ea82": 6, | ||||
|             "619636be6db0f2477964e710": 23, | ||||
|             "64b8725c4b75259c590fa899": 20, | ||||
|             "5fd20ff893a8961fc660a954": 9 | ||||
|         }, | ||||
|         "Caliber762x39": { | ||||
|             "59e4cf5286f7741778269d8a": 4, | ||||
|             "5656d7c34bdc2d9d198b4587": 28, | ||||
|             "64b7af434b75259c590fa893": 33, | ||||
|             "59e0d99486f7744a32234762": 20, | ||||
|             "601aa3d2b2bcb34913271e6d": 12 | ||||
|         }, | ||||
|         "Caliber762x51": { | ||||
|             "5e023e53d4353e3302577c4c": 6, | ||||
|             "58dd3ad986f77403051cba8f": 27, | ||||
|             "5a608bf24f39f98ffc77720e": 19, | ||||
|             "5a6086ea4f39f99cd479502f": 9, | ||||
|             "5efb0c1bd79ff02a1f5e68d9": 2 | ||||
|         }, | ||||
|         "Caliber762x54R": { | ||||
|             "5e023cf8186a883be655e54f": 3, | ||||
|             "5887431f2459777e1612938f": 20, | ||||
|             "59e77a2386f7742ee578960a": 25, | ||||
|             "5e023d34e8a400319a28ed44": 22, | ||||
|             "560d61e84bdc2da74d8b4571": 15, | ||||
|             "5e023d48186a883be655e551": 10 | ||||
|         }, | ||||
|         "Caliber86x70": { | ||||
|             "5fc382b6d6fa9c00c571bbc3": 5, | ||||
|             "5fc382c1016cce60e8341b20": 8, | ||||
|             "5fc275cf85fd526b824a571a": 8, | ||||
|             "5fc382a9d724d907e2077dab": 5 | ||||
|         }, | ||||
|         "Caliber9x18PM": { | ||||
|             "57371e4124597760ff7b25f1": 3, | ||||
|             "5737201124597760fc4431f1": 5, | ||||
|             "573720e02459776143012541": 12, | ||||
|             "573718ba2459775a75491131": 18, | ||||
|             "57371aab2459775a77142f22": 12, | ||||
|             "573719df2459775a626ccbc2": 10 | ||||
|         }, | ||||
|         "Caliber9x19PARA": { | ||||
|             "5c0d56a986f774449d5de529": 9, | ||||
|             "5efb0e16aeb21837e749c7ff": 5, | ||||
|             "5a3c16fe86f77452b62de32a": 4, | ||||
|             "56d59d3ad2720bdb418b4577": 18, | ||||
|             "5c925fa22e221601da359b7b": 22, | ||||
|             "5efb0da7a29a85116f6ea05f": 9 | ||||
|         }, | ||||
|         "Caliber9x21": { | ||||
|             "5a269f97c4a282000b151807": 8, | ||||
|             "6576f93989f0062e741ba952": 18, | ||||
|             "5a26ac0ec4a28200741e1e18": 18, | ||||
|             "6576f4708ca9c4381d16cd9d": 8 | ||||
|         }, | ||||
|         "Caliber9x33R": { | ||||
|             "62330c18744e5e31df12f516": 9, | ||||
|             "62330b3ed4dc74626d570b95": 6 | ||||
|         }, | ||||
|         "Caliber9x39": { | ||||
|             "5c0d668f86f7747ccb7f13b2": 9, | ||||
|             "61962d879bb3d20b0946d385": 25, | ||||
|             "57a0e5022459774d1673f889": 25, | ||||
|             "5c0d688c86f77413ae3407b2": 12 | ||||
|         }, | ||||
|         "Caliber127x33": { | ||||
|             "66a0d1c87d0d369e270bb9de": 3, | ||||
|             "66a0d1f88486c69fce00fdf6": 30, | ||||
|             "66a0d1e0ed648d72fe064d06": 25,  | ||||
|             "668fe62ac62660a5d8071446": 12 | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,493 @@ | |||
| { | ||||
|     "pmcUSEC": { | ||||
|         "appearance": { | ||||
|             "body": { | ||||
|                 "5cde95d97d6c8b647a3769b0": 1, | ||||
|                 "66546f823b51a4d21e0d17d7": 1, | ||||
|                 "5d1f56a686f7744bce0ee9eb": 1, | ||||
|                 "5d1f56c686f7744bcd13459c": 2, | ||||
|                 "637b945722e2a933ed0e33c8": 2, | ||||
|                 "6571cb0923aa6d72760a7f8f": 2, | ||||
|                 "5fd3e9f71b735718c25cd9f8": 2, | ||||
|                 "642d9bbf6c06444bf7033855": 2, | ||||
|                 "6033a35f80ae5e2f970ba6bb": 3, | ||||
|                 "66043728333907134309d647": 3, | ||||
|                 "5d1f56e486f7744bce0ee9ed": 3, | ||||
|                 "6295e8c3e08ed747e64aea00": 3, | ||||
|                 "642c18b8a6a0660b560fb31c": 3, | ||||
|                 "66acbe49dc61999a6a03d4d6": 3, | ||||
|                 "5d4da0cb86f77450fe0a6629": 5, | ||||
|                 "660437e57502eca33a08caca": 5, | ||||
|                 "5fcf63da5c287f01f22bf245": 5, | ||||
|                 "618109c96d7ca35d076b3363": 5, | ||||
|                 "5d1f56f186f7744bcb0acd1a": 5, | ||||
|                 "64ef3efdb63b74469b6c1499": 5, | ||||
|                 "642c5273ff5ecad7810a89d7": 5, | ||||
|                 "5d1f56ff86f7743f8362bcd7": 5, | ||||
|                 "5e4bb35286f77406a511c9bc": 5, | ||||
|                 "5cdea33e7d6c8b0474535dac": 5, | ||||
|                 "5e9da17386f774054b6f79a3": 5 | ||||
|             }, | ||||
|             "feet": { | ||||
|                 "5cde95ef7d6c8b04713c4f2d": 1, | ||||
|                 "5d1f58ed86f7744bcb0acd1c": 1, | ||||
|                 "5d1f590486f7744bcd13459e": 2, | ||||
|                 "642d4d8eb6b75d4c89077cf9": 2, | ||||
|                 "6033a3fee29c9f6c9b14e74e": 2, | ||||
|                 "5fcf940bce1ba36a513bb9cc": 3, | ||||
|                 "660436487502eca33a08cac8": 3, | ||||
|                 "6571cad4c8673f00290f5657": 3, | ||||
|                 "637ba17aa10a96c2b605dbc2": 3, | ||||
|                 "5d1f591186f7744bcc048755": 3, | ||||
|                 "6295e944e9de5e7b3751c4da": 3, | ||||
|                 "642c19360a69698d1b049e12": 3, | ||||
|                 "66acc8f719271bd6d00dec0b": 3, | ||||
|                 "660436a810bcdf80ff0e9f78": 5, | ||||
|                 "617c02e24013b06b0b78df80": 5, | ||||
|                 "5d1f593286f7743014162044": 5, | ||||
|                 "5d1f592286f7743f8362bcdb": 5, | ||||
|                 "642d6941ff5ecad7810a8a61": 5, | ||||
|                 "5df8a08886f7740bfe6df775": 5, | ||||
|                 "5e4bb3b586f77406812bd579": 5, | ||||
|                 "5e9dcadd86f7743e20652f23": 5 | ||||
|             }, | ||||
|             "hands": { | ||||
|                 "5cde95fa7d6c8b04737c2d13": 1 | ||||
|             }, | ||||
|             "head": { | ||||
|                 "5cde96047d6c8b20b577f016": 1, | ||||
|                 "5fdb4139e4ed5b5ea251e4ed": 1, | ||||
|                 "5fdb5950f5264a66150d1c6e": 1, | ||||
|                 "60a6aa8fd559ae040d0d951f": 1, | ||||
|                 "619f9e338858a474c8685cc9": 1, | ||||
|                 "62aca6a1310e67685a2fc2e7": 1, | ||||
|                 "6574aabee0423b9ebe0c79cf": 1 | ||||
|             } | ||||
|         } | ||||
|     }, | ||||
|     "pmcBEAR": { | ||||
|         "appearance": { | ||||
|             "body": { | ||||
|                 "5cc0858d14c02e000c6bea66": 1, | ||||
|                 "66546f823b51a4d21e0d17d7": 1, | ||||
|                 "5d1f565786f7743f8362bcd5": 1, | ||||
|                 "5fce3e0cfe40296c1d5fd782": 2, | ||||
|                 "6377266693a3b4967208e42b": 2, | ||||
|                 "5d1f564b86f7744bcb0acd16": 2, | ||||
|                 "6295e698e9de5e7b3751c47a": 2, | ||||
|                 "642e8ae07e17c882400c4f87": 2, | ||||
|                 "5d1f568486f7744bca3f0b98": 2, | ||||
|                 "657058fddf9b3231400e9188": 3, | ||||
|                 "6033a31e9ec839204e6a2f3e": 3, | ||||
|                 "66043cc27502eca33a08cad0": 3, | ||||
|                 "5fce3e47fe40296c1d5fd784": 3, | ||||
|                 "642ed297ac11c9eaf10d87e8": 3, | ||||
|                 "66acec1dc94f4bf5bc063a16": 3, | ||||
|                 "5d1f567786f7744bcc04874f": 5, | ||||
|                 "660440d2c8949a435906e43a": 5, | ||||
|                 "617bca4b4013b06b0b78df2a": 5, | ||||
|                 "5d1f566d86f7744bcd13459a": 5, | ||||
|                 "64ef3efdb63b74469b6c1499": 5, | ||||
|                 "6430119aac11c9eaf10d881b": 5, | ||||
|                 "5df89f1f86f77412631087ea": 5, | ||||
|                 "5e9d9fa986f774054d6b89f2": 5, | ||||
|                 "5cdea33e7d6c8b0474535dac": 5, | ||||
|                 "5e4bb31586f7740695730568": 5 | ||||
|             }, | ||||
|             "feet": { | ||||
|                 "5cc085bb14c02e000e67a5c5": 1, | ||||
|                 "5d1f58bd86f7744bce0ee9ef": 1, | ||||
|                 "6377315993a3b4967208e437": 2, | ||||
|                 "5d1f588e86f7744bcc048753": 2, | ||||
|                 "65707a89f5a6f1412f0c5f7b": 2, | ||||
|                 "642ed40af5bdf1c04e01952e": 2, | ||||
|                 "5fce3e965a9f8c40685693bc": 2, | ||||
|                 "6295e63de08ed747e64ae991": 3, | ||||
|                 "66043cf87502eca33a08cad2": 3, | ||||
|                 "6033a3d8ed2e0509b15f9031": 3, | ||||
|                 "5d1f58cb86f7744bca3f0b9a": 3, | ||||
|                 "5d1f58a086f7743f8362bcd9": 3, | ||||
|                 "642e71620a69698d1b049f0a": 3, | ||||
|                 "66acebd4ede86671bb09584b": 3, | ||||
|                 "66043d7ac8949a435906e434": 5, | ||||
|                 "5d1f58ab86f7743014162042": 5, | ||||
|                 "617be9e4e02b3b3fa50fa8f2": 5, | ||||
|                 "642eea6f881906a7fe086841": 5, | ||||
|                 "5df89f8f86f77412672a1e38": 5, | ||||
|                 "5e9dc97c86f774054c19ac9a": 5, | ||||
|                 "5e4bb39386f774067f79de05": 5 | ||||
|             }, | ||||
|             "hands": { | ||||
|                 "5cc0876314c02e000c6bea6b": 1 | ||||
|             }, | ||||
|             "head": { | ||||
|                 "5cc084dd14c02e000b0550a3": 1, | ||||
|                 "5fdb50bb2b730a787b3f78cf": 1, | ||||
|                 "5fdb7571e4ed5b5ea251e529": 1, | ||||
|                 "60a6aaad42fd2735e4589978": 1, | ||||
|                 "619f94f5b90286142b59d45f": 1, | ||||
|                 "62a9e7d15ea3b87d6f642a28": 1, | ||||
|                 "6574aa9a1b144de18c0fba45": 1 | ||||
|             } | ||||
|         } | ||||
|     }, | ||||
|     "springEarly": { | ||||
|         "pmcUSEC": { | ||||
|             "appearance": { | ||||
|                 "body": { | ||||
|                     "5d1f56c686f7744bcd13459c": 1, | ||||
|                     "5fd3e9f71b735718c25cd9f8": 1, | ||||
|                     "66043728333907134309d647": 1, | ||||
|                     "66acbe49dc61999a6a03d4d6": 1, | ||||
|                     "660437e57502eca33a08caca": 1, | ||||
|                     "5d1f56f186f7744bcb0acd1a": 1, | ||||
|                     "5d1f56ff86f7743f8362bcd7": 1, | ||||
|                     "5d1f56a686f7744bce0ee9eb": 2, | ||||
|                     "5e9da17386f774054b6f79a3": 2, | ||||
|                     "5e4bb35286f77406a511c9bc": 2, | ||||
|                     "5d1f56e486f7744bce0ee9ed": 2 | ||||
|                 }, | ||||
|                 "feet": { | ||||
|                     "642d4d8eb6b75d4c89077cf9": 1, | ||||
|                     "5fcf940bce1ba36a513bb9cc": 1, | ||||
|                     "66acc8f719271bd6d00dec0b": 1, | ||||
|                     "6295e944e9de5e7b3751c4da": 1, | ||||
|                     "5d1f592286f7743f8362bcdb": 1, | ||||
|                     "5e4bb3b586f77406812bd579": 1, | ||||
|                     "5d1f590486f7744bcd13459e": 3, | ||||
|                     "5d1f58ed86f7744bcb0acd1c": 3 | ||||
|                 }, | ||||
|                 "hands": { | ||||
|                     "5cde95fa7d6c8b04737c2d13": 1 | ||||
|                 }, | ||||
|                 "head": { | ||||
|                     "5cde96047d6c8b20b577f016": 1, | ||||
|                     "5fdb4139e4ed5b5ea251e4ed": 1, | ||||
|                     "5fdb5950f5264a66150d1c6e": 1, | ||||
|                     "60a6aa8fd559ae040d0d951f": 1, | ||||
|                     "619f9e338858a474c8685cc9": 1, | ||||
|                     "62aca6a1310e67685a2fc2e7": 1, | ||||
|                     "6574aabee0423b9ebe0c79cf": 1 | ||||
|                 } | ||||
|             } | ||||
|         }, | ||||
|         "pmcBEAR": { | ||||
|             "appearance": { | ||||
|                 "body": { | ||||
|                     "657058fddf9b3231400e9188": 1, | ||||
|                     "6033a31e9ec839204e6a2f3e": 1, | ||||
|                     "5d1f567786f7744bcc04874f": 1, | ||||
|                     "5e9d9fa986f774054d6b89f2": 1, | ||||
|                     "5f5e401747344c2e4f6c42c5": 1, | ||||
|                     "642e8ae07e17c882400c4f87": 2, | ||||
|                     "5d1f568486f7744bca3f0b98": 2, | ||||
|                     "66acec1dc94f4bf5bc063a16": 2, | ||||
|                     "5e4bb31586f7740695730568": 2 | ||||
|                 }, | ||||
|                 "feet": { | ||||
|                     "5d1f58bd86f7744bce0ee9ef": 1, | ||||
|                     "6377315993a3b4967208e437": 1, | ||||
|                     "66043cf87502eca33a08cad2": 1, | ||||
|                     "5d1f58cb86f7744bca3f0b9a": 1, | ||||
|                     "5d1f58a086f7743f8362bcd9": 1, | ||||
|                     "617be9e4e02b3b3fa50fa8f2": 1, | ||||
|                     "5f5e40400bc58666c37e7819": 1, | ||||
|                     "66acebd4ede86671bb09584b": 3, | ||||
|                     "5d1f58ab86f7743014162042": 3 | ||||
|                 }, | ||||
|                 "hands": { | ||||
|                     "5cc0876314c02e000c6bea6b": 1 | ||||
|                 }, | ||||
|                 "head": { | ||||
|                     "5cc084dd14c02e000b0550a3": 1, | ||||
|                     "5fdb50bb2b730a787b3f78cf": 1, | ||||
|                     "5fdb7571e4ed5b5ea251e529": 1, | ||||
|                     "60a6aaad42fd2735e4589978": 1, | ||||
|                     "619f94f5b90286142b59d45f": 1, | ||||
|                     "62a9e7d15ea3b87d6f642a28": 1, | ||||
|                     "6574aa9a1b144de18c0fba45": 1 | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     }, | ||||
|     "spring": { | ||||
|         "pmcUSEC": { | ||||
|             "appearance": { | ||||
|                 "body": { | ||||
|                     "5cde95d97d6c8b647a3769b0": 1, | ||||
|                     "5fd3e9f71b735718c25cd9f8": 1, | ||||
|                     "66043728333907134309d647": 1, | ||||
|                     "5d4da0cb86f77450fe0a6629": 1, | ||||
|                     "5d1f56f186f7744bcb0acd1a": 1, | ||||
|                     "5f5e4075df4f3100376a8138": 1 | ||||
|                 }, | ||||
|                 "feet": { | ||||
|                     "5cde95ef7d6c8b04713c4f2d": 1, | ||||
|                     "6033a3fee29c9f6c9b14e74e": 1, | ||||
|                     "660436487502eca33a08cac8": 1, | ||||
|                     "6571cad4c8673f00290f5657": 1, | ||||
|                     "66acc8f719271bd6d00dec0b": 1, | ||||
|                     "5d1f592286f7743f8362bcdb": 1, | ||||
|                     "642d6941ff5ecad7810a8a61": 1, | ||||
|                     "5e9dcadd86f7743e20652f23": 1 | ||||
|                 }, | ||||
|                 "hands": { | ||||
|                     "5cde95fa7d6c8b04737c2d13": 1 | ||||
|                 }, | ||||
|                 "head": { | ||||
|                     "5cde96047d6c8b20b577f016": 1, | ||||
|                     "5fdb4139e4ed5b5ea251e4ed": 1, | ||||
|                     "5fdb5950f5264a66150d1c6e": 1, | ||||
|                     "60a6aa8fd559ae040d0d951f": 1, | ||||
|                     "619f9e338858a474c8685cc9": 1, | ||||
|                     "62aca6a1310e67685a2fc2e7": 1, | ||||
|                     "6574aabee0423b9ebe0c79cf": 1 | ||||
|                 } | ||||
|             } | ||||
|         }, | ||||
|         "pmcBEAR": { | ||||
|             "appearance": { | ||||
|                 "body": { | ||||
|                     "5cc0858d14c02e000c6bea66": 1, | ||||
|                     "5d1f564b86f7744bcb0acd16": 1, | ||||
|                     "6295e698e9de5e7b3751c47a": 1, | ||||
|                     "6033a31e9ec839204e6a2f3e": 1, | ||||
|                     "5fce3e47fe40296c1d5fd784": 1, | ||||
|                     "617bca4b4013b06b0b78df2a": 1, | ||||
|                     "5df89f1f86f77412631087ea": 1 | ||||
|                 }, | ||||
|                 "feet": { | ||||
|                     "5cc085bb14c02e000e67a5c5": 1, | ||||
|                     "5d1f588e86f7744bcc048753": 1, | ||||
|                     "66043cf87502eca33a08cad2": 1, | ||||
|                     "6033a3d8ed2e0509b15f9031": 1, | ||||
|                     "642e71620a69698d1b049f0a": 1, | ||||
|                     "617be9e4e02b3b3fa50fa8f2": 1, | ||||
|                     "642eea6f881906a7fe086841": 1, | ||||
|                     "5df89f8f86f77412672a1e38": 1, | ||||
|                     "5e9dc97c86f774054c19ac9a": 1, | ||||
|                     "5e4bb39386f774067f79de05": 1 | ||||
|                 }, | ||||
|                 "hands": { | ||||
|                     "5cc0876314c02e000c6bea6b": 1 | ||||
|                 }, | ||||
|                 "head": { | ||||
|                     "5cc084dd14c02e000b0550a3": 1, | ||||
|                     "5fdb50bb2b730a787b3f78cf": 1, | ||||
|                     "5fdb7571e4ed5b5ea251e529": 1, | ||||
|                     "60a6aaad42fd2735e4589978": 1, | ||||
|                     "619f94f5b90286142b59d45f": 1, | ||||
|                     "62a9e7d15ea3b87d6f642a28": 1, | ||||
|                     "6574aa9a1b144de18c0fba45": 1 | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     }, | ||||
|     "summer": { | ||||
|         "pmcUSEC": { | ||||
|             "appearance": { | ||||
|                 "body": { | ||||
|                     "5cde95d97d6c8b647a3769b0": 1, | ||||
|                     "5d1f56c686f7744bcd13459c": 1, | ||||
|                     "5fd3e9f71b735718c25cd9f8": 1, | ||||
|                     "66043728333907134309d647": 1, | ||||
|                     "5d4da0cb86f77450fe0a6629": 1, | ||||
|                     "66acbe49dc61999a6a03d4d6": 1, | ||||
|                     "64ef3efdb63b74469b6c1499": 1, | ||||
|                     "642c18b8a6a0660b560fb31c": 1, | ||||
|                     "5d1f56f186f7744bcb0acd1a": 1, | ||||
|                     "5f5e4075df4f3100376a8138": 1 | ||||
|                 }, | ||||
|                 "feet": { | ||||
|                     "5cde95ef7d6c8b04713c4f2d": 1, | ||||
|                     "6033a3fee29c9f6c9b14e74e": 1, | ||||
|                     "660436487502eca33a08cac8": 1, | ||||
|                     "6571cad4c8673f00290f5657": 1, | ||||
|                     "66acc8f719271bd6d00dec0b": 1, | ||||
|                     "5d1f593286f7743014162044": 1, | ||||
|                     "5d1f592286f7743f8362bcdb": 1, | ||||
|                     "642d6941ff5ecad7810a8a61": 1, | ||||
|                     "5e9dcadd86f7743e20652f23": 1 | ||||
|                 }, | ||||
|                 "hands": { | ||||
|                     "5cde95fa7d6c8b04737c2d13": 1 | ||||
|                 }, | ||||
|                 "head": { | ||||
|                     "5cde96047d6c8b20b577f016": 1, | ||||
|                     "5fdb4139e4ed5b5ea251e4ed": 1, | ||||
|                     "5fdb5950f5264a66150d1c6e": 1, | ||||
|                     "60a6aa8fd559ae040d0d951f": 1, | ||||
|                     "619f9e338858a474c8685cc9": 1, | ||||
|                     "62aca6a1310e67685a2fc2e7": 1, | ||||
|                     "6574aabee0423b9ebe0c79cf": 1 | ||||
|                 } | ||||
|             } | ||||
|         }, | ||||
|         "pmcBEAR": { | ||||
|             "appearance": { | ||||
|                 "body": { | ||||
|                     "5cc0858d14c02e000c6bea66": 1, | ||||
|                     "5d1f564b86f7744bcb0acd16": 1, | ||||
|                     "6295e698e9de5e7b3751c47a": 1, | ||||
|                     "6033a31e9ec839204e6a2f3e": 1, | ||||
|                     "5fce3e47fe40296c1d5fd784": 1, | ||||
|                     "617bca4b4013b06b0b78df2a": 1, | ||||
|                     "64ef3efdb63b74469b6c1499": 1, | ||||
|                     "5df89f1f86f77412631087ea": 1, | ||||
|                     "5e9d9fa986f774054d6b89f2": 1 | ||||
|                 }, | ||||
|                 "feet": { | ||||
|                     "5cc085bb14c02e000e67a5c5": 1, | ||||
|                     "5d1f588e86f7744bcc048753": 1, | ||||
|                     "66043cf87502eca33a08cad2": 1, | ||||
|                     "6033a3d8ed2e0509b15f9031": 1, | ||||
|                     "642e71620a69698d1b049f0a": 1, | ||||
|                     "617be9e4e02b3b3fa50fa8f2": 1, | ||||
|                     "642eea6f881906a7fe086841": 1, | ||||
|                     "5df89f8f86f77412672a1e38": 1, | ||||
|                     "5e9dc97c86f774054c19ac9a": 1, | ||||
|                     "5e4bb39386f774067f79de05": 1 | ||||
|                 }, | ||||
|                 "hands": { | ||||
|                     "5cc0876314c02e000c6bea6b": 1 | ||||
|                 }, | ||||
|                 "head": { | ||||
|                     "5cc084dd14c02e000b0550a3": 1, | ||||
|                     "5fdb50bb2b730a787b3f78cf": 1, | ||||
|                     "5fdb7571e4ed5b5ea251e529": 1, | ||||
|                     "60a6aaad42fd2735e4589978": 1, | ||||
|                     "619f94f5b90286142b59d45f": 1, | ||||
|                     "62a9e7d15ea3b87d6f642a28": 1, | ||||
|                     "6574aa9a1b144de18c0fba45": 1 | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     }, | ||||
|     "autumn": { | ||||
|         "pmcUSEC": { | ||||
|             "appearance": { | ||||
|                 "body": { | ||||
|                     "5d1f56c686f7744bcd13459c": 1, | ||||
|                     "637b945722e2a933ed0e33c8": 1, | ||||
|                     "6571cb0923aa6d72760a7f8f": 1, | ||||
|                     "6033a35f80ae5e2f970ba6bb": 1, | ||||
|                     "5d1f56e486f7744bce0ee9ed": 1, | ||||
|                     "66acbe49dc61999a6a03d4d6": 1, | ||||
|                     "660437e57502eca33a08caca": 1, | ||||
|                     "64ef3efdb63b74469b6c1499": 1, | ||||
|                     "5d1f56ff86f7743f8362bcd7": 1 | ||||
|                 }, | ||||
|                 "feet": { | ||||
|                     "642d4d8eb6b75d4c89077cf9": 1, | ||||
|                     "5fcf940bce1ba36a513bb9cc": 1, | ||||
|                     "637ba17aa10a96c2b605dbc2": 1, | ||||
|                     "6295e944e9de5e7b3751c4da": 1, | ||||
|                     "5e4bb3b586f77406812bd579": 1, | ||||
|                     "5f5e40a06760b4138443b341": 1 | ||||
|                 }, | ||||
|                 "hands": { | ||||
|                     "5cde95fa7d6c8b04737c2d13": 1 | ||||
|                 }, | ||||
|                 "head": { | ||||
|                     "5cde96047d6c8b20b577f016": 1, | ||||
|                     "5fdb4139e4ed5b5ea251e4ed": 1, | ||||
|                     "5fdb5950f5264a66150d1c6e": 1, | ||||
|                     "60a6aa8fd559ae040d0d951f": 1, | ||||
|                     "619f9e338858a474c8685cc9": 1, | ||||
|                     "62aca6a1310e67685a2fc2e7": 1, | ||||
|                     "6574aabee0423b9ebe0c79cf": 1 | ||||
|                 } | ||||
|             } | ||||
|         }, | ||||
|         "pmcBEAR": { | ||||
|             "appearance": { | ||||
|                 "body": { | ||||
|                     "6377266693a3b4967208e42b": 1, | ||||
|                     "5d1f568486f7744bca3f0b98": 1, | ||||
|                     "657058fddf9b3231400e9188": 1, | ||||
|                     "642ed297ac11c9eaf10d87e8": 1, | ||||
|                     "5d1f567786f7744bcc04874f": 1, | ||||
|                     "64ef3efdb63b74469b6c1499": 1, | ||||
|                     "6430119aac11c9eaf10d881b": 1, | ||||
|                     "5f5e401747344c2e4f6c42c5": 1 | ||||
|                 }, | ||||
|                 "feet": { | ||||
|                     "5d1f58bd86f7744bce0ee9ef": 1, | ||||
|                     "6377315993a3b4967208e437": 1, | ||||
|                     "642ed40af5bdf1c04e01952e": 1, | ||||
|                     "6295e63de08ed747e64ae991": 1, | ||||
|                     "5d1f58a086f7743f8362bcd9": 1, | ||||
|                     "66043d7ac8949a435906e434": 1, | ||||
|                     "5d1f58ab86f7743014162042": 1, | ||||
|                     "5f5e40400bc58666c37e7819": 1 | ||||
|                 }, | ||||
|                 "hands": { | ||||
|                     "5cc0876314c02e000c6bea6b": 1 | ||||
|                 }, | ||||
|                 "head": { | ||||
|                     "5cc084dd14c02e000b0550a3": 1, | ||||
|                     "5fdb50bb2b730a787b3f78cf": 1, | ||||
|                     "5fdb7571e4ed5b5ea251e529": 1, | ||||
|                     "60a6aaad42fd2735e4589978": 1, | ||||
|                     "619f94f5b90286142b59d45f": 1, | ||||
|                     "62a9e7d15ea3b87d6f642a28": 1, | ||||
|                     "6574aa9a1b144de18c0fba45": 1 | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     }, | ||||
|     "winter": { | ||||
|         "pmcUSEC": { | ||||
|             "appearance": { | ||||
|                 "body": { | ||||
|                     "5d1f56a686f7744bce0ee9eb": 1, | ||||
|                     "5e9da17386f774054b6f79a3": 1, | ||||
|                     "5e4bb35286f77406a511c9bc": 1, | ||||
|                     "5d1f56e486f7744bce0ee9ed": 1 | ||||
|                 }, | ||||
|                 "feet": { | ||||
|                     "5d1f590486f7744bcd13459e": 1, | ||||
|                     "5d1f58ed86f7744bcb0acd1c": 1 | ||||
|                 }, | ||||
|                 "hands": { | ||||
|                     "5cde95fa7d6c8b04737c2d13": 1 | ||||
|                 }, | ||||
|                 "head": { | ||||
|                     "5cde96047d6c8b20b577f016": 1, | ||||
|                     "5fdb4139e4ed5b5ea251e4ed": 1, | ||||
|                     "5fdb5950f5264a66150d1c6e": 1, | ||||
|                     "60a6aa8fd559ae040d0d951f": 1, | ||||
|                     "619f9e338858a474c8685cc9": 1, | ||||
|                     "62aca6a1310e67685a2fc2e7": 1, | ||||
|                     "6574aabee0423b9ebe0c79cf": 1 | ||||
|                 } | ||||
|             } | ||||
|         }, | ||||
|         "pmcBEAR": { | ||||
|             "appearance": { | ||||
|                 "body": { | ||||
|                     "642e8ae07e17c882400c4f87": 1, | ||||
|                     "5d1f568486f7744bca3f0b98": 1, | ||||
|                     "66acec1dc94f4bf5bc063a16": 1, | ||||
|                     "5e4bb31586f7740695730568": 1 | ||||
|                 }, | ||||
|                 "feet": { | ||||
|                     "66acebd4ede86671bb09584b": 1, | ||||
|                     "5d1f58ab86f7743014162042": 1 | ||||
|                 }, | ||||
|                 "hands": { | ||||
|                     "5cc0876314c02e000c6bea6b": 1 | ||||
|                 }, | ||||
|                 "head": { | ||||
|                     "5cc084dd14c02e000b0550a3": 1, | ||||
|                     "5fdb50bb2b730a787b3f78cf": 1, | ||||
|                     "5fdb7571e4ed5b5ea251e529": 1, | ||||
|                     "60a6aaad42fd2735e4589978": 1, | ||||
|                     "619f94f5b90286142b59d45f": 1, | ||||
|                     "62a9e7d15ea3b87d6f642a28": 1, | ||||
|                     "6574aa9a1b144de18c0fba45": 1 | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							|  | @ -0,0 +1,446 @@ | |||
| {     | ||||
|     "scavAmmo": { | ||||
|         "Caliber1143x23ACP": { | ||||
|             "5efb0fc6aeb21837e749c801": 1, | ||||
|             "5efb0d4f4bc50b58e81710f3": 3 | ||||
|         }, | ||||
|         "Caliber127x55": { | ||||
|             "5cadf6e5ae921500113bb973": 1 | ||||
|         }, | ||||
|         "Caliber12g": { | ||||
|             "5d6e6772a4b936088465b17c": 2, | ||||
|             "5d6e6806a4b936088465b17e": 2, | ||||
|             "5d6e67fba4b9361bc73bc779": 2, | ||||
|             "560d5e524bdc2d25448b4571": 2, | ||||
|             "5d6e6869a4b9361c140bcfde": 1, | ||||
|             "5d6e68b3a4b9361bca7e50b5": 1, | ||||
|             "58820d1224597753c90aeb13": 1, | ||||
|             "5d6e68dea4b9361bcc29e659": 1, | ||||
|             "5d6e6891a4b9361bd473feea": 1, | ||||
|             "5d6e68e6a4b9361c140bcfe0": 1, | ||||
|             "5d6e689ca4b9361bc8618956": 1 | ||||
|         }, | ||||
|         "Caliber20g": { | ||||
|             "5d6e695fa4b936359b35d852": 2, | ||||
|             "5d6e69b9a4b9361bc8618958": 2, | ||||
|             "5a38ebd9c4a282000d722a5b": 2, | ||||
|             "5d6e69c7a4b9360b6c0d54e4": 1, | ||||
|             "5d6e6a53a4b9361bd473feec": 1 | ||||
|         }, | ||||
|         "Caliber23x75": { | ||||
|             "5f647f31b6238e5dd066e196": 3, | ||||
|             "5e85a9a6eacf8c039e4e2ac1": 1 | ||||
|         }, | ||||
|         "Caliber366TKM": { | ||||
|             "59e6658b86f77411d949b250": 3, | ||||
|             "59e6542b86f77411dc52a77a": 1 | ||||
|         }, | ||||
|         "Caliber40mmRU": { | ||||
|             "5656eb674bdc2d35148b457c": 1 | ||||
|         }, | ||||
|         "Caliber40x46": { | ||||
|             "5ede4739e0350d05467f73e8": 1, | ||||
|             "5ede47405b097655935d7d16": 1, | ||||
|             "5ede474b0c226a66f5402622": 1, | ||||
|             "5ede475339ee016e8c534742": 1, | ||||
|             "5ede475b549eed7c6d5c18fb": 1, | ||||
|             "5f0c892565703e5c461894e9": 1 | ||||
|         }, | ||||
|         "Caliber46x30": { | ||||
|             "5ba26812d4351e003201fef1": 3, | ||||
|             "5ba26844d4351e00334c9475": 1 | ||||
|         }, | ||||
|         "Caliber545x39": { | ||||
|             "56dff216d2720bbd668b4568": 1, | ||||
|             "56dff338d2720bbd668b4569": 4, | ||||
|             "56dff421d2720b5f5a8b4567": 4, | ||||
|             "56dff4ecd2720b5f5a8b4568": 2, | ||||
|             "56dff4a2d2720bbd668b456a": 4, | ||||
|             "56dff0bed2720bb0668b4567": 3, | ||||
|             "56dff3afd2720bba668b4567": 1 | ||||
|         }, | ||||
|         "Caliber556x45NATO": { | ||||
|             "59e6927d86f77411da468256": 2, | ||||
|             "59e6918f86f7746c9f75e849": 2, | ||||
|             "59e68f6f86f7746c9f75e846": 4, | ||||
|             "59e6920f86f77411d82aa167": 5, | ||||
|             "54527a984bdc2d4e668b4567": 1 | ||||
|         }, | ||||
|         "Caliber57x28": { | ||||
|             "5cc86832d7f00c000d3a6e6c": 2, | ||||
|             "5cc80f79e4a949033c7343b2": 3, | ||||
|             "5cc86840d7f00c002412c56c": 3, | ||||
|             "5cc80f8fe4a949033b0224a2": 1, | ||||
|             "5cc80f53e4a949000e1ea4f8": 1 | ||||
|         }, | ||||
|         "Caliber68x51": { | ||||
|             "6529302b8c26af6326029fb7": 1 | ||||
|         }, | ||||
|         "Caliber762x25TT": { | ||||
|             "573602322459776445391df1": 2, | ||||
|             "573601b42459776410737435": 2, | ||||
|             "5735fdcd2459776445391d61": 1, | ||||
|             "5736026a245977644601dc61": 1 | ||||
|         }, | ||||
|         "Caliber762x35": { | ||||
|             "6196365d58ef8c428c287da1": 1, | ||||
|             "6196364158ef8c428c287d9f": 6, | ||||
|             "5fbe3ffdf8b6a877a729ea82": 3 | ||||
|         }, | ||||
|         "Caliber762x39": { | ||||
|             "59e4d3d286f774176a36250a": 2, | ||||
|             "64b7af734b75259c590fa895": 2, | ||||
|             "64b7af5a8532cf95ee0a0dbd": 6, | ||||
|             "59e4d24686f7741776641ac7": 4, | ||||
|             "59e4cf5286f7741778269d8a": 2, | ||||
|             "5656d7c34bdc2d9d198b4587": 1 | ||||
|         }, | ||||
|         "Caliber762x51": { | ||||
|             "5e023e88277cce2b522ff2b1": 2, | ||||
|             "5e023e6e34d52a55c3304f71": 2, | ||||
|             "5e023e53d4353e3302577c4c": 1 | ||||
|         }, | ||||
|         "Caliber762x54R": { | ||||
|             "64b8f7c241772715af0f9c3d": 2, | ||||
|             "64b8f7b5389d7ffd620ccba2": 2, | ||||
|             "64b8f7968532cf95ee0a0dbf": 2, | ||||
|             "5e023cf8186a883be655e54f": 2, | ||||
|             "5887431f2459777e1612938f": 1 | ||||
|         }, | ||||
|         "Caliber86x70": { | ||||
|             "5fc382b6d6fa9c00c571bbc3": 2, | ||||
|             "5fc382c1016cce60e8341b20": 1 | ||||
|         }, | ||||
|         "Caliber9x18PM": { | ||||
|             "5737218f245977612125ba51": 5, | ||||
|             "57372140245977611f70ee91": 5, | ||||
|             "5737207f24597760ff7b25f2": 2, | ||||
|             "573719762459775a626ccbc1": 3, | ||||
|             "57371f8d24597761006c6a81": 3, | ||||
|             "57371f2b24597761224311f1": 5, | ||||
|             "57371eb62459776125652ac1": 1, | ||||
|             "57371b192459775a9f58a5e0": 1, | ||||
|             "57371e4124597760ff7b25f1": 1 | ||||
|         }, | ||||
|         "Caliber9x19PARA": { | ||||
|             "5efb0e16aeb21837e749c7ff": 1, | ||||
|             "58864a4f2459770fcc257101": 7, | ||||
|             "5a3c16fe86f77452b62de32a": 12, | ||||
|             "5c3df7d588a4501f290594e5": 6, | ||||
|             "64b7bbb74b75259c590fa897": 4, | ||||
|             "56d59d3ad2720bdb418b4577": 2 | ||||
|         }, | ||||
|         "Caliber9x21": { | ||||
|             "5a26ac06c4a282000c5a90a8": 5, | ||||
|             "5a26abfac4a28232980eabff": 3, | ||||
|             "5a269f97c4a282000b151807": 1 | ||||
|         }, | ||||
|         "Caliber9x33R": { | ||||
|             "62330c40bdd19b369e1e53d1": 5, | ||||
|             "62330bfadc5883093563729b": 3, | ||||
|             "62330c18744e5e31df12f516": 1 | ||||
|         }, | ||||
|         "Caliber9x39": { | ||||
|             "6576f96220d53a5b8f3e395e": 7, | ||||
|             "57a0dfb82459774d3078b56c": 5, | ||||
|             "5c0d668f86f7747ccb7f13b2": 1 | ||||
|         }, | ||||
|         "Caliber127x33": { | ||||
|             "66a0d1c87d0d369e270bb9de": 10, | ||||
|             "66a0d1f88486c69fce00fdf6": 1 | ||||
|         } | ||||
|     }, | ||||
|     "pmcAmmo": { | ||||
|         "Caliber1143x23ACP": { | ||||
|             "5ea2a8e200685063ec28c05a": 30, | ||||
|             "5e81f423763d9f754677bf2e": 20, | ||||
|             "5efb0cabfb3e451d70735af5": 50 | ||||
|         }, | ||||
|         "Caliber127x55": { | ||||
|             "5cadf6ddae9215051e1c23b2": 30, | ||||
|             "5cadf6eeae921500134b2799": 70 | ||||
|         }, | ||||
|         "Caliber12g": { | ||||
|             "64b8ee384b75259c590fa89b": 10, | ||||
|             "5d6e6911a4b9361bd5780d52": 30, | ||||
|             "5d6e68c4a4b9361b93413f79": 30, | ||||
|             "5d6e68a8a4b9360b6c0d54e2": 40 | ||||
|         }, | ||||
|         "Caliber20g": { | ||||
|             "5d6e6a05a4b93618084f58d0": 40, | ||||
|             "5d6e6a42a4b9364f07165f52": 60 | ||||
|         }, | ||||
|         "Caliber23x75": { | ||||
|             "5f647f31b6238e5dd066e196": 5, | ||||
|             "5e85a9a6eacf8c039e4e2ac1": 10, | ||||
|             "5e85aa1a988a8701445df1f5": 15 | ||||
|         }, | ||||
|         "Caliber366TKM": { | ||||
|             "59e655cb86f77411dc52a77b": 5, | ||||
|             "5f0596629e22f464da6bbdd9": 95 | ||||
|         }, | ||||
|         "Caliber40mmRU": { | ||||
|             "5656eb674bdc2d35148b457c": 1 | ||||
|         }, | ||||
|         "Caliber40x46": { | ||||
|             "5ede4739e0350d05467f73e8": 1, | ||||
|             "5ede47405b097655935d7d16": 1, | ||||
|             "5ede474b0c226a66f5402622": 1, | ||||
|             "5ede475339ee016e8c534742": 1, | ||||
|             "5ede475b549eed7c6d5c18fb": 1, | ||||
|             "5f0c892565703e5c461894e9": 1 | ||||
|         }, | ||||
|         "Caliber46x30": { | ||||
|             "64b6979341772715af0f9c39": 30, | ||||
|             "5ba2678ad4351e44f824b344": 30, | ||||
|             "5ba26835d4351e0035628ff5": 30 | ||||
|         }, | ||||
|         "Caliber545x39": { | ||||
|             "56dff061d2720bb5668b4567": 10, | ||||
|             "61962b617c6c7b169525f168": 20, | ||||
|             "56dfef82d2720bbd668b4567": 25, | ||||
|             "56dff026d2720bb8668b4567": 25, | ||||
|             "5c0d5e4486f77478390952fe": 20 | ||||
|         }, | ||||
|         "Caliber556x45NATO": { | ||||
|             "54527ac44bdc2d36668b4567": 40, | ||||
|             "59e690b686f7746c9f75e848": 30, | ||||
|             "601949593ae8f707c4608daa": 30 | ||||
|         }, | ||||
|         "Caliber57x28": { | ||||
|             "5cc80f38e4a949001152b560": 1 | ||||
|         }, | ||||
|         "Caliber68x51": { | ||||
|             "6529302b8c26af6326029fb7": 40, | ||||
|             "6529243824cbe3c74a05e5c1": 60 | ||||
|         }, | ||||
|         "Caliber762x25TT": { | ||||
|             "573603562459776430731618": 10 | ||||
|         }, | ||||
|         "Caliber762x35": { | ||||
|             "5fbe3ffdf8b6a877a729ea82": 10, | ||||
|             "619636be6db0f2477964e710": 25, | ||||
|             "64b8725c4b75259c590fa899": 35, | ||||
|             "5fd20ff893a8961fc660a954": 30 | ||||
|         }, | ||||
|         "Caliber762x39": { | ||||
|             "64b7af434b75259c590fa893": 15, | ||||
|             "59e0d99486f7744a32234762": 50, | ||||
|             "601aa3d2b2bcb34913271e6d": 35 | ||||
|         }, | ||||
|         "Caliber762x51": { | ||||
|             "58dd3ad986f77403051cba8f": 15, | ||||
|             "5a608bf24f39f98ffc77720e": 35, | ||||
|             "5a6086ea4f39f99cd479502f": 35, | ||||
|             "5efb0c1bd79ff02a1f5e68d9": 15 | ||||
|         }, | ||||
|         "Caliber762x54R": { | ||||
|             "59e77a2386f7742ee578960a": 5, | ||||
|             "5e023d34e8a400319a28ed44": 30, | ||||
|             "560d61e84bdc2da74d8b4571": 45, | ||||
|             "5e023d48186a883be655e551": 20 | ||||
|         }, | ||||
|         "Caliber86x70": { | ||||
|             "5fc382c1016cce60e8341b20": 10, | ||||
|             "5fc275cf85fd526b824a571a": 50, | ||||
|             "5fc382a9d724d907e2077dab": 40 | ||||
|         }, | ||||
|         "Caliber9x18PM": { | ||||
|             "573718ba2459775a75491131": 10, | ||||
|             "57371aab2459775a77142f22": 45, | ||||
|             "573719df2459775a626ccbc2": 45 | ||||
|         }, | ||||
|         "Caliber9x19PARA": { | ||||
|             "5c0d56a986f774449d5de529": 10, | ||||
|             "56d59d3ad2720bdb418b4577": 5, | ||||
|             "5c925fa22e221601da359b7b": 45, | ||||
|             "5efb0da7a29a85116f6ea05f": 35 | ||||
|         }, | ||||
|         "Caliber9x21": { | ||||
|             "5a269f97c4a282000b151807": 10, | ||||
|             "6576f93989f0062e741ba952": 20, | ||||
|             "5a26ac0ec4a28200741e1e18": 30, | ||||
|             "6576f4708ca9c4381d16cd9d": 30 | ||||
|         }, | ||||
|         "Caliber9x33R": { | ||||
|             "62330b3ed4dc74626d570b95": 10 | ||||
|         }, | ||||
|         "Caliber9x39": { | ||||
|             "61962d879bb3d20b0946d385": 20, | ||||
|             "57a0e5022459774d1673f889": 40, | ||||
|             "5c0d688c86f77413ae3407b2": 40 | ||||
|         }, | ||||
|         "Caliber127x33": { | ||||
|             "66a0d1c87d0d369e270bb9de": 2, | ||||
|             "66a0d1f88486c69fce00fdf6": 10, | ||||
|             "66a0d1e0ed648d72fe064d06": 40, | ||||
|             "668fe62ac62660a5d8071446": 40 | ||||
|         } | ||||
|     }, | ||||
|     "bossAmmo": { | ||||
|         "Caliber1143x23ACP": { | ||||
|             "5ea2a8e200685063ec28c05a": 4, | ||||
|             "5efb0fc6aeb21837e749c801": 1, | ||||
|             "5efb0d4f4bc50b58e81710f3": 10, | ||||
|             "5e81f423763d9f754677bf2e": 18, | ||||
|             "5efb0cabfb3e451d70735af5": 10 | ||||
|         }, | ||||
|         "Caliber127x55": { | ||||
|             "5cadf6e5ae921500113bb973": 3, | ||||
|             "5cadf6ddae9215051e1c23b2": 12, | ||||
|             "5cadf6eeae921500134b2799": 8 | ||||
|         }, | ||||
|         "Caliber12g": { | ||||
|             "5d6e6806a4b936088465b17e": 7, | ||||
|             "64b8ee384b75259c590fa89b": 4, | ||||
|             "5d6e6911a4b9361bd5780d52": 3, | ||||
|             "5c0d591486f7744c505b416f": 5, | ||||
|             "5d6e6891a4b9361bd473feea": 2, | ||||
|             "5d6e68e6a4b9361c140bcfe0": 6, | ||||
|             "5d6e689ca4b9361bc8618956": 8, | ||||
|             "5d6e68c4a4b9361b93413f79": 8, | ||||
|             "5d6e68a8a4b9360b6c0d54e2": 3 | ||||
|         }, | ||||
|         "Caliber20g": { | ||||
|             "5d6e69c7a4b9360b6c0d54e4": 1, | ||||
|             "5d6e6a53a4b9361bd473feec": 4, | ||||
|             "5d6e6a05a4b93618084f58d0": 5, | ||||
|             "5d6e6a42a4b9364f07165f52": 5 | ||||
|         }, | ||||
|         "Caliber23x75": { | ||||
|             "5f647f31b6238e5dd066e196": 2, | ||||
|             "5e85a9a6eacf8c039e4e2ac1": 4, | ||||
|             "5e85aa1a988a8701445df1f5": 4 | ||||
|         }, | ||||
|         "Caliber366TKM": { | ||||
|             "59e6658b86f77411d949b250": 1, | ||||
|             "59e6542b86f77411dc52a77a": 2, | ||||
|             "59e655cb86f77411dc52a77b": 10, | ||||
|             "5f0596629e22f464da6bbdd9": 8 | ||||
|         }, | ||||
|         "Caliber40mmRU": { | ||||
|             "5656eb674bdc2d35148b457c": 1 | ||||
|         }, | ||||
|         "Caliber40x46": { | ||||
|             "5ede4739e0350d05467f73e8": 1, | ||||
|             "5ede47405b097655935d7d16": 1, | ||||
|             "5ede474b0c226a66f5402622": 1, | ||||
|             "5ede475339ee016e8c534742": 1, | ||||
|             "5ede475b549eed7c6d5c18fb": 1, | ||||
|             "5f0c892565703e5c461894e9": 1 | ||||
|         }, | ||||
|         "Caliber46x30": { | ||||
|             "5ba26812d4351e003201fef1": 2, | ||||
|             "5ba26844d4351e00334c9475": 4, | ||||
|             "5ba2678ad4351e44f824b344": 15, | ||||
|             "64b6979341772715af0f9c39": 15, | ||||
|             "5ba26835d4351e0035628ff5": 8 | ||||
|         }, | ||||
|         "Caliber545x39": { | ||||
|             "56dff3afd2720bba668b4567": 6, | ||||
|             "56dff2ced2720bb4668b4567": 12, | ||||
|             "56dff061d2720bb5668b4567": 20, | ||||
|             "61962b617c6c7b169525f168": 12, | ||||
|             "56dfef82d2720bbd668b4567": 9, | ||||
|             "56dff026d2720bb8668b4567": 8, | ||||
|             "5c0d5e4486f77478390952fe": 4 | ||||
|         }, | ||||
|         "Caliber556x45NATO": { | ||||
|             "5c0d5ae286f7741e46554302": 1, | ||||
|             "54527a984bdc2d4e668b4567": 7, | ||||
|             "60194943740c5d77f6705eea": 20, | ||||
|             "59e6906286f7746c9f75e847": 26, | ||||
|             "54527ac44bdc2d36668b4567": 30, | ||||
|             "59e690b686f7746c9f75e848": 7, | ||||
|             "601949593ae8f707c4608daa": 5 | ||||
|         }, | ||||
|         "Caliber57x28": { | ||||
|             "5cc80f8fe4a949033b0224a2": 5, | ||||
|             "5cc80f53e4a949000e1ea4f8": 21, | ||||
|             "5cc80f67e4a949035e43bbba": 15, | ||||
|             "5cc80f38e4a949001152b560": 12 | ||||
|         }, | ||||
|         "Caliber68x51": { | ||||
|             "6529302b8c26af6326029fb7": 10, | ||||
|             "6529243824cbe3c74a05e5c1": 5 | ||||
|         }, | ||||
|         "Caliber762x25TT": { | ||||
|             "5736026a245977644601dc61": 5, | ||||
|             "573603c924597764442bd9cb": 10, | ||||
|             "573603562459776430731618": 10 | ||||
|         }, | ||||
|         "Caliber762x35": { | ||||
|             "6196365d58ef8c428c287da1": 7, | ||||
|             "5fbe3ffdf8b6a877a729ea82": 6, | ||||
|             "619636be6db0f2477964e710": 23, | ||||
|             "64b8725c4b75259c590fa899": 20, | ||||
|             "5fd20ff893a8961fc660a954": 9 | ||||
|         }, | ||||
|         "Caliber762x39": { | ||||
|             "59e4cf5286f7741778269d8a": 4, | ||||
|             "5656d7c34bdc2d9d198b4587": 28, | ||||
|             "64b7af434b75259c590fa893": 33, | ||||
|             "59e0d99486f7744a32234762": 20, | ||||
|             "601aa3d2b2bcb34913271e6d": 12 | ||||
|         }, | ||||
|         "Caliber762x51": { | ||||
|             "5e023e53d4353e3302577c4c": 6, | ||||
|             "58dd3ad986f77403051cba8f": 27, | ||||
|             "5a608bf24f39f98ffc77720e": 19, | ||||
|             "5a6086ea4f39f99cd479502f": 9, | ||||
|             "5efb0c1bd79ff02a1f5e68d9": 2 | ||||
|         }, | ||||
|         "Caliber762x54R": { | ||||
|             "5e023cf8186a883be655e54f": 3, | ||||
|             "5887431f2459777e1612938f": 20, | ||||
|             "59e77a2386f7742ee578960a": 25, | ||||
|             "5e023d34e8a400319a28ed44": 22, | ||||
|             "560d61e84bdc2da74d8b4571": 15, | ||||
|             "5e023d48186a883be655e551": 10 | ||||
|         }, | ||||
|         "Caliber86x70": { | ||||
|             "5fc382b6d6fa9c00c571bbc3": 5, | ||||
|             "5fc382c1016cce60e8341b20": 8, | ||||
|             "5fc275cf85fd526b824a571a": 8, | ||||
|             "5fc382a9d724d907e2077dab": 5 | ||||
|         }, | ||||
|         "Caliber9x18PM": { | ||||
|             "57371e4124597760ff7b25f1": 3, | ||||
|             "5737201124597760fc4431f1": 5, | ||||
|             "573720e02459776143012541": 12, | ||||
|             "573718ba2459775a75491131": 18, | ||||
|             "57371aab2459775a77142f22": 12, | ||||
|             "573719df2459775a626ccbc2": 10 | ||||
|         }, | ||||
|         "Caliber9x19PARA": { | ||||
|             "5c0d56a986f774449d5de529": 9, | ||||
|             "5efb0e16aeb21837e749c7ff": 5, | ||||
|             "5a3c16fe86f77452b62de32a": 4, | ||||
|             "56d59d3ad2720bdb418b4577": 18, | ||||
|             "5c925fa22e221601da359b7b": 22, | ||||
|             "5efb0da7a29a85116f6ea05f": 9 | ||||
|         }, | ||||
|         "Caliber9x21": { | ||||
|             "5a269f97c4a282000b151807": 8, | ||||
|             "6576f93989f0062e741ba952": 18, | ||||
|             "5a26ac0ec4a28200741e1e18": 18, | ||||
|             "6576f4708ca9c4381d16cd9d": 8 | ||||
|         }, | ||||
|         "Caliber9x33R": { | ||||
|             "62330c18744e5e31df12f516": 9, | ||||
|             "62330b3ed4dc74626d570b95": 6 | ||||
|         }, | ||||
|         "Caliber9x39": { | ||||
|             "5c0d668f86f7747ccb7f13b2": 9, | ||||
|             "61962d879bb3d20b0946d385": 25, | ||||
|             "57a0e5022459774d1673f889": 25, | ||||
|             "5c0d688c86f77413ae3407b2": 12 | ||||
|         }, | ||||
|         "Caliber127x33": { | ||||
|             "66a0d1c87d0d369e270bb9de": 3, | ||||
|             "66a0d1f88486c69fce00fdf6": 30, | ||||
|             "66a0d1e0ed648d72fe064d06": 25,  | ||||
|             "668fe62ac62660a5d8071446": 12 | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,487 @@ | |||
| { | ||||
|     "pmcUSEC": { | ||||
|         "appearance": { | ||||
|             "body": { | ||||
|                 "5d1f56c686f7744bcd13459c": 1, | ||||
|                 "637b945722e2a933ed0e33c8": 1, | ||||
|                 "6571cb0923aa6d72760a7f8f": 1, | ||||
|                 "5fd3e9f71b735718c25cd9f8": 1, | ||||
|                 "642d9bbf6c06444bf7033855": 1, | ||||
|                 "6033a35f80ae5e2f970ba6bb": 2, | ||||
|                 "66043728333907134309d647": 2, | ||||
|                 "5d1f56e486f7744bce0ee9ed": 2, | ||||
|                 "6295e8c3e08ed747e64aea00": 2, | ||||
|                 "642c18b8a6a0660b560fb31c": 2, | ||||
|                 "66acbe49dc61999a6a03d4d6": 2, | ||||
|                 "5d4da0cb86f77450fe0a6629": 3, | ||||
|                 "660437e57502eca33a08caca": 3, | ||||
|                 "5fcf63da5c287f01f22bf245": 3, | ||||
|                 "618109c96d7ca35d076b3363": 3, | ||||
|                 "5d1f56f186f7744bcb0acd1a": 3, | ||||
|                 "64ef3efdb63b74469b6c1499": 5, | ||||
|                 "642c5273ff5ecad7810a89d7": 5, | ||||
|                 "5d1f56ff86f7743f8362bcd7": 5, | ||||
|                 "5e4bb35286f77406a511c9bc": 5, | ||||
|                 "5cdea33e7d6c8b0474535dac": 5, | ||||
|                 "5e9da17386f774054b6f79a3": 5, | ||||
|                 "5f5e4075df4f3100376a8138": 5 | ||||
|             }, | ||||
|             "feet": { | ||||
|                 "5d1f590486f7744bcd13459e": 1, | ||||
|                 "642d4d8eb6b75d4c89077cf9": 1, | ||||
|                 "6033a3fee29c9f6c9b14e74e": 1, | ||||
|                 "5fcf940bce1ba36a513bb9cc": 2, | ||||
|                 "660436487502eca33a08cac8": 2, | ||||
|                 "6571cad4c8673f00290f5657": 2, | ||||
|                 "637ba17aa10a96c2b605dbc2": 2, | ||||
|                 "5d1f591186f7744bcc048755": 2, | ||||
|                 "6295e944e9de5e7b3751c4da": 2, | ||||
|                 "642c19360a69698d1b049e12": 2, | ||||
|                 "66acc8f719271bd6d00dec0b": 2, | ||||
|                 "660436a810bcdf80ff0e9f78": 3, | ||||
|                 "617c02e24013b06b0b78df80": 3, | ||||
|                 "5d1f593286f7743014162044": 3, | ||||
|                 "5d1f592286f7743f8362bcdb": 3, | ||||
|                 "642d6941ff5ecad7810a8a61": 5, | ||||
|                 "5df8a08886f7740bfe6df775": 5, | ||||
|                 "5e4bb3b586f77406812bd579": 5, | ||||
|                 "5e9dcadd86f7743e20652f23": 5, | ||||
|                 "5f5e40a06760b4138443b341": 5 | ||||
|             }, | ||||
|             "hands": { | ||||
|                 "5cde95fa7d6c8b04737c2d13": 1 | ||||
|             }, | ||||
|             "head": { | ||||
|                 "5cde96047d6c8b20b577f016": 1, | ||||
|                 "5fdb4139e4ed5b5ea251e4ed": 1, | ||||
|                 "5fdb5950f5264a66150d1c6e": 1, | ||||
|                 "60a6aa8fd559ae040d0d951f": 1, | ||||
|                 "619f9e338858a474c8685cc9": 1, | ||||
|                 "62aca6a1310e67685a2fc2e7": 1, | ||||
|                 "6574aabee0423b9ebe0c79cf": 1 | ||||
|             } | ||||
|         } | ||||
|     }, | ||||
|     "pmcBEAR": { | ||||
|         "appearance": { | ||||
|             "body": { | ||||
|                 "5fce3e0cfe40296c1d5fd782": 1, | ||||
|                 "6377266693a3b4967208e42b": 1, | ||||
|                 "5d1f564b86f7744bcb0acd16": 1, | ||||
|                 "6295e698e9de5e7b3751c47a": 1, | ||||
|                 "642e8ae07e17c882400c4f87": 1, | ||||
|                 "5d1f568486f7744bca3f0b98": 1, | ||||
|                 "657058fddf9b3231400e9188": 2, | ||||
|                 "6033a31e9ec839204e6a2f3e": 2, | ||||
|                 "66043cc27502eca33a08cad0": 2, | ||||
|                 "5fce3e47fe40296c1d5fd784": 2, | ||||
|                 "642ed297ac11c9eaf10d87e8": 2, | ||||
|                 "66acec1dc94f4bf5bc063a16": 2, | ||||
|                 "5d1f567786f7744bcc04874f": 3, | ||||
|                 "660440d2c8949a435906e43a": 3, | ||||
|                 "617bca4b4013b06b0b78df2a": 3, | ||||
|                 "5d1f566d86f7744bcd13459a": 3, | ||||
|                 "64ef3efdb63b74469b6c1499": 5, | ||||
|                 "6430119aac11c9eaf10d881b": 5, | ||||
|                 "5df89f1f86f77412631087ea": 5, | ||||
|                 "5e9d9fa986f774054d6b89f2": 5, | ||||
|                 "5cdea33e7d6c8b0474535dac": 5, | ||||
|                 "5e4bb31586f7740695730568": 5, | ||||
|                 "5f5e401747344c2e4f6c42c5": 5 | ||||
|             }, | ||||
|             "feet": { | ||||
|                 "6377315993a3b4967208e437": 1, | ||||
|                 "5d1f588e86f7744bcc048753": 1, | ||||
|                 "65707a89f5a6f1412f0c5f7b": 1, | ||||
|                 "642ed40af5bdf1c04e01952e": 1, | ||||
|                 "5fce3e965a9f8c40685693bc": 1, | ||||
|                 "6295e63de08ed747e64ae991": 2, | ||||
|                 "66043cf87502eca33a08cad2": 2, | ||||
|                 "6033a3d8ed2e0509b15f9031": 2, | ||||
|                 "5d1f58cb86f7744bca3f0b9a": 2, | ||||
|                 "5d1f58a086f7743f8362bcd9": 2, | ||||
|                 "642e71620a69698d1b049f0a": 2, | ||||
|                 "66acebd4ede86671bb09584b": 2, | ||||
|                 "66043d7ac8949a435906e434": 3, | ||||
|                 "5d1f58ab86f7743014162042": 3, | ||||
|                 "617be9e4e02b3b3fa50fa8f2": 3, | ||||
|                 "642eea6f881906a7fe086841": 5, | ||||
|                 "5df89f8f86f77412672a1e38": 5, | ||||
|                 "5e9dc97c86f774054c19ac9a": 5, | ||||
|                 "5e4bb39386f774067f79de05": 5, | ||||
|                 "5f5e40400bc58666c37e7819": 5 | ||||
|             }, | ||||
|             "hands": { | ||||
|                 "5cc0876314c02e000c6bea6b": 1 | ||||
|             }, | ||||
|             "head": { | ||||
|                 "5cc084dd14c02e000b0550a3": 1, | ||||
|                 "5fdb50bb2b730a787b3f78cf": 1, | ||||
|                 "5fdb7571e4ed5b5ea251e529": 1, | ||||
|                 "60a6aaad42fd2735e4589978": 1, | ||||
|                 "619f94f5b90286142b59d45f": 1, | ||||
|                 "62a9e7d15ea3b87d6f642a28": 1, | ||||
|                 "6574aa9a1b144de18c0fba45": 1 | ||||
|             } | ||||
|         } | ||||
|     }, | ||||
|     "springEarly": { | ||||
|         "pmcUSEC": { | ||||
|             "appearance": { | ||||
|                 "body": { | ||||
|                     "5d1f56c686f7744bcd13459c": 1, | ||||
|                     "5fd3e9f71b735718c25cd9f8": 1, | ||||
|                     "66043728333907134309d647": 1, | ||||
|                     "66acbe49dc61999a6a03d4d6": 1, | ||||
|                     "660437e57502eca33a08caca": 1, | ||||
|                     "5d1f56f186f7744bcb0acd1a": 1, | ||||
|                     "5d1f56ff86f7743f8362bcd7": 1, | ||||
|                     "5d1f56a686f7744bce0ee9eb": 2, | ||||
|                     "5e9da17386f774054b6f79a3": 2, | ||||
|                     "5e4bb35286f77406a511c9bc": 2, | ||||
|                     "5d1f56e486f7744bce0ee9ed": 2 | ||||
|                 }, | ||||
|                 "feet": { | ||||
|                     "642d4d8eb6b75d4c89077cf9": 1, | ||||
|                     "5fcf940bce1ba36a513bb9cc": 1, | ||||
|                     "66acc8f719271bd6d00dec0b": 1, | ||||
|                     "6295e944e9de5e7b3751c4da": 1, | ||||
|                     "5d1f592286f7743f8362bcdb": 1, | ||||
|                     "5e4bb3b586f77406812bd579": 1, | ||||
|                     "5d1f590486f7744bcd13459e": 3, | ||||
|                     "5d1f58ed86f7744bcb0acd1c": 3 | ||||
|                 }, | ||||
|                 "hands": { | ||||
|                     "5cde95fa7d6c8b04737c2d13": 1 | ||||
|                 }, | ||||
|                 "head": { | ||||
|                     "5cde96047d6c8b20b577f016": 1, | ||||
|                     "5fdb4139e4ed5b5ea251e4ed": 1, | ||||
|                     "5fdb5950f5264a66150d1c6e": 1, | ||||
|                     "60a6aa8fd559ae040d0d951f": 1, | ||||
|                     "619f9e338858a474c8685cc9": 1, | ||||
|                     "62aca6a1310e67685a2fc2e7": 1, | ||||
|                     "6574aabee0423b9ebe0c79cf": 1 | ||||
|                 } | ||||
|             } | ||||
|         }, | ||||
|         "pmcBEAR": { | ||||
|             "appearance": { | ||||
|                 "body": { | ||||
|                     "657058fddf9b3231400e9188": 1, | ||||
|                     "6033a31e9ec839204e6a2f3e": 1, | ||||
|                     "5d1f567786f7744bcc04874f": 1, | ||||
|                     "5e9d9fa986f774054d6b89f2": 1, | ||||
|                     "5f5e401747344c2e4f6c42c5": 1, | ||||
|                     "642e8ae07e17c882400c4f87": 2, | ||||
|                     "5d1f568486f7744bca3f0b98": 2, | ||||
|                     "66acec1dc94f4bf5bc063a16": 2, | ||||
|                     "5e4bb31586f7740695730568": 2 | ||||
|                 }, | ||||
|                 "feet": { | ||||
|                     "5d1f58bd86f7744bce0ee9ef": 1, | ||||
|                     "6377315993a3b4967208e437": 1, | ||||
|                     "66043cf87502eca33a08cad2": 1, | ||||
|                     "5d1f58cb86f7744bca3f0b9a": 1, | ||||
|                     "5d1f58a086f7743f8362bcd9": 1, | ||||
|                     "617be9e4e02b3b3fa50fa8f2": 1, | ||||
|                     "5f5e40400bc58666c37e7819": 1, | ||||
|                     "66acebd4ede86671bb09584b": 3, | ||||
|                     "5d1f58ab86f7743014162042": 3 | ||||
|                 }, | ||||
|                 "hands": { | ||||
|                     "5cc0876314c02e000c6bea6b": 1 | ||||
|                 }, | ||||
|                 "head": { | ||||
|                     "5cc084dd14c02e000b0550a3": 1, | ||||
|                     "5fdb50bb2b730a787b3f78cf": 1, | ||||
|                     "5fdb7571e4ed5b5ea251e529": 1, | ||||
|                     "60a6aaad42fd2735e4589978": 1, | ||||
|                     "619f94f5b90286142b59d45f": 1, | ||||
|                     "62a9e7d15ea3b87d6f642a28": 1, | ||||
|                     "6574aa9a1b144de18c0fba45": 1 | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     }, | ||||
|     "spring": { | ||||
|         "pmcUSEC": { | ||||
|             "appearance": { | ||||
|                 "body": { | ||||
|                     "5cde95d97d6c8b647a3769b0": 1, | ||||
|                     "5fd3e9f71b735718c25cd9f8": 1, | ||||
|                     "66043728333907134309d647": 1, | ||||
|                     "5d4da0cb86f77450fe0a6629": 1, | ||||
|                     "5d1f56f186f7744bcb0acd1a": 1, | ||||
|                     "5f5e4075df4f3100376a8138": 1 | ||||
|                 }, | ||||
|                 "feet": { | ||||
|                     "5cde95ef7d6c8b04713c4f2d": 1, | ||||
|                     "6033a3fee29c9f6c9b14e74e": 1, | ||||
|                     "660436487502eca33a08cac8": 1, | ||||
|                     "6571cad4c8673f00290f5657": 1, | ||||
|                     "66acc8f719271bd6d00dec0b": 1, | ||||
|                     "5d1f592286f7743f8362bcdb": 1, | ||||
|                     "642d6941ff5ecad7810a8a61": 1, | ||||
|                     "5e9dcadd86f7743e20652f23": 1 | ||||
|                 }, | ||||
|                 "hands": { | ||||
|                     "5cde95fa7d6c8b04737c2d13": 1 | ||||
|                 }, | ||||
|                 "head": { | ||||
|                     "5cde96047d6c8b20b577f016": 1, | ||||
|                     "5fdb4139e4ed5b5ea251e4ed": 1, | ||||
|                     "5fdb5950f5264a66150d1c6e": 1, | ||||
|                     "60a6aa8fd559ae040d0d951f": 1, | ||||
|                     "619f9e338858a474c8685cc9": 1, | ||||
|                     "62aca6a1310e67685a2fc2e7": 1, | ||||
|                     "6574aabee0423b9ebe0c79cf": 1 | ||||
|                 } | ||||
|             } | ||||
|         }, | ||||
|         "pmcBEAR": { | ||||
|             "appearance": { | ||||
|                 "body": { | ||||
|                     "5cc0858d14c02e000c6bea66": 1, | ||||
|                     "5d1f564b86f7744bcb0acd16": 1, | ||||
|                     "6295e698e9de5e7b3751c47a": 1, | ||||
|                     "6033a31e9ec839204e6a2f3e": 1, | ||||
|                     "5fce3e47fe40296c1d5fd784": 1, | ||||
|                     "617bca4b4013b06b0b78df2a": 1, | ||||
|                     "5df89f1f86f77412631087ea": 1 | ||||
|                 }, | ||||
|                 "feet": { | ||||
|                     "5cc085bb14c02e000e67a5c5": 1, | ||||
|                     "5d1f588e86f7744bcc048753": 1, | ||||
|                     "66043cf87502eca33a08cad2": 1, | ||||
|                     "6033a3d8ed2e0509b15f9031": 1, | ||||
|                     "642e71620a69698d1b049f0a": 1, | ||||
|                     "617be9e4e02b3b3fa50fa8f2": 1, | ||||
|                     "642eea6f881906a7fe086841": 1, | ||||
|                     "5df89f8f86f77412672a1e38": 1, | ||||
|                     "5e9dc97c86f774054c19ac9a": 1, | ||||
|                     "5e4bb39386f774067f79de05": 1 | ||||
|                 }, | ||||
|                 "hands": { | ||||
|                     "5cc0876314c02e000c6bea6b": 1 | ||||
|                 }, | ||||
|                 "head": { | ||||
|                     "5cc084dd14c02e000b0550a3": 1, | ||||
|                     "5fdb50bb2b730a787b3f78cf": 1, | ||||
|                     "5fdb7571e4ed5b5ea251e529": 1, | ||||
|                     "60a6aaad42fd2735e4589978": 1, | ||||
|                     "619f94f5b90286142b59d45f": 1, | ||||
|                     "62a9e7d15ea3b87d6f642a28": 1, | ||||
|                     "6574aa9a1b144de18c0fba45": 1 | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     }, | ||||
|     "summer": { | ||||
|         "pmcUSEC": { | ||||
|             "appearance": { | ||||
|                 "body": { | ||||
|                     "5cde95d97d6c8b647a3769b0": 1, | ||||
|                     "5d1f56c686f7744bcd13459c": 1, | ||||
|                     "5fd3e9f71b735718c25cd9f8": 1, | ||||
|                     "66043728333907134309d647": 1, | ||||
|                     "5d4da0cb86f77450fe0a6629": 1, | ||||
|                     "66acbe49dc61999a6a03d4d6": 1, | ||||
|                     "64ef3efdb63b74469b6c1499": 1, | ||||
|                     "642c18b8a6a0660b560fb31c": 1, | ||||
|                     "5d1f56f186f7744bcb0acd1a": 1, | ||||
|                     "5f5e4075df4f3100376a8138": 1 | ||||
|                 }, | ||||
|                 "feet": { | ||||
|                     "5cde95ef7d6c8b04713c4f2d": 1, | ||||
|                     "6033a3fee29c9f6c9b14e74e": 1, | ||||
|                     "660436487502eca33a08cac8": 1, | ||||
|                     "6571cad4c8673f00290f5657": 1, | ||||
|                     "66acc8f719271bd6d00dec0b": 1, | ||||
|                     "5d1f593286f7743014162044": 1, | ||||
|                     "5d1f592286f7743f8362bcdb": 1, | ||||
|                     "642d6941ff5ecad7810a8a61": 1, | ||||
|                     "5e9dcadd86f7743e20652f23": 1 | ||||
|                 }, | ||||
|                 "hands": { | ||||
|                     "5cde95fa7d6c8b04737c2d13": 1 | ||||
|                 }, | ||||
|                 "head": { | ||||
|                     "5cde96047d6c8b20b577f016": 1, | ||||
|                     "5fdb4139e4ed5b5ea251e4ed": 1, | ||||
|                     "5fdb5950f5264a66150d1c6e": 1, | ||||
|                     "60a6aa8fd559ae040d0d951f": 1, | ||||
|                     "619f9e338858a474c8685cc9": 1, | ||||
|                     "62aca6a1310e67685a2fc2e7": 1, | ||||
|                     "6574aabee0423b9ebe0c79cf": 1 | ||||
|                 } | ||||
|             } | ||||
|         }, | ||||
|         "pmcBEAR": { | ||||
|             "appearance": { | ||||
|                 "body": { | ||||
|                     "5cc0858d14c02e000c6bea66": 1, | ||||
|                     "5d1f564b86f7744bcb0acd16": 1, | ||||
|                     "6295e698e9de5e7b3751c47a": 1, | ||||
|                     "6033a31e9ec839204e6a2f3e": 1, | ||||
|                     "5fce3e47fe40296c1d5fd784": 1, | ||||
|                     "617bca4b4013b06b0b78df2a": 1, | ||||
|                     "64ef3efdb63b74469b6c1499": 1, | ||||
|                     "5df89f1f86f77412631087ea": 1, | ||||
|                     "5e9d9fa986f774054d6b89f2": 1 | ||||
|                 }, | ||||
|                 "feet": { | ||||
|                     "5cc085bb14c02e000e67a5c5": 1, | ||||
|                     "5d1f588e86f7744bcc048753": 1, | ||||
|                     "66043cf87502eca33a08cad2": 1, | ||||
|                     "6033a3d8ed2e0509b15f9031": 1, | ||||
|                     "642e71620a69698d1b049f0a": 1, | ||||
|                     "617be9e4e02b3b3fa50fa8f2": 1, | ||||
|                     "642eea6f881906a7fe086841": 1, | ||||
|                     "5df89f8f86f77412672a1e38": 1, | ||||
|                     "5e9dc97c86f774054c19ac9a": 1, | ||||
|                     "5e4bb39386f774067f79de05": 1 | ||||
|                 }, | ||||
|                 "hands": { | ||||
|                     "5cc0876314c02e000c6bea6b": 1 | ||||
|                 }, | ||||
|                 "head": { | ||||
|                     "5cc084dd14c02e000b0550a3": 1, | ||||
|                     "5fdb50bb2b730a787b3f78cf": 1, | ||||
|                     "5fdb7571e4ed5b5ea251e529": 1, | ||||
|                     "60a6aaad42fd2735e4589978": 1, | ||||
|                     "619f94f5b90286142b59d45f": 1, | ||||
|                     "62a9e7d15ea3b87d6f642a28": 1, | ||||
|                     "6574aa9a1b144de18c0fba45": 1 | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     }, | ||||
|     "autumn": { | ||||
|         "pmcUSEC": { | ||||
|             "appearance": { | ||||
|                 "body": { | ||||
|                     "5d1f56c686f7744bcd13459c": 1, | ||||
|                     "637b945722e2a933ed0e33c8": 1, | ||||
|                     "6571cb0923aa6d72760a7f8f": 1, | ||||
|                     "6033a35f80ae5e2f970ba6bb": 1, | ||||
|                     "5d1f56e486f7744bce0ee9ed": 1, | ||||
|                     "66acbe49dc61999a6a03d4d6": 1, | ||||
|                     "660437e57502eca33a08caca": 1, | ||||
|                     "64ef3efdb63b74469b6c1499": 1, | ||||
|                     "5d1f56ff86f7743f8362bcd7": 1 | ||||
|                 }, | ||||
|                 "feet": { | ||||
|                     "642d4d8eb6b75d4c89077cf9": 1, | ||||
|                     "5fcf940bce1ba36a513bb9cc": 1, | ||||
|                     "637ba17aa10a96c2b605dbc2": 1, | ||||
|                     "6295e944e9de5e7b3751c4da": 1, | ||||
|                     "5e4bb3b586f77406812bd579": 1, | ||||
|                     "5f5e40a06760b4138443b341": 1 | ||||
|                 }, | ||||
|                 "hands": { | ||||
|                     "5cde95fa7d6c8b04737c2d13": 1 | ||||
|                 }, | ||||
|                 "head": { | ||||
|                     "5cde96047d6c8b20b577f016": 1, | ||||
|                     "5fdb4139e4ed5b5ea251e4ed": 1, | ||||
|                     "5fdb5950f5264a66150d1c6e": 1, | ||||
|                     "60a6aa8fd559ae040d0d951f": 1, | ||||
|                     "619f9e338858a474c8685cc9": 1, | ||||
|                     "62aca6a1310e67685a2fc2e7": 1, | ||||
|                     "6574aabee0423b9ebe0c79cf": 1 | ||||
|                 } | ||||
|             } | ||||
|         }, | ||||
|         "pmcBEAR": { | ||||
|             "appearance": { | ||||
|                 "body": { | ||||
|                     "6377266693a3b4967208e42b": 1, | ||||
|                     "5d1f568486f7744bca3f0b98": 1, | ||||
|                     "657058fddf9b3231400e9188": 1, | ||||
|                     "642ed297ac11c9eaf10d87e8": 1, | ||||
|                     "5d1f567786f7744bcc04874f": 1, | ||||
|                     "64ef3efdb63b74469b6c1499": 1, | ||||
|                     "6430119aac11c9eaf10d881b": 1, | ||||
|                     "5f5e401747344c2e4f6c42c5": 1 | ||||
|                 }, | ||||
|                 "feet": { | ||||
|                     "5d1f58bd86f7744bce0ee9ef": 1, | ||||
|                     "6377315993a3b4967208e437": 1, | ||||
|                     "642ed40af5bdf1c04e01952e": 1, | ||||
|                     "6295e63de08ed747e64ae991": 1, | ||||
|                     "5d1f58a086f7743f8362bcd9": 1, | ||||
|                     "66043d7ac8949a435906e434": 1, | ||||
|                     "5d1f58ab86f7743014162042": 1, | ||||
|                     "5f5e40400bc58666c37e7819": 1 | ||||
|                 }, | ||||
|                 "hands": { | ||||
|                     "5cc0876314c02e000c6bea6b": 1 | ||||
|                 }, | ||||
|                 "head": { | ||||
|                     "5cc084dd14c02e000b0550a3": 1, | ||||
|                     "5fdb50bb2b730a787b3f78cf": 1, | ||||
|                     "5fdb7571e4ed5b5ea251e529": 1, | ||||
|                     "60a6aaad42fd2735e4589978": 1, | ||||
|                     "619f94f5b90286142b59d45f": 1, | ||||
|                     "62a9e7d15ea3b87d6f642a28": 1, | ||||
|                     "6574aa9a1b144de18c0fba45": 1 | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     }, | ||||
|     "winter": { | ||||
|         "pmcUSEC": { | ||||
|             "appearance": { | ||||
|                 "body": { | ||||
|                     "5d1f56a686f7744bce0ee9eb": 1, | ||||
|                     "5e9da17386f774054b6f79a3": 1, | ||||
|                     "5e4bb35286f77406a511c9bc": 1, | ||||
|                     "5d1f56e486f7744bce0ee9ed": 1 | ||||
|                 }, | ||||
|                 "feet": { | ||||
|                     "5d1f590486f7744bcd13459e": 1, | ||||
|                     "5d1f58ed86f7744bcb0acd1c": 1 | ||||
|                 }, | ||||
|                 "hands": { | ||||
|                     "5cde95fa7d6c8b04737c2d13": 1 | ||||
|                 }, | ||||
|                 "head": { | ||||
|                     "5cde96047d6c8b20b577f016": 1, | ||||
|                     "5fdb4139e4ed5b5ea251e4ed": 1, | ||||
|                     "5fdb5950f5264a66150d1c6e": 1, | ||||
|                     "60a6aa8fd559ae040d0d951f": 1, | ||||
|                     "619f9e338858a474c8685cc9": 1, | ||||
|                     "62aca6a1310e67685a2fc2e7": 1, | ||||
|                     "6574aabee0423b9ebe0c79cf": 1 | ||||
|                 } | ||||
|             } | ||||
|         }, | ||||
|         "pmcBEAR": { | ||||
|             "appearance": { | ||||
|                 "body": { | ||||
|                     "642e8ae07e17c882400c4f87": 1, | ||||
|                     "5d1f568486f7744bca3f0b98": 1, | ||||
|                     "66acec1dc94f4bf5bc063a16": 1, | ||||
|                     "5e4bb31586f7740695730568": 1 | ||||
|                 }, | ||||
|                 "feet": { | ||||
|                     "66acebd4ede86671bb09584b": 1, | ||||
|                     "5d1f58ab86f7743014162042": 1 | ||||
|                 }, | ||||
|                 "hands": { | ||||
|                     "5cc0876314c02e000c6bea6b": 1 | ||||
|                 }, | ||||
|                 "head": { | ||||
|                     "5cc084dd14c02e000b0550a3": 1, | ||||
|                     "5fdb50bb2b730a787b3f78cf": 1, | ||||
|                     "5fdb7571e4ed5b5ea251e529": 1, | ||||
|                     "60a6aaad42fd2735e4589978": 1, | ||||
|                     "619f94f5b90286142b59d45f": 1, | ||||
|                     "62a9e7d15ea3b87d6f642a28": 1, | ||||
|                     "6574aa9a1b144de18c0fba45": 1 | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							|  | @ -0,0 +1,436 @@ | |||
| {     | ||||
|     "scavAmmo": { | ||||
|         "Caliber1143x23ACP": { | ||||
|             "5efb0fc6aeb21837e749c801": 1, | ||||
|             "5efb0d4f4bc50b58e81710f3": 3 | ||||
|         }, | ||||
|         "Caliber127x55": { | ||||
|             "5cadf6e5ae921500113bb973": 1 | ||||
|         }, | ||||
|         "Caliber12g": { | ||||
|             "5d6e6772a4b936088465b17c": 2, | ||||
|             "5d6e6806a4b936088465b17e": 2, | ||||
|             "5d6e67fba4b9361bc73bc779": 2, | ||||
|             "560d5e524bdc2d25448b4571": 2, | ||||
|             "5d6e6869a4b9361c140bcfde": 1, | ||||
|             "5d6e68b3a4b9361bca7e50b5": 1, | ||||
|             "58820d1224597753c90aeb13": 1, | ||||
|             "5d6e68dea4b9361bcc29e659": 1, | ||||
|             "5d6e6891a4b9361bd473feea": 1, | ||||
|             "5d6e68e6a4b9361c140bcfe0": 1, | ||||
|             "5d6e689ca4b9361bc8618956": 1 | ||||
|         }, | ||||
|         "Caliber20g": { | ||||
|             "5d6e695fa4b936359b35d852": 2, | ||||
|             "5d6e69b9a4b9361bc8618958": 2, | ||||
|             "5a38ebd9c4a282000d722a5b": 2, | ||||
|             "5d6e69c7a4b9360b6c0d54e4": 1, | ||||
|             "5d6e6a53a4b9361bd473feec": 1 | ||||
|         }, | ||||
|         "Caliber23x75": { | ||||
|             "5f647f31b6238e5dd066e196": 3, | ||||
|             "5e85a9a6eacf8c039e4e2ac1": 1 | ||||
|         }, | ||||
|         "Caliber366TKM": { | ||||
|             "59e6658b86f77411d949b250": 3, | ||||
|             "59e6542b86f77411dc52a77a": 1 | ||||
|         }, | ||||
|         "Caliber40mmRU": { | ||||
|             "5656eb674bdc2d35148b457c": 1 | ||||
|         }, | ||||
|         "Caliber40x46": { | ||||
|             "5ede4739e0350d05467f73e8": 1, | ||||
|             "5ede47405b097655935d7d16": 1, | ||||
|             "5ede474b0c226a66f5402622": 1, | ||||
|             "5ede475339ee016e8c534742": 1, | ||||
|             "5ede475b549eed7c6d5c18fb": 1, | ||||
|             "5f0c892565703e5c461894e9": 1 | ||||
|         }, | ||||
|         "Caliber46x30": { | ||||
|             "5ba26812d4351e003201fef1": 3, | ||||
|             "5ba26844d4351e00334c9475": 1 | ||||
|         }, | ||||
|         "Caliber545x39": { | ||||
|             "56dff216d2720bbd668b4568": 1, | ||||
|             "56dff338d2720bbd668b4569": 4, | ||||
|             "56dff421d2720b5f5a8b4567": 4, | ||||
|             "56dff4ecd2720b5f5a8b4568": 2, | ||||
|             "56dff4a2d2720bbd668b456a": 4, | ||||
|             "56dff0bed2720bb0668b4567": 3, | ||||
|             "56dff3afd2720bba668b4567": 1 | ||||
|         }, | ||||
|         "Caliber556x45NATO": { | ||||
|             "59e6927d86f77411da468256": 2, | ||||
|             "59e6918f86f7746c9f75e849": 2, | ||||
|             "59e68f6f86f7746c9f75e846": 4, | ||||
|             "59e6920f86f77411d82aa167": 5, | ||||
|             "54527a984bdc2d4e668b4567": 1 | ||||
|         }, | ||||
|         "Caliber57x28": { | ||||
|             "5cc86832d7f00c000d3a6e6c": 2, | ||||
|             "5cc80f79e4a949033c7343b2": 3, | ||||
|             "5cc86840d7f00c002412c56c": 3, | ||||
|             "5cc80f8fe4a949033b0224a2": 1, | ||||
|             "5cc80f53e4a949000e1ea4f8": 1 | ||||
|         }, | ||||
|         "Caliber68x51": { | ||||
|             "6529302b8c26af6326029fb7": 1 | ||||
|         }, | ||||
|         "Caliber762x25TT": { | ||||
|             "573602322459776445391df1": 2, | ||||
|             "573601b42459776410737435": 2, | ||||
|             "5735fdcd2459776445391d61": 1, | ||||
|             "5736026a245977644601dc61": 1 | ||||
|         }, | ||||
|         "Caliber762x35": { | ||||
|             "6196365d58ef8c428c287da1": 1, | ||||
|             "6196364158ef8c428c287d9f": 6, | ||||
|             "5fbe3ffdf8b6a877a729ea82": 3 | ||||
|         }, | ||||
|         "Caliber762x39": { | ||||
|             "59e4d3d286f774176a36250a": 2, | ||||
|             "64b7af734b75259c590fa895": 2, | ||||
|             "64b7af5a8532cf95ee0a0dbd": 6, | ||||
|             "59e4d24686f7741776641ac7": 4, | ||||
|             "59e4cf5286f7741778269d8a": 2, | ||||
|             "5656d7c34bdc2d9d198b4587": 1 | ||||
|         }, | ||||
|         "Caliber762x51": { | ||||
|             "5e023e88277cce2b522ff2b1": 2, | ||||
|             "5e023e6e34d52a55c3304f71": 2, | ||||
|             "5e023e53d4353e3302577c4c": 1 | ||||
|         }, | ||||
|         "Caliber762x54R": { | ||||
|             "64b8f7c241772715af0f9c3d": 2, | ||||
|             "64b8f7b5389d7ffd620ccba2": 2, | ||||
|             "64b8f7968532cf95ee0a0dbf": 2, | ||||
|             "5e023cf8186a883be655e54f": 2, | ||||
|             "5887431f2459777e1612938f": 1 | ||||
|         }, | ||||
|         "Caliber86x70": { | ||||
|             "5fc382b6d6fa9c00c571bbc3": 2, | ||||
|             "5fc382c1016cce60e8341b20": 1 | ||||
|         }, | ||||
|         "Caliber9x18PM": { | ||||
|             "5737218f245977612125ba51": 5, | ||||
|             "57372140245977611f70ee91": 5, | ||||
|             "5737207f24597760ff7b25f2": 2, | ||||
|             "573719762459775a626ccbc1": 3, | ||||
|             "57371f8d24597761006c6a81": 3, | ||||
|             "57371f2b24597761224311f1": 5, | ||||
|             "57371eb62459776125652ac1": 1, | ||||
|             "57371b192459775a9f58a5e0": 1, | ||||
|             "57371e4124597760ff7b25f1": 1 | ||||
|         }, | ||||
|         "Caliber9x19PARA": { | ||||
|             "5efb0e16aeb21837e749c7ff": 1, | ||||
|             "58864a4f2459770fcc257101": 7, | ||||
|             "5a3c16fe86f77452b62de32a": 12, | ||||
|             "5c3df7d588a4501f290594e5": 6, | ||||
|             "64b7bbb74b75259c590fa897": 4, | ||||
|             "56d59d3ad2720bdb418b4577": 2 | ||||
|         }, | ||||
|         "Caliber9x21": { | ||||
|             "5a26ac06c4a282000c5a90a8": 5, | ||||
|             "5a26abfac4a28232980eabff": 3, | ||||
|             "5a269f97c4a282000b151807": 1 | ||||
|         }, | ||||
|         "Caliber9x33R": { | ||||
|             "62330c40bdd19b369e1e53d1": 5, | ||||
|             "62330bfadc5883093563729b": 3, | ||||
|             "62330c18744e5e31df12f516": 1 | ||||
|         }, | ||||
|         "Caliber9x39": { | ||||
|             "6576f96220d53a5b8f3e395e": 7, | ||||
|             "57a0dfb82459774d3078b56c": 5, | ||||
|             "5c0d668f86f7747ccb7f13b2": 1 | ||||
|         }, | ||||
|         "Caliber127x33": { | ||||
|             "66a0d1c87d0d369e270bb9de": 10, | ||||
|             "66a0d1f88486c69fce00fdf6": 1 | ||||
|         } | ||||
|     }, | ||||
|     "pmcAmmo": { | ||||
|         "Caliber1143x23ACP": { | ||||
|             "5ea2a8e200685063ec28c05a": 20, | ||||
|             "5efb0cabfb3e451d70735af5": 50 | ||||
|         }, | ||||
|         "Caliber127x55": { | ||||
|             "5cadf6ddae9215051e1c23b2": 15, | ||||
|             "5cadf6eeae921500134b2799": 85 | ||||
|         }, | ||||
|         "Caliber12g": { | ||||
|             "64b8ee384b75259c590fa89b": 15, | ||||
|             "5d6e6911a4b9361bd5780d52": 15, | ||||
|             "5d6e68c4a4b9361b93413f79": 25, | ||||
|             "5d6e68a8a4b9360b6c0d54e2": 45 | ||||
|         }, | ||||
|         "Caliber20g": { | ||||
|             "5d6e6a05a4b93618084f58d0": 20, | ||||
|             "5d6e6a42a4b9364f07165f52": 80 | ||||
|         }, | ||||
|         "Caliber23x75": { | ||||
|             "5e85a9a6eacf8c039e4e2ac1": 10, | ||||
|             "5e85aa1a988a8701445df1f5": 30 | ||||
|         }, | ||||
|         "Caliber366TKM": { | ||||
|             "5f0596629e22f464da6bbdd9": 1 | ||||
|         }, | ||||
|         "Caliber40mmRU": { | ||||
|             "5656eb674bdc2d35148b457c": 1 | ||||
|         }, | ||||
|         "Caliber40x46": { | ||||
|             "5ede4739e0350d05467f73e8": 1, | ||||
|             "5ede47405b097655935d7d16": 1, | ||||
|             "5ede474b0c226a66f5402622": 1, | ||||
|             "5ede475339ee016e8c534742": 1, | ||||
|             "5ede475b549eed7c6d5c18fb": 1, | ||||
|             "5f0c892565703e5c461894e9": 1 | ||||
|         }, | ||||
|         "Caliber46x30": { | ||||
|             "64b6979341772715af0f9c39": 20, | ||||
|             "5ba2678ad4351e44f824b344": 30, | ||||
|             "5ba26835d4351e0035628ff5": 50 | ||||
|         }, | ||||
|         "Caliber545x39": { | ||||
|             "56dff061d2720bb5668b4567": 5, | ||||
|             "61962b617c6c7b169525f168": 5, | ||||
|             "56dfef82d2720bbd668b4567": 15, | ||||
|             "56dff026d2720bb8668b4567": 35, | ||||
|             "5c0d5e4486f77478390952fe": 40 | ||||
|         }, | ||||
|         "Caliber556x45NATO": { | ||||
|             "54527ac44bdc2d36668b4567": 30, | ||||
|             "59e690b686f7746c9f75e848": 35, | ||||
|             "601949593ae8f707c4608daa": 35 | ||||
|         }, | ||||
|         "Caliber57x28": { | ||||
|             "5cc80f38e4a949001152b560": 1 | ||||
|         }, | ||||
|         "Caliber68x51": { | ||||
|             "6529302b8c26af6326029fb7": 20, | ||||
|             "6529243824cbe3c74a05e5c1": 80 | ||||
|         }, | ||||
|         "Caliber762x25TT": { | ||||
|             "573603562459776430731618": 10 | ||||
|         }, | ||||
|         "Caliber762x35": { | ||||
|             "619636be6db0f2477964e710": 20, | ||||
|             "64b8725c4b75259c590fa899": 40, | ||||
|             "5fd20ff893a8961fc660a954": 40 | ||||
|         }, | ||||
|         "Caliber762x39": { | ||||
|             "64b7af434b75259c590fa893": 10, | ||||
|             "59e0d99486f7744a32234762": 45, | ||||
|             "601aa3d2b2bcb34913271e6d": 45 | ||||
|         }, | ||||
|         "Caliber762x51": { | ||||
|             "58dd3ad986f77403051cba8f": 10, | ||||
|             "5a608bf24f39f98ffc77720e": 20, | ||||
|             "5a6086ea4f39f99cd479502f": 40, | ||||
|             "5efb0c1bd79ff02a1f5e68d9": 30 | ||||
|         }, | ||||
|         "Caliber762x54R": { | ||||
|             "5e023d34e8a400319a28ed44": 20, | ||||
|             "560d61e84bdc2da74d8b4571": 55, | ||||
|             "5e023d48186a883be655e551": 35 | ||||
|         }, | ||||
|         "Caliber86x70": { | ||||
|             "5fc275cf85fd526b824a571a": 50, | ||||
|             "5fc382a9d724d907e2077dab": 50 | ||||
|         }, | ||||
|         "Caliber9x18PM": { | ||||
|             "57371aab2459775a77142f22": 40, | ||||
|             "573719df2459775a626ccbc2": 60 | ||||
|         }, | ||||
|         "Caliber9x19PARA": { | ||||
|             "5c0d56a986f774449d5de529": 10, | ||||
|             "5c925fa22e221601da359b7b": 45, | ||||
|             "5efb0da7a29a85116f6ea05f": 45 | ||||
|         }, | ||||
|         "Caliber9x21": { | ||||
|             "6576f93989f0062e741ba952": 20, | ||||
|             "5a26ac0ec4a28200741e1e18": 30, | ||||
|             "6576f4708ca9c4381d16cd9d": 30 | ||||
|         }, | ||||
|         "Caliber9x33R": { | ||||
|             "62330b3ed4dc74626d570b95": 10 | ||||
|         }, | ||||
|         "Caliber9x39": { | ||||
|             "57a0e5022459774d1673f889": 40, | ||||
|             "5c0d688c86f77413ae3407b2": 60 | ||||
|         }, | ||||
|         "Caliber127x33": { | ||||
|             "66a0d1c87d0d369e270bb9de": 1, | ||||
|             "66a0d1f88486c69fce00fdf6": 3, | ||||
|             "66a0d1e0ed648d72fe064d06": 50, | ||||
|             "668fe62ac62660a5d8071446": 50 | ||||
|         } | ||||
|     }, | ||||
|     "bossAmmo": { | ||||
|         "Caliber1143x23ACP": { | ||||
|             "5ea2a8e200685063ec28c05a": 4, | ||||
|             "5efb0fc6aeb21837e749c801": 1, | ||||
|             "5efb0d4f4bc50b58e81710f3": 10, | ||||
|             "5e81f423763d9f754677bf2e": 18, | ||||
|             "5efb0cabfb3e451d70735af5": 10 | ||||
|         }, | ||||
|         "Caliber127x55": { | ||||
|             "5cadf6e5ae921500113bb973": 3, | ||||
|             "5cadf6ddae9215051e1c23b2": 12, | ||||
|             "5cadf6eeae921500134b2799": 8 | ||||
|         }, | ||||
|         "Caliber12g": { | ||||
|             "5d6e6806a4b936088465b17e": 7, | ||||
|             "64b8ee384b75259c590fa89b": 4, | ||||
|             "5d6e6911a4b9361bd5780d52": 3, | ||||
|             "5c0d591486f7744c505b416f": 5, | ||||
|             "5d6e6891a4b9361bd473feea": 2, | ||||
|             "5d6e68e6a4b9361c140bcfe0": 6, | ||||
|             "5d6e689ca4b9361bc8618956": 8, | ||||
|             "5d6e68c4a4b9361b93413f79": 8, | ||||
|             "5d6e68a8a4b9360b6c0d54e2": 3 | ||||
|         }, | ||||
|         "Caliber20g": { | ||||
|             "5d6e69c7a4b9360b6c0d54e4": 1, | ||||
|             "5d6e6a53a4b9361bd473feec": 4, | ||||
|             "5d6e6a05a4b93618084f58d0": 5, | ||||
|             "5d6e6a42a4b9364f07165f52": 5 | ||||
|         }, | ||||
|         "Caliber23x75": { | ||||
|             "5f647f31b6238e5dd066e196": 2, | ||||
|             "5e85a9a6eacf8c039e4e2ac1": 4, | ||||
|             "5e85aa1a988a8701445df1f5": 4 | ||||
|         }, | ||||
|         "Caliber366TKM": { | ||||
|             "59e6658b86f77411d949b250": 1, | ||||
|             "59e6542b86f77411dc52a77a": 2, | ||||
|             "59e655cb86f77411dc52a77b": 10, | ||||
|             "5f0596629e22f464da6bbdd9": 8 | ||||
|         }, | ||||
|         "Caliber40mmRU": { | ||||
|             "5656eb674bdc2d35148b457c": 1 | ||||
|         }, | ||||
|         "Caliber40x46": { | ||||
|             "5ede4739e0350d05467f73e8": 1, | ||||
|             "5ede47405b097655935d7d16": 1, | ||||
|             "5ede474b0c226a66f5402622": 1, | ||||
|             "5ede475339ee016e8c534742": 1, | ||||
|             "5ede475b549eed7c6d5c18fb": 1, | ||||
|             "5f0c892565703e5c461894e9": 1 | ||||
|         }, | ||||
|         "Caliber46x30": { | ||||
|             "5ba26812d4351e003201fef1": 2, | ||||
|             "5ba26844d4351e00334c9475": 4, | ||||
|             "5ba2678ad4351e44f824b344": 15, | ||||
|             "64b6979341772715af0f9c39": 15, | ||||
|             "5ba26835d4351e0035628ff5": 8 | ||||
|         }, | ||||
|         "Caliber545x39": { | ||||
|             "56dff3afd2720bba668b4567": 6, | ||||
|             "56dff2ced2720bb4668b4567": 12, | ||||
|             "56dff061d2720bb5668b4567": 20, | ||||
|             "61962b617c6c7b169525f168": 12, | ||||
|             "56dfef82d2720bbd668b4567": 9, | ||||
|             "56dff026d2720bb8668b4567": 8, | ||||
|             "5c0d5e4486f77478390952fe": 4 | ||||
|         }, | ||||
|         "Caliber556x45NATO": { | ||||
|             "5c0d5ae286f7741e46554302": 1, | ||||
|             "54527a984bdc2d4e668b4567": 7, | ||||
|             "60194943740c5d77f6705eea": 20, | ||||
|             "59e6906286f7746c9f75e847": 26, | ||||
|             "54527ac44bdc2d36668b4567": 30, | ||||
|             "59e690b686f7746c9f75e848": 7, | ||||
|             "601949593ae8f707c4608daa": 5 | ||||
|         }, | ||||
|         "Caliber57x28": { | ||||
|             "5cc80f8fe4a949033b0224a2": 5, | ||||
|             "5cc80f53e4a949000e1ea4f8": 21, | ||||
|             "5cc80f67e4a949035e43bbba": 15, | ||||
|             "5cc80f38e4a949001152b560": 12 | ||||
|         }, | ||||
|         "Caliber68x51": { | ||||
|             "6529302b8c26af6326029fb7": 10, | ||||
|             "6529243824cbe3c74a05e5c1": 5 | ||||
|         }, | ||||
|         "Caliber762x25TT": { | ||||
|             "5736026a245977644601dc61": 5, | ||||
|             "573603c924597764442bd9cb": 10, | ||||
|             "573603562459776430731618": 10 | ||||
|         }, | ||||
|         "Caliber762x35": { | ||||
|             "6196365d58ef8c428c287da1": 7, | ||||
|             "5fbe3ffdf8b6a877a729ea82": 6, | ||||
|             "619636be6db0f2477964e710": 23, | ||||
|             "64b8725c4b75259c590fa899": 20, | ||||
|             "5fd20ff893a8961fc660a954": 9 | ||||
|         }, | ||||
|         "Caliber762x39": { | ||||
|             "59e4cf5286f7741778269d8a": 4, | ||||
|             "5656d7c34bdc2d9d198b4587": 28, | ||||
|             "64b7af434b75259c590fa893": 33, | ||||
|             "59e0d99486f7744a32234762": 20, | ||||
|             "601aa3d2b2bcb34913271e6d": 12 | ||||
|         }, | ||||
|         "Caliber762x51": { | ||||
|             "5e023e53d4353e3302577c4c": 6, | ||||
|             "58dd3ad986f77403051cba8f": 27, | ||||
|             "5a608bf24f39f98ffc77720e": 19, | ||||
|             "5a6086ea4f39f99cd479502f": 9, | ||||
|             "5efb0c1bd79ff02a1f5e68d9": 2 | ||||
|         }, | ||||
|         "Caliber762x54R": { | ||||
|             "5e023cf8186a883be655e54f": 3, | ||||
|             "5887431f2459777e1612938f": 20, | ||||
|             "59e77a2386f7742ee578960a": 25, | ||||
|             "5e023d34e8a400319a28ed44": 22, | ||||
|             "560d61e84bdc2da74d8b4571": 15, | ||||
|             "5e023d48186a883be655e551": 10 | ||||
|         }, | ||||
|         "Caliber86x70": { | ||||
|             "5fc382b6d6fa9c00c571bbc3": 5, | ||||
|             "5fc382c1016cce60e8341b20": 8, | ||||
|             "5fc275cf85fd526b824a571a": 8, | ||||
|             "5fc382a9d724d907e2077dab": 5 | ||||
|         }, | ||||
|         "Caliber9x18PM": { | ||||
|             "57371e4124597760ff7b25f1": 3, | ||||
|             "5737201124597760fc4431f1": 5, | ||||
|             "573720e02459776143012541": 12, | ||||
|             "573718ba2459775a75491131": 18, | ||||
|             "57371aab2459775a77142f22": 12, | ||||
|             "573719df2459775a626ccbc2": 10 | ||||
|         }, | ||||
|         "Caliber9x19PARA": { | ||||
|             "5c0d56a986f774449d5de529": 9, | ||||
|             "5efb0e16aeb21837e749c7ff": 5, | ||||
|             "5a3c16fe86f77452b62de32a": 4, | ||||
|             "56d59d3ad2720bdb418b4577": 18, | ||||
|             "5c925fa22e221601da359b7b": 22, | ||||
|             "5efb0da7a29a85116f6ea05f": 9 | ||||
|         }, | ||||
|         "Caliber9x21": { | ||||
|             "5a269f97c4a282000b151807": 8, | ||||
|             "6576f93989f0062e741ba952": 18, | ||||
|             "5a26ac0ec4a28200741e1e18": 18, | ||||
|             "6576f4708ca9c4381d16cd9d": 8 | ||||
|         }, | ||||
|         "Caliber9x33R": { | ||||
|             "62330c18744e5e31df12f516": 9, | ||||
|             "62330b3ed4dc74626d570b95": 6 | ||||
|         }, | ||||
|         "Caliber9x39": { | ||||
|             "5c0d668f86f7747ccb7f13b2": 9, | ||||
|             "61962d879bb3d20b0946d385": 25, | ||||
|             "57a0e5022459774d1673f889": 25, | ||||
|             "5c0d688c86f77413ae3407b2": 12 | ||||
|         }, | ||||
|         "Caliber127x33": { | ||||
|             "66a0d1c87d0d369e270bb9de": 3, | ||||
|             "66a0d1f88486c69fce00fdf6": 30, | ||||
|             "66a0d1e0ed648d72fe064d06": 25,  | ||||
|             "668fe62ac62660a5d8071446": 12 | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,468 @@ | |||
| { | ||||
|     "pmcUSEC": { | ||||
|         "appearance": { | ||||
|             "body": { | ||||
|                 "6033a35f80ae5e2f970ba6bb": 1, | ||||
|                 "66043728333907134309d647": 1, | ||||
|                 "5d1f56e486f7744bce0ee9ed": 1, | ||||
|                 "6295e8c3e08ed747e64aea00": 1, | ||||
|                 "642c18b8a6a0660b560fb31c": 1, | ||||
|                 "66acbe49dc61999a6a03d4d6": 1, | ||||
|                 "5d4da0cb86f77450fe0a6629": 3, | ||||
|                 "660437e57502eca33a08caca": 3, | ||||
|                 "5fcf63da5c287f01f22bf245": 3, | ||||
|                 "618109c96d7ca35d076b3363": 3, | ||||
|                 "5d1f56f186f7744bcb0acd1a": 3, | ||||
|                 "64ef3efdb63b74469b6c1499": 5, | ||||
|                 "642c5273ff5ecad7810a89d7": 5, | ||||
|                 "5d1f56ff86f7743f8362bcd7": 5, | ||||
|                 "5e4bb35286f77406a511c9bc": 5, | ||||
|                 "5cdea33e7d6c8b0474535dac": 5, | ||||
|                 "5e9da17386f774054b6f79a3": 5, | ||||
|                 "5f5e4075df4f3100376a8138": 5 | ||||
|             }, | ||||
|             "feet": { | ||||
|                 "5fcf940bce1ba36a513bb9cc": 1, | ||||
|                 "660436487502eca33a08cac8": 1, | ||||
|                 "6571cad4c8673f00290f5657": 1, | ||||
|                 "637ba17aa10a96c2b605dbc2": 1, | ||||
|                 "5d1f591186f7744bcc048755": 1, | ||||
|                 "6295e944e9de5e7b3751c4da": 1, | ||||
|                 "642c19360a69698d1b049e12": 1, | ||||
|                 "66acc8f719271bd6d00dec0b": 1, | ||||
|                 "660436a810bcdf80ff0e9f78": 3, | ||||
|                 "617c02e24013b06b0b78df80": 3, | ||||
|                 "5d1f593286f7743014162044": 3, | ||||
|                 "5d1f592286f7743f8362bcdb": 3, | ||||
|                 "642d6941ff5ecad7810a8a61": 5, | ||||
|                 "5df8a08886f7740bfe6df775": 5, | ||||
|                 "5e4bb3b586f77406812bd579": 5, | ||||
|                 "5e9dcadd86f7743e20652f23": 5, | ||||
|                 "5f5e40a06760b4138443b341": 5 | ||||
|             }, | ||||
|             "hands": { | ||||
|                 "5cde95fa7d6c8b04737c2d13": 1 | ||||
|             }, | ||||
|             "head": { | ||||
|                 "5cde96047d6c8b20b577f016": 1, | ||||
|                 "5fdb4139e4ed5b5ea251e4ed": 1, | ||||
|                 "5fdb5950f5264a66150d1c6e": 1, | ||||
|                 "60a6aa8fd559ae040d0d951f": 1, | ||||
|                 "619f9e338858a474c8685cc9": 1, | ||||
|                 "62aca6a1310e67685a2fc2e7": 1, | ||||
|                 "6574aabee0423b9ebe0c79cf": 1 | ||||
|             } | ||||
|         } | ||||
|     }, | ||||
|     "pmcBEAR": { | ||||
|         "appearance": { | ||||
|             "body": { | ||||
|                 "657058fddf9b3231400e9188": 1, | ||||
|                 "6033a31e9ec839204e6a2f3e": 1, | ||||
|                 "66043cc27502eca33a08cad0": 1, | ||||
|                 "5fce3e47fe40296c1d5fd784": 1, | ||||
|                 "642ed297ac11c9eaf10d87e8": 1, | ||||
|                 "66acec1dc94f4bf5bc063a16": 1, | ||||
|                 "5d1f567786f7744bcc04874f": 3, | ||||
|                 "660440d2c8949a435906e43a": 3, | ||||
|                 "617bca4b4013b06b0b78df2a": 3, | ||||
|                 "5d1f566d86f7744bcd13459a": 3, | ||||
|                 "64ef3efdb63b74469b6c1499": 5, | ||||
|                 "6430119aac11c9eaf10d881b": 5, | ||||
|                 "5df89f1f86f77412631087ea": 5, | ||||
|                 "5e9d9fa986f774054d6b89f2": 5, | ||||
|                 "5cdea33e7d6c8b0474535dac": 5, | ||||
|                 "5e4bb31586f7740695730568": 5, | ||||
|                 "5f5e401747344c2e4f6c42c5": 5 | ||||
|             }, | ||||
|             "feet": { | ||||
|                 "6295e63de08ed747e64ae991": 1, | ||||
|                 "66043cf87502eca33a08cad2": 1, | ||||
|                 "6033a3d8ed2e0509b15f9031": 1, | ||||
|                 "5d1f58cb86f7744bca3f0b9a": 1, | ||||
|                 "5d1f58a086f7743f8362bcd9": 1, | ||||
|                 "642e71620a69698d1b049f0a": 1, | ||||
|                 "66acebd4ede86671bb09584b": 1, | ||||
|                 "66043d7ac8949a435906e434": 3, | ||||
|                 "5d1f58ab86f7743014162042": 3, | ||||
|                 "617be9e4e02b3b3fa50fa8f2": 3, | ||||
|                 "642eea6f881906a7fe086841": 5, | ||||
|                 "5df89f8f86f77412672a1e38": 5, | ||||
|                 "5e9dc97c86f774054c19ac9a": 5, | ||||
|                 "5e4bb39386f774067f79de05": 5, | ||||
|                 "5f5e40400bc58666c37e7819": 5 | ||||
|             }, | ||||
|             "hands": { | ||||
|                 "5cc0876314c02e000c6bea6b": 1 | ||||
|             }, | ||||
|             "head": { | ||||
|                 "5cc084dd14c02e000b0550a3": 1, | ||||
|                 "5fdb50bb2b730a787b3f78cf": 1, | ||||
|                 "5fdb7571e4ed5b5ea251e529": 1, | ||||
|                 "60a6aaad42fd2735e4589978": 1, | ||||
|                 "619f94f5b90286142b59d45f": 1, | ||||
|                 "62a9e7d15ea3b87d6f642a28": 1, | ||||
|                 "6574aa9a1b144de18c0fba45": 1 | ||||
|             } | ||||
|         } | ||||
|     }, | ||||
|     "springEarly": { | ||||
|         "pmcUSEC": { | ||||
|             "appearance": { | ||||
|                 "body": { | ||||
|                     "5d1f56c686f7744bcd13459c": 1, | ||||
|                     "5fd3e9f71b735718c25cd9f8": 1, | ||||
|                     "66043728333907134309d647": 1, | ||||
|                     "66acbe49dc61999a6a03d4d6": 1, | ||||
|                     "660437e57502eca33a08caca": 1, | ||||
|                     "5d1f56f186f7744bcb0acd1a": 1, | ||||
|                     "5d1f56ff86f7743f8362bcd7": 1, | ||||
|                     "5d1f56a686f7744bce0ee9eb": 2, | ||||
|                     "5e9da17386f774054b6f79a3": 2, | ||||
|                     "5e4bb35286f77406a511c9bc": 2, | ||||
|                     "5d1f56e486f7744bce0ee9ed": 2 | ||||
|                 }, | ||||
|                 "feet": { | ||||
|                     "642d4d8eb6b75d4c89077cf9": 1, | ||||
|                     "5fcf940bce1ba36a513bb9cc": 1, | ||||
|                     "66acc8f719271bd6d00dec0b": 1, | ||||
|                     "6295e944e9de5e7b3751c4da": 1, | ||||
|                     "5d1f592286f7743f8362bcdb": 1, | ||||
|                     "5e4bb3b586f77406812bd579": 1, | ||||
|                     "5d1f590486f7744bcd13459e": 3, | ||||
|                     "5d1f58ed86f7744bcb0acd1c": 3 | ||||
|                 }, | ||||
|                 "hands": { | ||||
|                     "5cde95fa7d6c8b04737c2d13": 1 | ||||
|                 }, | ||||
|                 "head": { | ||||
|                     "5cde96047d6c8b20b577f016": 1, | ||||
|                     "5fdb4139e4ed5b5ea251e4ed": 1, | ||||
|                     "5fdb5950f5264a66150d1c6e": 1, | ||||
|                     "60a6aa8fd559ae040d0d951f": 1, | ||||
|                     "619f9e338858a474c8685cc9": 1, | ||||
|                     "62aca6a1310e67685a2fc2e7": 1, | ||||
|                     "6574aabee0423b9ebe0c79cf": 1 | ||||
|                 } | ||||
|             } | ||||
|         }, | ||||
|         "pmcBEAR": { | ||||
|             "appearance": { | ||||
|                 "body": { | ||||
|                     "657058fddf9b3231400e9188": 1, | ||||
|                     "6033a31e9ec839204e6a2f3e": 1, | ||||
|                     "5d1f567786f7744bcc04874f": 1, | ||||
|                     "5e9d9fa986f774054d6b89f2": 1, | ||||
|                     "5f5e401747344c2e4f6c42c5": 1, | ||||
|                     "642e8ae07e17c882400c4f87": 2, | ||||
|                     "5d1f568486f7744bca3f0b98": 2, | ||||
|                     "66acec1dc94f4bf5bc063a16": 2, | ||||
|                     "5e4bb31586f7740695730568": 2 | ||||
|                 }, | ||||
|                 "feet": { | ||||
|                     "5d1f58bd86f7744bce0ee9ef": 1, | ||||
|                     "6377315993a3b4967208e437": 1, | ||||
|                     "66043cf87502eca33a08cad2": 1, | ||||
|                     "5d1f58cb86f7744bca3f0b9a": 1, | ||||
|                     "5d1f58a086f7743f8362bcd9": 1, | ||||
|                     "617be9e4e02b3b3fa50fa8f2": 1, | ||||
|                     "5f5e40400bc58666c37e7819": 1, | ||||
|                     "66acebd4ede86671bb09584b": 3, | ||||
|                     "5d1f58ab86f7743014162042": 3 | ||||
|                 }, | ||||
|                 "hands": { | ||||
|                     "5cc0876314c02e000c6bea6b": 1 | ||||
|                 }, | ||||
|                 "head": { | ||||
|                     "5cc084dd14c02e000b0550a3": 1, | ||||
|                     "5fdb50bb2b730a787b3f78cf": 1, | ||||
|                     "5fdb7571e4ed5b5ea251e529": 1, | ||||
|                     "60a6aaad42fd2735e4589978": 1, | ||||
|                     "619f94f5b90286142b59d45f": 1, | ||||
|                     "62a9e7d15ea3b87d6f642a28": 1, | ||||
|                     "6574aa9a1b144de18c0fba45": 1 | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     }, | ||||
|     "spring": { | ||||
|         "pmcUSEC": { | ||||
|             "appearance": { | ||||
|                 "body": { | ||||
|                     "5cde95d97d6c8b647a3769b0": 1, | ||||
|                     "5fd3e9f71b735718c25cd9f8": 1, | ||||
|                     "66043728333907134309d647": 1, | ||||
|                     "5d4da0cb86f77450fe0a6629": 1, | ||||
|                     "5d1f56f186f7744bcb0acd1a": 1, | ||||
|                     "5f5e4075df4f3100376a8138": 1 | ||||
|                 }, | ||||
|                 "feet": { | ||||
|                     "5cde95ef7d6c8b04713c4f2d": 1, | ||||
|                     "6033a3fee29c9f6c9b14e74e": 1, | ||||
|                     "660436487502eca33a08cac8": 1, | ||||
|                     "6571cad4c8673f00290f5657": 1, | ||||
|                     "66acc8f719271bd6d00dec0b": 1, | ||||
|                     "5d1f592286f7743f8362bcdb": 1, | ||||
|                     "642d6941ff5ecad7810a8a61": 1, | ||||
|                     "5e9dcadd86f7743e20652f23": 1 | ||||
|                 }, | ||||
|                 "hands": { | ||||
|                     "5cde95fa7d6c8b04737c2d13": 1 | ||||
|                 }, | ||||
|                 "head": { | ||||
|                     "5cde96047d6c8b20b577f016": 1, | ||||
|                     "5fdb4139e4ed5b5ea251e4ed": 1, | ||||
|                     "5fdb5950f5264a66150d1c6e": 1, | ||||
|                     "60a6aa8fd559ae040d0d951f": 1, | ||||
|                     "619f9e338858a474c8685cc9": 1, | ||||
|                     "62aca6a1310e67685a2fc2e7": 1, | ||||
|                     "6574aabee0423b9ebe0c79cf": 1 | ||||
|                 } | ||||
|             } | ||||
|         }, | ||||
|         "pmcBEAR": { | ||||
|             "appearance": { | ||||
|                 "body": { | ||||
|                     "5cc0858d14c02e000c6bea66": 1, | ||||
|                     "5d1f564b86f7744bcb0acd16": 1, | ||||
|                     "6295e698e9de5e7b3751c47a": 1, | ||||
|                     "6033a31e9ec839204e6a2f3e": 1, | ||||
|                     "5fce3e47fe40296c1d5fd784": 1, | ||||
|                     "617bca4b4013b06b0b78df2a": 1, | ||||
|                     "5df89f1f86f77412631087ea": 1 | ||||
|                 }, | ||||
|                 "feet": { | ||||
|                     "5cc085bb14c02e000e67a5c5": 1, | ||||
|                     "5d1f588e86f7744bcc048753": 1, | ||||
|                     "66043cf87502eca33a08cad2": 1, | ||||
|                     "6033a3d8ed2e0509b15f9031": 1, | ||||
|                     "642e71620a69698d1b049f0a": 1, | ||||
|                     "617be9e4e02b3b3fa50fa8f2": 1, | ||||
|                     "642eea6f881906a7fe086841": 1, | ||||
|                     "5df89f8f86f77412672a1e38": 1, | ||||
|                     "5e9dc97c86f774054c19ac9a": 1, | ||||
|                     "5e4bb39386f774067f79de05": 1 | ||||
|                 }, | ||||
|                 "hands": { | ||||
|                     "5cc0876314c02e000c6bea6b": 1 | ||||
|                 }, | ||||
|                 "head": { | ||||
|                     "5cc084dd14c02e000b0550a3": 1, | ||||
|                     "5fdb50bb2b730a787b3f78cf": 1, | ||||
|                     "5fdb7571e4ed5b5ea251e529": 1, | ||||
|                     "60a6aaad42fd2735e4589978": 1, | ||||
|                     "619f94f5b90286142b59d45f": 1, | ||||
|                     "62a9e7d15ea3b87d6f642a28": 1, | ||||
|                     "6574aa9a1b144de18c0fba45": 1 | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     }, | ||||
|     "summer": { | ||||
|         "pmcUSEC": { | ||||
|             "appearance": { | ||||
|                 "body": { | ||||
|                     "5cde95d97d6c8b647a3769b0": 1, | ||||
|                     "5d1f56c686f7744bcd13459c": 1, | ||||
|                     "5fd3e9f71b735718c25cd9f8": 1, | ||||
|                     "66043728333907134309d647": 1, | ||||
|                     "5d4da0cb86f77450fe0a6629": 1, | ||||
|                     "66acbe49dc61999a6a03d4d6": 1, | ||||
|                     "64ef3efdb63b74469b6c1499": 1, | ||||
|                     "642c18b8a6a0660b560fb31c": 1, | ||||
|                     "5d1f56f186f7744bcb0acd1a": 1, | ||||
|                     "5f5e4075df4f3100376a8138": 1 | ||||
|                 }, | ||||
|                 "feet": { | ||||
|                     "5cde95ef7d6c8b04713c4f2d": 1, | ||||
|                     "6033a3fee29c9f6c9b14e74e": 1, | ||||
|                     "660436487502eca33a08cac8": 1, | ||||
|                     "6571cad4c8673f00290f5657": 1, | ||||
|                     "66acc8f719271bd6d00dec0b": 1, | ||||
|                     "5d1f593286f7743014162044": 1, | ||||
|                     "5d1f592286f7743f8362bcdb": 1, | ||||
|                     "642d6941ff5ecad7810a8a61": 1, | ||||
|                     "5e9dcadd86f7743e20652f23": 1 | ||||
|                 }, | ||||
|                 "hands": { | ||||
|                     "5cde95fa7d6c8b04737c2d13": 1 | ||||
|                 }, | ||||
|                 "head": { | ||||
|                     "5cde96047d6c8b20b577f016": 1, | ||||
|                     "5fdb4139e4ed5b5ea251e4ed": 1, | ||||
|                     "5fdb5950f5264a66150d1c6e": 1, | ||||
|                     "60a6aa8fd559ae040d0d951f": 1, | ||||
|                     "619f9e338858a474c8685cc9": 1, | ||||
|                     "62aca6a1310e67685a2fc2e7": 1, | ||||
|                     "6574aabee0423b9ebe0c79cf": 1 | ||||
|                 } | ||||
|             } | ||||
|         }, | ||||
|         "pmcBEAR": { | ||||
|             "appearance": { | ||||
|                 "body": { | ||||
|                     "5cc0858d14c02e000c6bea66": 1, | ||||
|                     "5d1f564b86f7744bcb0acd16": 1, | ||||
|                     "6295e698e9de5e7b3751c47a": 1, | ||||
|                     "6033a31e9ec839204e6a2f3e": 1, | ||||
|                     "5fce3e47fe40296c1d5fd784": 1, | ||||
|                     "617bca4b4013b06b0b78df2a": 1, | ||||
|                     "64ef3efdb63b74469b6c1499": 1, | ||||
|                     "5df89f1f86f77412631087ea": 1, | ||||
|                     "5e9d9fa986f774054d6b89f2": 1 | ||||
|                 }, | ||||
|                 "feet": { | ||||
|                     "5cc085bb14c02e000e67a5c5": 1, | ||||
|                     "5d1f588e86f7744bcc048753": 1, | ||||
|                     "66043cf87502eca33a08cad2": 1, | ||||
|                     "6033a3d8ed2e0509b15f9031": 1, | ||||
|                     "642e71620a69698d1b049f0a": 1, | ||||
|                     "617be9e4e02b3b3fa50fa8f2": 1, | ||||
|                     "642eea6f881906a7fe086841": 1, | ||||
|                     "5df89f8f86f77412672a1e38": 1, | ||||
|                     "5e9dc97c86f774054c19ac9a": 1, | ||||
|                     "5e4bb39386f774067f79de05": 1 | ||||
|                 }, | ||||
|                 "hands": { | ||||
|                     "5cc0876314c02e000c6bea6b": 1 | ||||
|                 }, | ||||
|                 "head": { | ||||
|                     "5cc084dd14c02e000b0550a3": 1, | ||||
|                     "5fdb50bb2b730a787b3f78cf": 1, | ||||
|                     "5fdb7571e4ed5b5ea251e529": 1, | ||||
|                     "60a6aaad42fd2735e4589978": 1, | ||||
|                     "619f94f5b90286142b59d45f": 1, | ||||
|                     "62a9e7d15ea3b87d6f642a28": 1, | ||||
|                     "6574aa9a1b144de18c0fba45": 1 | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     }, | ||||
|     "autumn": { | ||||
|         "pmcUSEC": { | ||||
|             "appearance": { | ||||
|                 "body": { | ||||
|                     "5d1f56c686f7744bcd13459c": 1, | ||||
|                     "637b945722e2a933ed0e33c8": 1, | ||||
|                     "6571cb0923aa6d72760a7f8f": 1, | ||||
|                     "6033a35f80ae5e2f970ba6bb": 1, | ||||
|                     "5d1f56e486f7744bce0ee9ed": 1, | ||||
|                     "66acbe49dc61999a6a03d4d6": 1, | ||||
|                     "660437e57502eca33a08caca": 1, | ||||
|                     "64ef3efdb63b74469b6c1499": 1, | ||||
|                     "5d1f56ff86f7743f8362bcd7": 1 | ||||
|                 }, | ||||
|                 "feet": { | ||||
|                     "642d4d8eb6b75d4c89077cf9": 1, | ||||
|                     "5fcf940bce1ba36a513bb9cc": 1, | ||||
|                     "637ba17aa10a96c2b605dbc2": 1, | ||||
|                     "6295e944e9de5e7b3751c4da": 1, | ||||
|                     "5e4bb3b586f77406812bd579": 1, | ||||
|                     "5f5e40a06760b4138443b341": 1 | ||||
|                 }, | ||||
|                 "hands": { | ||||
|                     "5cde95fa7d6c8b04737c2d13": 1 | ||||
|                 }, | ||||
|                 "head": { | ||||
|                     "5cde96047d6c8b20b577f016": 1, | ||||
|                     "5fdb4139e4ed5b5ea251e4ed": 1, | ||||
|                     "5fdb5950f5264a66150d1c6e": 1, | ||||
|                     "60a6aa8fd559ae040d0d951f": 1, | ||||
|                     "619f9e338858a474c8685cc9": 1, | ||||
|                     "62aca6a1310e67685a2fc2e7": 1, | ||||
|                     "6574aabee0423b9ebe0c79cf": 1 | ||||
|                 } | ||||
|             } | ||||
|         }, | ||||
|         "pmcBEAR": { | ||||
|             "appearance": { | ||||
|                 "body": { | ||||
|                     "6377266693a3b4967208e42b": 1, | ||||
|                     "5d1f568486f7744bca3f0b98": 1, | ||||
|                     "657058fddf9b3231400e9188": 1, | ||||
|                     "642ed297ac11c9eaf10d87e8": 1, | ||||
|                     "5d1f567786f7744bcc04874f": 1, | ||||
|                     "64ef3efdb63b74469b6c1499": 1, | ||||
|                     "6430119aac11c9eaf10d881b": 1, | ||||
|                     "5f5e401747344c2e4f6c42c5": 1 | ||||
|                 }, | ||||
|                 "feet": { | ||||
|                     "5d1f58bd86f7744bce0ee9ef": 1, | ||||
|                     "6377315993a3b4967208e437": 1, | ||||
|                     "642ed40af5bdf1c04e01952e": 1, | ||||
|                     "6295e63de08ed747e64ae991": 1, | ||||
|                     "5d1f58a086f7743f8362bcd9": 1, | ||||
|                     "66043d7ac8949a435906e434": 1, | ||||
|                     "5d1f58ab86f7743014162042": 1, | ||||
|                     "5f5e40400bc58666c37e7819": 1 | ||||
|                 }, | ||||
|                 "hands": { | ||||
|                     "5cc0876314c02e000c6bea6b": 1 | ||||
|                 }, | ||||
|                 "head": { | ||||
|                     "5cc084dd14c02e000b0550a3": 1, | ||||
|                     "5fdb50bb2b730a787b3f78cf": 1, | ||||
|                     "5fdb7571e4ed5b5ea251e529": 1, | ||||
|                     "60a6aaad42fd2735e4589978": 1, | ||||
|                     "619f94f5b90286142b59d45f": 1, | ||||
|                     "62a9e7d15ea3b87d6f642a28": 1, | ||||
|                     "6574aa9a1b144de18c0fba45": 1 | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     }, | ||||
|     "winter": { | ||||
|         "pmcUSEC": { | ||||
|             "appearance": { | ||||
|                 "body": { | ||||
|                     "5d1f56a686f7744bce0ee9eb": 1, | ||||
|                     "5e9da17386f774054b6f79a3": 1, | ||||
|                     "5e4bb35286f77406a511c9bc": 1, | ||||
|                     "5d1f56e486f7744bce0ee9ed": 1 | ||||
|                 }, | ||||
|                 "feet": { | ||||
|                     "5d1f590486f7744bcd13459e": 1, | ||||
|                     "5d1f58ed86f7744bcb0acd1c": 1 | ||||
|                 }, | ||||
|                 "hands": { | ||||
|                     "5cde95fa7d6c8b04737c2d13": 1 | ||||
|                 }, | ||||
|                 "head": { | ||||
|                     "5cde96047d6c8b20b577f016": 1, | ||||
|                     "5fdb4139e4ed5b5ea251e4ed": 1, | ||||
|                     "5fdb5950f5264a66150d1c6e": 1, | ||||
|                     "60a6aa8fd559ae040d0d951f": 1, | ||||
|                     "619f9e338858a474c8685cc9": 1, | ||||
|                     "62aca6a1310e67685a2fc2e7": 1, | ||||
|                     "6574aabee0423b9ebe0c79cf": 1 | ||||
|                 } | ||||
|             } | ||||
|         }, | ||||
|         "pmcBEAR": { | ||||
|             "appearance": { | ||||
|                 "body": { | ||||
|                     "642e8ae07e17c882400c4f87": 1, | ||||
|                     "5d1f568486f7744bca3f0b98": 1, | ||||
|                     "66acec1dc94f4bf5bc063a16": 1, | ||||
|                     "5e4bb31586f7740695730568": 1 | ||||
|                 }, | ||||
|                 "feet": { | ||||
|                     "66acebd4ede86671bb09584b": 1, | ||||
|                     "5d1f58ab86f7743014162042": 1 | ||||
|                 }, | ||||
|                 "hands": { | ||||
|                     "5cc0876314c02e000c6bea6b": 1 | ||||
|                 }, | ||||
|                 "head": { | ||||
|                     "5cc084dd14c02e000b0550a3": 1, | ||||
|                     "5fdb50bb2b730a787b3f78cf": 1, | ||||
|                     "5fdb7571e4ed5b5ea251e529": 1, | ||||
|                     "60a6aaad42fd2735e4589978": 1, | ||||
|                     "619f94f5b90286142b59d45f": 1, | ||||
|                     "62a9e7d15ea3b87d6f642a28": 1, | ||||
|                     "6574aa9a1b144de18c0fba45": 1 | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							|  | @ -0,0 +1,635 @@ | |||
| /* eslint-disable @typescript-eslint/naming-convention */ | ||||
| import { injectable, inject } from "tsyringe"; | ||||
| import { IDatabaseTables } from "@spt/models/spt/server/IDatabaseTables"; | ||||
| import { ConfigServer } from "@spt/servers/ConfigServer"; | ||||
| import { IBotConfig } from "@spt/models/spt/config/IBotConfig"; | ||||
| import { IPmcConfig } from "@spt/models/spt/config/IPmcConfig"; | ||||
| import { ConfigTypes } from "@spt/models/enums/ConfigTypes"; | ||||
| import { DatabaseService } from "@spt/services/DatabaseService"; | ||||
| import { BaseClasses } from "@spt/models/enums/BaseClasses"; | ||||
| import { ItemHelper } from "@spt/helpers/ItemHelper"; | ||||
| 
 | ||||
| import { APBSEquipmentGetter } from "../Utils/APBSEquipmentGetter"; | ||||
| import { TierInformation } from "../Globals/TierInformation"; | ||||
| import { RaidInformation } from "../Globals/RaidInformation"; | ||||
| import { ModConfig } from "../Globals/ModConfig"; | ||||
| import { APBSLogger } from "../Utils/APBSLogger"; | ||||
| import { Logging } from "../Enums/Logging"; | ||||
| 
 | ||||
| 
 | ||||
| @injectable() | ||||
| export class BotConfigs | ||||
| { | ||||
|     protected botConfig: IBotConfig; | ||||
|     protected pmcConfig: IPmcConfig; | ||||
|      | ||||
|     private pmcLimitedCategories = { | ||||
|         "5448e8d04bdc2ddf718b4569": 1, | ||||
|         "5448e8d64bdc2dce718b4568": 1, | ||||
|         "5448f39d4bdc2d0a728b4568": 1, | ||||
|         "5448f3a64bdc2d60728b456a": 2, | ||||
|         "5448f3ac4bdc2dce718b4569": 1, | ||||
|         "5448f3a14bdc2d27728b4569": 1,         | ||||
|         "5c99f98d86f7745c314214b3": 1, | ||||
|         "5c164d2286f774194c5e69fa": 1, | ||||
|         "550aa4cd4bdc2dd8348b456c": 2, | ||||
|         "55818add4bdc2d5b648b456f": 1, | ||||
|         "55818ad54bdc2ddc698b4569": 1, | ||||
|         "55818aeb4bdc2ddc698b456a": 1, | ||||
|         "55818ae44bdc2dde698b456c": 1, | ||||
|         "55818af64bdc2d5b648b4570": 1, | ||||
|         "5448e54d4bdc2dcc718b4568": 1, | ||||
|         "5447e1d04bdc2dff2f8b4567": 1, | ||||
|         "5a341c4686f77469e155819e": 1, | ||||
|         "55818b164bdc2ddc698b456c": 2, | ||||
|         "5448bc234bdc2d3c308b4569": 2, | ||||
|         "543be5dd4bdc2deb348b4569": 1, | ||||
|         "543be5cb4bdc2deb348b4568": 2, | ||||
|         "5485a8684bdc2da71d8b4567": 2, | ||||
|         "5d650c3e815116009f6201d2": 2, | ||||
|         "543be6564bdc2df4348b4568": 4 | ||||
|     } | ||||
| 
 | ||||
|     constructor( | ||||
|         @inject("IDatabaseTables") protected tables: IDatabaseTables, | ||||
|         @inject("DatabaseService") protected database: DatabaseService, | ||||
|         @inject("ConfigServer") protected configServer: ConfigServer, | ||||
|         @inject("ItemHelper") protected itemHelper: ItemHelper, | ||||
|         @inject("APBSEquipmentGetter") protected apbsEquipmentGetter: APBSEquipmentGetter, | ||||
|         @inject("TierInformation") protected tierInformation: TierInformation, | ||||
|         @inject("RaidInformation") protected raidInformation: RaidInformation, | ||||
|         @inject("APBSLogger") protected apbsLogger: APBSLogger | ||||
|     ) | ||||
|     { | ||||
|         this.botConfig = this.configServer.getConfig(ConfigTypes.BOT); | ||||
|         this.pmcConfig = this.configServer.getConfig(ConfigTypes.PMC); | ||||
|     } | ||||
| 
 | ||||
|     public initialize(): void | ||||
|     { | ||||
|         if (!ModConfig.config.disablePMCTierGeneration) | ||||
|         { | ||||
|             this.setPMCItemLimits(); | ||||
|             this.setPMCLoot(); | ||||
|             this.setPMCScopeWhitelist(); | ||||
|             this.setPMCSlotIDsToMakeRequired(); | ||||
|             if (ModConfig.config.gameVersionWeight) this.setPMCGameVersionWeights(); | ||||
|         } | ||||
|         if (!ModConfig.config.disableScavTierGeneration) | ||||
|         { | ||||
|             if (ModConfig.config.addAllKeysToScavs || ModConfig.config.addOnlyKeyCardsToScavs || ModConfig.config.addOnlyMechanicalKeysToScavs) this.pushScavKeys(); | ||||
|             if (!ModConfig.config.scavLoot) this.removeScavLoot(); | ||||
|         } | ||||
| 
 | ||||
|         this.clearNoLongerNeededBotDetails(); | ||||
|         this.configureBotExperienceLevels(); | ||||
|         this.configurePlateWeightings(); | ||||
|         this.configureWeaponDurability(); | ||||
|         this.adjustNVG(); | ||||
|         this.setLootItemResourceRandomization(); | ||||
|         this.removeThermalGoggles(ModConfig.config.enableT7Thermals); | ||||
|          | ||||
|         if (ModConfig.config.enableCustomPlateChances) this.setPlateChances(); | ||||
|         if (ModConfig.config.forceStock) this.setForceStock(); | ||||
|         if (ModConfig.config.forceDustCover) this.setForceDustCover(); | ||||
|         if (ModConfig.config.forceScopeSlot) this.setForceScopes(); | ||||
|         if (ModConfig.config.forceWeaponModLimits) this.setWeaponModLimits(); | ||||
|         if (ModConfig.config.enableScavEqualEquipmentTiering) this.setIdenticalScavWeights(); | ||||
|         if (ModConfig.config.enableCustomLevelDeltas) this.setLevelDeltas(); | ||||
|         if (ModConfig.config.enableScavCustomLevelDeltas) this.setScavLevelDeltas(); | ||||
|         if (ModConfig.config.forceMuzzle) this.setMuzzleChances(); | ||||
|     } | ||||
| 
 | ||||
|     private configureBotExperienceLevels(): void | ||||
|     { | ||||
|         const botTypeTable = this.tables.bots.types; | ||||
| 
 | ||||
|         for (const botType in botTypeTable) | ||||
|         { | ||||
|             botTypeTable[botType].experience.level.min = 1; | ||||
|             botTypeTable[botType].experience.level.max = 79; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private configurePlateWeightings(): void | ||||
|     { | ||||
|         const botConfigEquipment = this.botConfig.equipment | ||||
|         for (const botType in botConfigEquipment) | ||||
|         { | ||||
|             if (botType.includes("assault") || botType.includes("marksman")) | ||||
|             { | ||||
|                 botConfigEquipment[botType].filterPlatesByLevel = true; | ||||
|                 botConfigEquipment[botType].armorPlateWeighting = this.tierInformation.scavArmorPlateWeights; | ||||
|                 continue; | ||||
|             } | ||||
|             botConfigEquipment[botType].filterPlatesByLevel = true; | ||||
|             botConfigEquipment[botType].armorPlateWeighting = this.tierInformation.armorPlateWeights; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private clearNoLongerNeededBotDetails(): void | ||||
|     { | ||||
|         const botConfigEquipment = this.botConfig.equipment | ||||
|         for (const botType in botConfigEquipment) | ||||
|         { | ||||
|             botConfigEquipment[botType].randomisation = []; | ||||
|             botConfigEquipment[botType].weightingAdjustmentsByBotLevel = []; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private configureWeaponDurability(): void | ||||
|     { | ||||
|         // Do this better in the future - this looks like shit. Bad Acid. Bad.
 | ||||
|         const botConfigDurability = this.botConfig.durability | ||||
| 
 | ||||
|         for (const botType in botConfigDurability) | ||||
|         { | ||||
|             if (botType == "pmc") | ||||
|             { | ||||
|                 botConfigDurability[botType].weapon.lowestMax = ModConfig.config.pmcWeaponDurability[0] | ||||
|                 botConfigDurability[botType].weapon.highestMax = ModConfig.config.pmcWeaponDurability[1] | ||||
|                 botConfigDurability[botType].weapon.minDelta = ModConfig.config.pmcWeaponDurability[2] | ||||
|                 botConfigDurability[botType].weapon.maxDelta = ModConfig.config.pmcWeaponDurability[3] | ||||
|                 botConfigDurability[botType].weapon.minLimitPercent = 40 | ||||
|             } | ||||
|             if (botType == "boss" || botType == "arenafighterevent" || botType == "arenafighter" || botType == "sectantpriest" || botType == "sectantwarrior") | ||||
|             { | ||||
|                 botConfigDurability[botType].weapon.lowestMax = ModConfig.config.bossWeaponDurability[0] | ||||
|                 botConfigDurability[botType].weapon.highestMax = ModConfig.config.bossWeaponDurability[1] | ||||
|                 botConfigDurability[botType].weapon.minDelta = ModConfig.config.bossWeaponDurability[2] | ||||
|                 botConfigDurability[botType].weapon.maxDelta = ModConfig.config.bossWeaponDurability[3] | ||||
|                 botConfigDurability[botType].weapon.minLimitPercent = 40 | ||||
|             } | ||||
|             if (botType == "assault" || botType == "cursedassault" || botType == "marksman" || botType == "crazyassaultevent" || botType == "default") | ||||
|             { | ||||
|                 botConfigDurability[botType].weapon.lowestMax = ModConfig.config.scavWeaponDurability[0] | ||||
|                 botConfigDurability[botType].weapon.highestMax = ModConfig.config.scavWeaponDurability[1] | ||||
|                 botConfigDurability[botType].weapon.minDelta = ModConfig.config.scavWeaponDurability[2] | ||||
|                 botConfigDurability[botType].weapon.maxDelta = ModConfig.config.scavWeaponDurability[3] | ||||
|                 botConfigDurability[botType].weapon.minLimitPercent = 40 | ||||
|             } | ||||
|             if (botType == "follower") | ||||
|             { | ||||
|                 botConfigDurability[botType].weapon.lowestMax = ModConfig.config.guardWeaponDurability[0] | ||||
|                 botConfigDurability[botType].weapon.highestMax = ModConfig.config.guardWeaponDurability[1] | ||||
|                 botConfigDurability[botType].weapon.minDelta = ModConfig.config.guardWeaponDurability[2] | ||||
|                 botConfigDurability[botType].weapon.maxDelta = ModConfig.config.guardWeaponDurability[3] | ||||
|                 botConfigDurability[botType].weapon.minLimitPercent = 40 | ||||
|             } | ||||
|             if (botType == "pmcbot" || botType == "exusec") | ||||
|             { | ||||
|                 botConfigDurability[botType].weapon.lowestMax = ModConfig.config.raiderWeaponDurability[0] | ||||
|                 botConfigDurability[botType].weapon.highestMax = ModConfig.config.raiderWeaponDurability[1] | ||||
|                 botConfigDurability[botType].weapon.minDelta = ModConfig.config.raiderWeaponDurability[2] | ||||
|                 botConfigDurability[botType].weapon.maxDelta = ModConfig.config.raiderWeaponDurability[3] | ||||
|                 botConfigDurability[botType].weapon.minLimitPercent = 40 | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private adjustNVG(): void | ||||
|     { | ||||
|         const botConfigEquipment = this.botConfig.equipment | ||||
| 
 | ||||
|         for (const botType in botConfigEquipment) | ||||
|         { | ||||
|             botConfigEquipment[botType].faceShieldIsActiveChancePercent = 90; | ||||
|             botConfigEquipment[botType].lightIsActiveDayChancePercent = 7; | ||||
|             botConfigEquipment[botType].lightIsActiveNightChancePercent = 25; | ||||
|             botConfigEquipment[botType].laserIsActiveChancePercent = 50; | ||||
|             botConfigEquipment[botType].nvgIsActiveChanceDayPercent = 0; | ||||
|             botConfigEquipment[botType].nvgIsActiveChanceNightPercent = 95; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private setForceStock(): void | ||||
|     { | ||||
|         for (const tierObject in this.tierInformation.tiers) | ||||
|         { | ||||
|             const tierNumber = this.tierInformation.tiers[tierObject].tier | ||||
|             const tierJson = this.apbsEquipmentGetter.getTierChancesJson(tierNumber); | ||||
| 
 | ||||
|             for (const botType in this.tierInformation.tier1chances) | ||||
|             { | ||||
|                 const chances = tierJson[botType].chances | ||||
|                 for (const weaponType in chances) | ||||
|                 { | ||||
|                     chances[weaponType]["mod_stock"] = 100; | ||||
|                     chances[weaponType]["mod_stock_000"] = 100; | ||||
|                     chances[weaponType]["mod_stock_001"] = 100; | ||||
|                     chances[weaponType]["mod_stock_akms"] = 100; | ||||
|                     chances[weaponType]["mod_stock_axis"] = 100; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private setForceDustCover(): void | ||||
|     { | ||||
|         for (const tierObject in this.tierInformation.tiers) | ||||
|         { | ||||
|             const tierNumber = this.tierInformation.tiers[tierObject].tier | ||||
|             const tierJson = this.apbsEquipmentGetter.getTierChancesJson(tierNumber); | ||||
| 
 | ||||
|             for (const botType in this.tierInformation.tier1chances) | ||||
|             { | ||||
|                 const chances = tierJson[botType].chances | ||||
|                 for (const weaponType in chances) | ||||
|                 { | ||||
|                     chances[weaponType]["mod_reciever"] = 100; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private setForceScopes(): void | ||||
|     { | ||||
|         for (const tierObject in this.tierInformation.tiers) | ||||
|         { | ||||
|             const tierNumber = this.tierInformation.tiers[tierObject].tier | ||||
|             const tierJson = this.apbsEquipmentGetter.getTierChancesJson(tierNumber); | ||||
| 
 | ||||
|             for (const botType in this.tierInformation.tier1chances) | ||||
|             { | ||||
|                 const chances = tierJson[botType].chances | ||||
|                 for (const weaponType in chances) | ||||
|                 { | ||||
|                     chances[weaponType]["mod_scope"] = 100; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private setPlateChances()  | ||||
|     { | ||||
|         for (const tierObject in this.tierInformation.tiers) | ||||
|         { | ||||
|             const tierNumber = this.tierInformation.tiers[tierObject].tier | ||||
|             const tierJson = this.apbsEquipmentGetter.getTierChancesJson(tierNumber); | ||||
| 
 | ||||
|             for (const botType in this.tierInformation.tier1chances) | ||||
|             { | ||||
|                 if (botType == "pmcUSEC" || botType == "pmcBEAR") | ||||
|                 { | ||||
|                     tierJson[botType].chances.equipmentMods["back_plate"] = tierJson[botType].chances.equipmentMods["front_plate"] = ModConfig.config.pmcMainPlateChance[tierObject]; | ||||
|                     tierJson[botType].chances.equipmentMods["left_side_plate"] = tierJson[botType].chances.equipmentMods["right_side_plate"] = ModConfig.config.pmcSidePlateChance[tierObject]; | ||||
|                 } | ||||
|                 if (botType == "followerbirdeye" || botType == "followerbigpipe" || botType.includes("boss") || botType.includes("sectant")) | ||||
|                 { | ||||
|                     tierJson[botType].chances.equipmentMods["back_plate"] = tierJson[botType].chances.equipmentMods["front_plate"] = ModConfig.config.bossMainPlateChance[tierObject]; | ||||
|                     tierJson[botType].chances.equipmentMods["left_side_plate"] = tierJson[botType].chances.equipmentMods["right_side_plate"] = ModConfig.config.bossSidePlateChance[tierObject]; | ||||
|                 } | ||||
|                 if (botType == "scav") | ||||
|                 { | ||||
|                     tierJson[botType].chances.equipmentMods["back_plate"] = tierJson[botType].chances.equipmentMods["front_plate"] = ModConfig.config.scavMainPlateChance[tierObject]; | ||||
|                     tierJson[botType].chances.equipmentMods["left_side_plate"] = tierJson[botType].chances.equipmentMods["right_side_plate"] = ModConfig.config.scavSidePlateChance[tierObject]; | ||||
|                 } | ||||
|                 if (botType == "exusec" || botType == "pmcbot") | ||||
|                 { | ||||
|                     tierJson[botType].chances.equipmentMods["back_plate"] = tierJson[botType].chances.equipmentMods["front_plate"] = ModConfig.config.raiderMainPlateChance[tierObject]; | ||||
|                     tierJson[botType].chances.equipmentMods["left_side_plate"] = tierJson[botType].chances.equipmentMods["right_side_plate"] = ModConfig.config.raiderSidePlateChance[tierObject]; | ||||
|                 } | ||||
|                 if (botType == "default") | ||||
|                 { | ||||
|                     tierJson[botType].chances.equipmentMods["back_plate"] = tierJson[botType].chances.equipmentMods["front_plate"] = ModConfig.config.guardMainPlateChance[tierObject]; | ||||
|                     tierJson[botType].chances.equipmentMods["left_side_plate"] = tierJson[botType].chances.equipmentMods["right_side_plate"] = ModConfig.config.guardSidePlateChance[tierObject]; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private setWeaponModLimits(): void | ||||
|     { | ||||
|         const botConfigEquipment = this.botConfig.equipment | ||||
|         for (const botType in botConfigEquipment) | ||||
|         { | ||||
|             if (botConfigEquipment[botType].weaponModLimits == undefined)  | ||||
|             { | ||||
|                 botConfigEquipment[botType].weaponModLimits =  | ||||
|                 { | ||||
|                     "scopeLimit": 2, | ||||
|                     "lightLaserLimit": 1 | ||||
|                 } | ||||
|             } | ||||
|             botConfigEquipment[botType].weaponModLimits.scopeLimit = ModConfig.config.scopeLimit; | ||||
|             botConfigEquipment[botType].weaponModLimits.lightLaserLimit = ModConfig.config.tacticalLimit; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private setLootItemResourceRandomization(): void | ||||
|     { | ||||
|         // Chance it is 100% full
 | ||||
|         let scavFoodMaxChance = 100; | ||||
|         let scavMedMaxChance = 100; | ||||
|         let pmcFoodMaxChance = 100; | ||||
|         let pmcMedMaxChance = 100; | ||||
| 
 | ||||
|         // Minimum resource amount
 | ||||
|         let scavFoodResourcePercent = 60; | ||||
|         let scavMedResourcePercent = 60; | ||||
|         let pmcFoodResourcePercent = 60; | ||||
|         let pmcMedResourcePercent = 60; | ||||
| 
 | ||||
|         // Check if enabled, if so - change to values in config
 | ||||
|         if (ModConfig.config.enableConsumableResourceRandomization) | ||||
|         { | ||||
|             scavFoodMaxChance = ModConfig.config.scavFoodRates[0]; | ||||
|             scavMedMaxChance = ModConfig.config.scavMedRates[0]; | ||||
|             pmcFoodMaxChance = ModConfig.config.pmcFoodRates[0]; | ||||
|             pmcMedMaxChance = ModConfig.config.pmcMedRates[0]; | ||||
| 
 | ||||
|             scavFoodResourcePercent = ModConfig.config.scavFoodRates[1]; | ||||
|             scavMedResourcePercent = ModConfig.config.scavMedRates[1]; | ||||
|             pmcFoodResourcePercent = ModConfig.config.pmcFoodRates[1]; | ||||
|             pmcMedResourcePercent = ModConfig.config.pmcMedRates[1]; | ||||
|         } | ||||
| 
 | ||||
|         // Set values in botConfig
 | ||||
|         this.botConfig.lootItemResourceRandomization.assault = {"food": { "chanceMaxResourcePercent": scavFoodMaxChance, "resourcePercent": scavFoodResourcePercent }, "meds": { "chanceMaxResourcePercent": scavMedMaxChance, "resourcePercent": scavMedResourcePercent } } | ||||
|         this.botConfig.lootItemResourceRandomization.marksman = {"food": { "chanceMaxResourcePercent": scavFoodMaxChance, "resourcePercent": scavFoodResourcePercent }, "meds": { "chanceMaxResourcePercent": scavMedMaxChance, "resourcePercent": scavMedResourcePercent } } | ||||
|         this.botConfig.lootItemResourceRandomization.pmcusec = {"food": { "chanceMaxResourcePercent": pmcFoodMaxChance, "resourcePercent": pmcFoodResourcePercent }, "meds": { "chanceMaxResourcePercent": pmcMedMaxChance, "resourcePercent": pmcMedResourcePercent } } | ||||
|         this.botConfig.lootItemResourceRandomization.pmcbear = {"food": { "chanceMaxResourcePercent": pmcFoodMaxChance, "resourcePercent": pmcFoodResourcePercent }, "meds": { "chanceMaxResourcePercent": pmcMedMaxChance, "resourcePercent": pmcMedResourcePercent } } | ||||
|         this.botConfig.lootItemResourceRandomization.pmc = {"food": { "chanceMaxResourcePercent": pmcFoodMaxChance, "resourcePercent": pmcFoodResourcePercent }, "meds": { "chanceMaxResourcePercent": pmcMedMaxChance, "resourcePercent": pmcMedResourcePercent } } | ||||
|     } | ||||
| 
 | ||||
|     private setPMCItemLimits(): void | ||||
|     { | ||||
|         // Clear PMC item limits
 | ||||
|         this.botConfig.itemSpawnLimits.pmc = {} | ||||
| 
 | ||||
|         // Go through custom limits and add them
 | ||||
|         for (const [item, count] of Object.entries(this.pmcLimitedCategories)) | ||||
|         { | ||||
|             this.botConfig.itemSpawnLimits.pmc[item] = count; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private setPMCLoot(): void | ||||
|     { | ||||
|         const allBots = this.database.getTables().bots.types; | ||||
| 
 | ||||
|         this.pmcConfig.looseWeaponInBackpackLootMinMax.min = 0; | ||||
|         this.pmcConfig.looseWeaponInBackpackLootMinMax.max = 0; | ||||
|         this.botConfig.equipment.pmc.randomisation = []; | ||||
| 
 | ||||
|         if (ModConfig.config.pmcLoot) | ||||
|         { | ||||
|             if (ModConfig.config.pmcLootBlacklistItems.length > 0) | ||||
|             { | ||||
|                 for (const item in ModConfig.config.pmcLootBlacklistItems) | ||||
|                 { | ||||
|                     this.pmcConfig.backpackLoot.blacklist.push(item); | ||||
|                     this.pmcConfig.vestLoot.blacklist.push(item); | ||||
|                     this.pmcConfig.pocketLoot.blacklist.push(item); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         if (!ModConfig.config.pmcLoot) | ||||
|         {             | ||||
|             this.botConfig.disableLootOnBotTypes.push("pmcusec", "pmcbear") | ||||
|         } | ||||
|          | ||||
|         for (const botType in allBots) | ||||
|         { | ||||
|             if (botType == "pmcbear" || botType == "pmcusec") | ||||
|             { | ||||
|                 allBots[botType].inventory.items.Backpack = {}; | ||||
|                 allBots[botType].inventory.items.Pockets = {}; | ||||
|                 allBots[botType].inventory.items.TacticalVest = {}; | ||||
|                 allBots[botType].inventory.items.SpecialLoot = {}; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private setPMCScopeWhitelist(): void | ||||
|     { | ||||
|         this.botConfig.equipment.pmc.weaponSightWhitelist = { | ||||
|             "5447b5fc4bdc2d87278b4567": [ | ||||
|                 "55818ad54bdc2ddc698b4569", | ||||
|                 "55818acf4bdc2dde698b456b", | ||||
|                 "55818ae44bdc2dde698b456c", | ||||
|                 "55818ac54bdc2d5b648b456e", | ||||
|                 "55818add4bdc2d5b648b456f", | ||||
|                 "55818aeb4bdc2ddc698b456a" | ||||
|             ], | ||||
|             "5447b5f14bdc2d61278b4567": [ | ||||
|                 "55818ad54bdc2ddc698b4569", | ||||
|                 "55818acf4bdc2dde698b456b", | ||||
|                 "55818ae44bdc2dde698b456c", | ||||
|                 "55818ac54bdc2d5b648b456e", | ||||
|                 "55818add4bdc2d5b648b456f", | ||||
|                 "55818aeb4bdc2ddc698b456a" | ||||
|             ], | ||||
|             "5447bedf4bdc2d87278b4568": [ | ||||
|                 "55818ad54bdc2ddc698b4569", | ||||
|                 "55818add4bdc2d5b648b456f", | ||||
|                 "55818ac54bdc2d5b648b456e", | ||||
|                 "55818aeb4bdc2ddc698b456a" | ||||
|             ], | ||||
|             "5447bed64bdc2d97278b4568": [ | ||||
|                 "55818ad54bdc2ddc698b4569", | ||||
|                 "55818acf4bdc2dde698b456b", | ||||
|                 "55818ac54bdc2d5b648b456e", | ||||
|                 "55818add4bdc2d5b648b456f", | ||||
|                 "55818aeb4bdc2ddc698b456a" | ||||
|             ], | ||||
|             "5447b6194bdc2d67278b4567": [ | ||||
|                 "55818ad54bdc2ddc698b4569", | ||||
|                 "55818ae44bdc2dde698b456c", | ||||
|                 "55818ac54bdc2d5b648b456e", | ||||
|                 "55818aeb4bdc2ddc698b456a", | ||||
|                 "55818add4bdc2d5b648b456f" | ||||
|             ], | ||||
|             "5447b5cf4bdc2d65278b4567": [ | ||||
|                 "55818ad54bdc2ddc698b4569", | ||||
|                 "55818acf4bdc2dde698b456b", | ||||
|                 "55818ac54bdc2d5b648b456e" | ||||
|             ], | ||||
|             "617f1ef5e8b54b0998387733": [ | ||||
|                 "55818ad54bdc2ddc698b4569", | ||||
|                 "55818acf4bdc2dde698b456b", | ||||
|                 "55818ac54bdc2d5b648b456e" | ||||
|             ], | ||||
|             "5447b6094bdc2dc3278b4567": [ | ||||
|                 "55818ad54bdc2ddc698b4569", | ||||
|                 "55818acf4bdc2dde698b456b", | ||||
|                 "55818ac54bdc2d5b648b456e" | ||||
|             ], | ||||
|             "5447b5e04bdc2d62278b4567": [ | ||||
|                 "55818ad54bdc2ddc698b4569", | ||||
|                 "55818acf4bdc2dde698b456b", | ||||
|                 "55818ac54bdc2d5b648b456e" | ||||
|             ], | ||||
|             "5447b6254bdc2dc3278b4568": [ | ||||
|                 "55818ae44bdc2dde698b456c", | ||||
|                 "55818ac54bdc2d5b648b456e", | ||||
|                 "55818aeb4bdc2ddc698b456a", | ||||
|                 "55818add4bdc2d5b648b456f" | ||||
|             ] | ||||
|         }; | ||||
|     } | ||||
| 
 | ||||
|     private pushScavKeys(): void | ||||
|     { | ||||
|         const scavBackpack = this.tables.bots.types.assault.inventory.items.Backpack | ||||
|         const items = Object.values(this.tables.templates.items); | ||||
|         const baseClass = this.getKeyConfig(); | ||||
|         const allKeys = items.filter(x => this.itemHelper.isOfBaseclass(x._id, baseClass)); | ||||
| 
 | ||||
|         let count = 0; | ||||
|         for (const key in allKeys) | ||||
|         { | ||||
|             if (scavBackpack[allKeys[key]._id] == undefined) | ||||
|             { | ||||
|                 scavBackpack[allKeys[key]._id] = 1; | ||||
|                 count++ | ||||
|             } | ||||
|         } | ||||
|         this.apbsLogger.log(Logging.DEBUG, `Added ${count} keys to Scav Backpacks (Key Class Added: ${baseClass})`) | ||||
|     } | ||||
| 
 | ||||
|     private getKeyConfig(): BaseClasses | ||||
|     { | ||||
|         if (ModConfig.config.addAllKeysToScavs) return BaseClasses.KEY | ||||
|         if (ModConfig.config.addOnlyMechanicalKeysToScavs) return BaseClasses.KEY_MECHANICAL | ||||
|         if (ModConfig.config.addOnlyKeyCardsToScavs) return BaseClasses.KEYCARD | ||||
|     } | ||||
| 
 | ||||
|     private removeScavLoot(): void | ||||
|     { | ||||
|         this.botConfig.disableLootOnBotTypes.push("assault", "marksman", "cursedassault", "assaultgroup", "crazyassaultevent"); | ||||
|     } | ||||
| 
 | ||||
|     private setIdenticalScavWeights(): void | ||||
|     { | ||||
|         for (const tierObject in this.tierInformation.tiers) | ||||
|         { | ||||
|             const tierNumber = this.tierInformation.tiers[tierObject].tier | ||||
|             const tierJson = this.apbsEquipmentGetter.getTierJson(tierNumber, true); | ||||
|             const scav = tierJson.scav.equipment | ||||
|             for (const slot in scav) | ||||
|             { | ||||
|                 if (slot == "SecondPrimaryWeapon" || slot == "ArmBand") continue; | ||||
|                 if (slot == "FirstPrimaryWeapon") | ||||
|                 { | ||||
|                     for (const subSlot in scav[slot]) | ||||
|                     { | ||||
|                         for (const item in scav[slot][subSlot]) | ||||
|                         { | ||||
|                             scav[slot][subSlot][item] = 1; | ||||
|                         } | ||||
|                     } | ||||
|                     continue; | ||||
|                 } | ||||
|                 for (const item in scav[slot]) | ||||
|                 { | ||||
|                     scav[slot][item] = 1; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private removeThermalGoggles(removeSome: boolean): void | ||||
|     { | ||||
|         for (const tierObject in this.tierInformation.tiers) | ||||
|         { | ||||
|             const tierNumber = this.tierInformation.tiers[tierObject].tier | ||||
|             const tierJson = this.apbsEquipmentGetter.getTierModsJson(tierNumber, true); | ||||
|             const tatmMods = tierJson["5a16b8a9fcdbcb00165aa6ca"].mod_nvg; | ||||
|             const index = tatmMods.indexOf("5c11046cd174af02a012e42b"); | ||||
| 
 | ||||
|             if (removeSome && tierNumber >= ModConfig.config.startTier) continue; | ||||
|             if (index > -1) | ||||
|             { | ||||
|                 tatmMods.splice(index, 1) | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private setPMCGameVersionWeights(): void | ||||
|     { | ||||
|         this.pmcConfig.gameVersionWeight.standard = ModConfig.config.standard; | ||||
|         this.pmcConfig.gameVersionWeight.left_behind = ModConfig.config.left_behind; | ||||
|         this.pmcConfig.gameVersionWeight.prepare_for_escape = ModConfig.config.prepare_for_escape; | ||||
|         this.pmcConfig.gameVersionWeight.edge_of_darkness = ModConfig.config.edge_of_darkness; | ||||
|         this.pmcConfig.gameVersionWeight.unheard_edition = ModConfig.config.unheard_edition; | ||||
|     } | ||||
| 
 | ||||
|     private setLevelDeltas(): void | ||||
|     { | ||||
|         this.tierInformation.tiers[0].botMinLevelVariance = ModConfig.config.tier1LevelDelta[0] | ||||
|         this.tierInformation.tiers[0].botMaxLevelVariance = ModConfig.config.tier1LevelDelta[1] | ||||
| 
 | ||||
|         this.tierInformation.tiers[1].botMinLevelVariance = ModConfig.config.tier2LevelDelta[0] | ||||
|         this.tierInformation.tiers[1].botMaxLevelVariance = ModConfig.config.tier2LevelDelta[1] | ||||
| 
 | ||||
|         this.tierInformation.tiers[2].botMinLevelVariance = ModConfig.config.tier3LevelDelta[0] | ||||
|         this.tierInformation.tiers[2].botMaxLevelVariance = ModConfig.config.tier3LevelDelta[1] | ||||
| 
 | ||||
|         this.tierInformation.tiers[3].botMinLevelVariance = ModConfig.config.tier4LevelDelta[0] | ||||
|         this.tierInformation.tiers[3].botMaxLevelVariance = ModConfig.config.tier4LevelDelta[1] | ||||
| 
 | ||||
|         this.tierInformation.tiers[4].botMinLevelVariance = ModConfig.config.tier5LevelDelta[0] | ||||
|         this.tierInformation.tiers[4].botMaxLevelVariance = ModConfig.config.tier5LevelDelta[1] | ||||
| 
 | ||||
|         this.tierInformation.tiers[5].botMinLevelVariance = ModConfig.config.tier6LevelDelta[0] | ||||
|         this.tierInformation.tiers[5].botMaxLevelVariance = ModConfig.config.tier6LevelDelta[1] | ||||
| 
 | ||||
|         this.tierInformation.tiers[6].botMinLevelVariance = ModConfig.config.tier7LevelDelta[0] | ||||
|         this.tierInformation.tiers[6].botMaxLevelVariance = ModConfig.config.tier7LevelDelta[1] | ||||
|     } | ||||
| 
 | ||||
|     private setScavLevelDeltas(): void | ||||
|     { | ||||
|         this.tierInformation.tiers[0].scavMinLevelVariance = ModConfig.config.tier1ScavLevelDelta[0] | ||||
|         this.tierInformation.tiers[0].scavMaxLevelVariance = ModConfig.config.tier1ScavLevelDelta[1] | ||||
| 
 | ||||
|         this.tierInformation.tiers[1].scavMinLevelVariance = ModConfig.config.tier2ScavLevelDelta[0] | ||||
|         this.tierInformation.tiers[1].scavMaxLevelVariance = ModConfig.config.tier2ScavLevelDelta[1] | ||||
| 
 | ||||
|         this.tierInformation.tiers[2].scavMinLevelVariance = ModConfig.config.tier3ScavLevelDelta[0] | ||||
|         this.tierInformation.tiers[2].scavMaxLevelVariance = ModConfig.config.tier3ScavLevelDelta[1] | ||||
| 
 | ||||
|         this.tierInformation.tiers[3].scavMinLevelVariance = ModConfig.config.tier4ScavLevelDelta[0] | ||||
|         this.tierInformation.tiers[3].scavMaxLevelVariance = ModConfig.config.tier4ScavLevelDelta[1] | ||||
| 
 | ||||
|         this.tierInformation.tiers[4].scavMinLevelVariance = ModConfig.config.tier5ScavLevelDelta[0] | ||||
|         this.tierInformation.tiers[4].scavMaxLevelVariance = ModConfig.config.tier5ScavLevelDelta[1] | ||||
| 
 | ||||
|         this.tierInformation.tiers[5].scavMinLevelVariance = ModConfig.config.tier6ScavLevelDelta[0] | ||||
|         this.tierInformation.tiers[5].scavMaxLevelVariance = ModConfig.config.tier6ScavLevelDelta[1] | ||||
| 
 | ||||
|         this.tierInformation.tiers[6].scavMinLevelVariance = ModConfig.config.tier7ScavLevelDelta[0] | ||||
|         this.tierInformation.tiers[6].scavMaxLevelVariance = ModConfig.config.tier7ScavLevelDelta[1] | ||||
|     } | ||||
| 
 | ||||
|     private setPMCSlotIDsToMakeRequired(): void | ||||
|     { | ||||
|         this.botConfig.equipment.pmc.weaponSlotIdsToMakeRequired = [ "mod_reciever", "mod_stock" ] | ||||
|     }     | ||||
| 
 | ||||
|     private setMuzzleChances(): void | ||||
|     { | ||||
|         for (const tierObject in this.tierInformation.tiers) | ||||
|         { | ||||
|             const tierNumber = this.tierInformation.tiers[tierObject].tier | ||||
|             const tierJson = this.apbsEquipmentGetter.getTierChancesJson(tierNumber); | ||||
|             const usec = tierJson.pmcUSEC.chances | ||||
|             const bear = tierJson.pmcBEAR.chances | ||||
|             for (const type in usec) | ||||
|             { | ||||
|                 if (type == "equipment" || type == "equipmentMods" || type == "generation") continue; | ||||
| 
 | ||||
|                 const arrayPosition = tierNumber - 1; | ||||
| 
 | ||||
|                 usec[type].mod_muzzle = ModConfig.config.muzzleChance[arrayPosition] | ||||
|                 usec[type].mod_muzzle_000 = ModConfig.config.muzzleChance[arrayPosition] | ||||
|                 usec[type].mod_muzzle_000 = ModConfig.config.muzzleChance[arrayPosition] | ||||
| 
 | ||||
|                 bear[type].mod_muzzle = ModConfig.config.muzzleChance[arrayPosition] | ||||
|                 bear[type].mod_muzzle_000 = ModConfig.config.muzzleChance[arrayPosition] | ||||
|                 bear[type].mod_muzzle_000 = ModConfig.config.muzzleChance[arrayPosition] | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,752 @@ | |||
| import { inject, injectable } from "tsyringe"; | ||||
| 
 | ||||
| import { BotGeneratorHelper } from "@spt/helpers/BotGeneratorHelper"; | ||||
| import { BotHelper } from "@spt/helpers/BotHelper"; | ||||
| import { BotWeaponGeneratorHelper } from "@spt/helpers/BotWeaponGeneratorHelper"; | ||||
| import { ItemHelper } from "@spt/helpers/ItemHelper"; | ||||
| import { PresetHelper } from "@spt/helpers/PresetHelper"; | ||||
| import { ProbabilityHelper } from "@spt/helpers/ProbabilityHelper"; | ||||
| import { ProfileHelper } from "@spt/helpers/ProfileHelper"; | ||||
| import { WeightedRandomHelper } from "@spt/helpers/WeightedRandomHelper"; | ||||
| import { IItem } from "@spt/models/eft/common/tables/IItem"; | ||||
| import { ITemplateItem } from "@spt/models/eft/common/tables/ITemplateItem"; | ||||
| import { ModSpawn } from "@spt/models/enums/ModSpawn"; | ||||
| import { IFilterPlateModsForSlotByLevelResult, Result } from "@spt/models/spt/bots/IFilterPlateModsForSlotByLevelResult"; | ||||
| import { IGenerateEquipmentProperties } from "@spt/models/spt/bots/IGenerateEquipmentProperties"; | ||||
| import { ExhaustableArray } from "@spt/models/spt/server/ExhaustableArray"; | ||||
| import { ILogger } from "@spt/models/spt/utils/ILogger"; | ||||
| import { ConfigServer } from "@spt/servers/ConfigServer"; | ||||
| import { BotEquipmentFilterService } from "@spt/services/BotEquipmentFilterService"; | ||||
| import { BotEquipmentModPoolService } from "@spt/services/BotEquipmentModPoolService"; | ||||
| import { BotWeaponModLimitService } from "@spt/services/BotWeaponModLimitService"; | ||||
| import { DatabaseService } from "@spt/services/DatabaseService"; | ||||
| import { ItemFilterService } from "@spt/services/ItemFilterService"; | ||||
| import { LocalisationService } from "@spt/services/LocalisationService"; | ||||
| import { HashUtil } from "@spt/utils/HashUtil"; | ||||
| import { RandomUtil } from "@spt/utils/RandomUtil"; | ||||
| import { ICloner } from "@spt/utils/cloners/ICloner"; | ||||
| import { Money } from "@spt/models/enums/Money"; | ||||
| import { IGenerateWeaponRequest } from "@spt/models/spt/bots/IGenerateWeaponRequest"; | ||||
| import { IModToSpawnRequest } from "@spt/models/spt/bots/IModToSpawnRequest"; | ||||
| import { BaseClasses } from "@spt/models/enums/BaseClasses"; | ||||
| import { IEquipmentFilterDetails } from "@spt/models/spt/config/IBotConfig"; | ||||
| import { BotEquipmentModGenerator } from "@spt/generators/BotEquipmentModGenerator"; | ||||
| import { IChooseRandomCompatibleModResult } from "@spt/models/spt/bots/IChooseRandomCompatibleModResult"; | ||||
| 
 | ||||
| import { APBSEquipmentGetter } from "../Utils/APBSEquipmentGetter"; | ||||
| import { APBSTierGetter } from "../Utils/APBSTierGetter"; | ||||
| import { ModConfig } from "../Globals/ModConfig"; | ||||
| import { RaidInformation } from "../Globals/RaidInformation"; | ||||
| import { ModInformation } from "../Globals/ModInformation"; | ||||
| import { APBSTester } from "../Utils/APBSTester"; | ||||
| import { vanillaButtpads } from "../Globals/VanillaItemLists"; | ||||
| import { APBSLogger } from "../Utils/APBSLogger"; | ||||
| import { RealismHelper } from "../Helpers/RealismHelper"; | ||||
| 
 | ||||
| /** Handle profile related client events */ | ||||
| @injectable() | ||||
| export class APBSBotEquipmentModGenerator extends BotEquipmentModGenerator | ||||
| { | ||||
| 
 | ||||
|     constructor( | ||||
|         @inject("PrimaryLogger") protected logger: ILogger, | ||||
|         @inject("HashUtil") protected hashUtil: HashUtil, | ||||
|         @inject("RandomUtil") protected randomUtil: RandomUtil, | ||||
|         @inject("ProbabilityHelper") protected probabilityHelper: ProbabilityHelper, | ||||
|         @inject("DatabaseService") protected databaseService: DatabaseService, | ||||
|         @inject("ItemHelper") protected itemHelper: ItemHelper, | ||||
|         @inject("BotEquipmentFilterService") protected botEquipmentFilterService: BotEquipmentFilterService, | ||||
|         @inject("ItemFilterService") protected itemFilterService: ItemFilterService, | ||||
|         @inject("ProfileHelper") protected profileHelper: ProfileHelper, | ||||
|         @inject("BotWeaponModLimitService") protected botWeaponModLimitService: BotWeaponModLimitService, | ||||
|         @inject("BotHelper") protected botHelper: BotHelper, | ||||
|         @inject("BotGeneratorHelper") protected botGeneratorHelper: BotGeneratorHelper, | ||||
|         @inject("BotWeaponGeneratorHelper") protected botWeaponGeneratorHelper: BotWeaponGeneratorHelper, | ||||
|         @inject("WeightedRandomHelper") protected weightedRandomHelper: WeightedRandomHelper, | ||||
|         @inject("PresetHelper") protected presetHelper: PresetHelper, | ||||
|         @inject("LocalisationService") protected localisationService: LocalisationService, | ||||
|         @inject("BotEquipmentModPoolService") protected botEquipmentModPoolService: BotEquipmentModPoolService, | ||||
|         @inject("ConfigServer") protected configServer: ConfigServer, | ||||
|         @inject("PrimaryCloner") protected cloner: ICloner, | ||||
|         @inject("APBSEquipmentGetter") protected apbsEquipmentGetter: APBSEquipmentGetter, | ||||
|         @inject("APBSTierGetter") protected apbsTierGetter: APBSTierGetter, | ||||
|         @inject("RaidInformation") protected raidInformation: RaidInformation, | ||||
|         @inject("ModInformation") protected modInformation: ModInformation, | ||||
|         @inject("APBSTester") protected apbsTester: APBSTester, | ||||
|         @inject("APBSLogger") protected apbsLogger: APBSLogger, | ||||
|         @inject("RealismHelper") protected realismHelper: RealismHelper | ||||
|     ) | ||||
|     { | ||||
|         super(logger,  | ||||
|             hashUtil,  | ||||
|             randomUtil,  | ||||
|             probabilityHelper,  | ||||
|             databaseService,  | ||||
|             itemHelper,  | ||||
|             botEquipmentFilterService,  | ||||
|             itemFilterService,  | ||||
|             profileHelper,  | ||||
|             botWeaponModLimitService,  | ||||
|             botHelper,  | ||||
|             botGeneratorHelper,  | ||||
|             botWeaponGeneratorHelper,  | ||||
|             weightedRandomHelper,  | ||||
|             presetHelper,  | ||||
|             localisationService,  | ||||
|             botEquipmentModPoolService,  | ||||
|             configServer,  | ||||
|             cloner) | ||||
|     } | ||||
| 
 | ||||
|     public override generateModsForEquipment(equipment: IItem[], parentId: string, parentTemplate: ITemplateItem, settings: IGenerateEquipmentProperties, specificBlacklist: IEquipmentFilterDetails, shouldForceSpawn: boolean): IItem[] | ||||
|     { | ||||
|         let forceSpawn = shouldForceSpawn; | ||||
| 
 | ||||
|         const botRole = settings.botData.role; | ||||
|         const tier = this.apbsTierGetter.getTierByLevel(settings.botData.level); | ||||
|         const tieredModPool = this.apbsEquipmentGetter.getModsByBotRole(botRole, tier) | ||||
|          | ||||
|         let spawnChances = this.apbsEquipmentGetter.getSpawnChancesByBotRole(botRole, tier); | ||||
|         let compatibleModsPool = tieredModPool[parentTemplate._id] | ||||
|         let actualModPool = tieredModPool; | ||||
| 
 | ||||
|         if (!this.raidInformation.isBotEnabled(botRole)) | ||||
|         { | ||||
|             spawnChances = settings.spawnChances; | ||||
|             compatibleModsPool = settings.modPool[parentTemplate._id]; | ||||
|             actualModPool = settings.modPool; | ||||
|         } | ||||
| 
 | ||||
|         if (!compatibleModsPool) | ||||
|         { | ||||
|             this.logger.warning( | ||||
|                 `bot: ${botRole} lacks a mod slot pool for item: ${parentTemplate._id} ${parentTemplate._name}`); | ||||
|         } | ||||
| 
 | ||||
|         // Iterate over mod pool and choose mods to add to item
 | ||||
|         for (const modSlotName in compatibleModsPool) | ||||
|         { | ||||
|             if (modSlotName === "mod_equipment_000" && this.raidInformation.nightTime) continue; | ||||
| 
 | ||||
|             if (modSlotName === "mod_equipment" && this.realismHelper.gasMasks.includes(parentTemplate._id) && this.realismHelper.realismDetected == true) | ||||
|             { | ||||
|                 forceSpawn = true; | ||||
|             } | ||||
| 
 | ||||
|             const itemSlotTemplate = this.getModItemSlotFromDb(modSlotName, parentTemplate); | ||||
|             if (!itemSlotTemplate) | ||||
|             { | ||||
|                 this.logger.error( | ||||
|                     this.localisationService.getText("bot-mod_slot_missing_from_item", { | ||||
|                         modSlot: modSlotName, | ||||
|                         parentId: parentTemplate._id, | ||||
|                         parentName: parentTemplate._name, | ||||
|                         botRole: settings.botData.role | ||||
|                     }) | ||||
|                 ); | ||||
|                 continue; | ||||
|             } | ||||
|             const modSpawnResult = this.shouldModBeSpawned( | ||||
|                 itemSlotTemplate, | ||||
|                 modSlotName.toLowerCase(), | ||||
|                 spawnChances.equipmentMods, | ||||
|                 settings.botEquipmentConfig | ||||
|             ); | ||||
|             if (modSpawnResult === ModSpawn.SKIP && !forceSpawn) | ||||
|             { | ||||
|                 continue; | ||||
|             } | ||||
| 
 | ||||
|             // Ensure submods for nvgs all spawn together if it's night
 | ||||
|             if (modSlotName === "mod_nvg") | ||||
|             { | ||||
|                 if (this.raidInformation.nightTime)  | ||||
|                 { | ||||
|                     forceSpawn = true; | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     continue; | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             let modPoolToChooseFrom = compatibleModsPool[modSlotName]; | ||||
|             if ( | ||||
|                 settings.botEquipmentConfig.filterPlatesByLevel | ||||
|                 && this.itemHelper.isRemovablePlateSlot(modSlotName.toLowerCase()) | ||||
|             ) | ||||
|             { | ||||
|                 const outcome = this.filterPlateModsForSlotByLevel( | ||||
|                     settings, | ||||
|                     modSlotName.toLowerCase(), | ||||
|                     compatibleModsPool[modSlotName], | ||||
|                     parentTemplate | ||||
|                 ); | ||||
|                 if ([Result.UNKNOWN_FAILURE, Result.NO_DEFAULT_FILTER].includes(outcome.result)) | ||||
|                 { | ||||
|                     this.logger.debug( | ||||
|                         `Plate slot: ${modSlotName} selection for armor: ${parentTemplate._id} failed: ${ | ||||
|                             Result[outcome.result] | ||||
|                         }, skipping` | ||||
|                     ); | ||||
| 
 | ||||
|                     continue; | ||||
|                 } | ||||
| 
 | ||||
|                 if ([Result.LACKS_PLATE_WEIGHTS].includes(outcome.result)) | ||||
|                 { | ||||
|                     this.logger.warning( | ||||
|                         `Plate slot: ${modSlotName} lacks weights for armor: ${parentTemplate._id}, unable to adjust plate choice, using existing data` | ||||
|                     ); | ||||
|                 } | ||||
| 
 | ||||
|                 modPoolToChooseFrom = outcome.plateModTpls; | ||||
|             } | ||||
| 
 | ||||
|             // Find random mod and check its compatible
 | ||||
|             let modTpl: string | undefined; | ||||
|             let found = false; | ||||
|             const exhaustableModPool = new ExhaustableArray<string>(modPoolToChooseFrom, this.randomUtil, this.cloner); | ||||
|             while (exhaustableModPool.hasValues()) | ||||
|             { | ||||
|                 modTpl = exhaustableModPool.getRandomValue(); | ||||
|                 if (modTpl | ||||
|                     && !this.botGeneratorHelper.isItemIncompatibleWithCurrentItems(equipment, modTpl, modSlotName) | ||||
|                         .incompatible | ||||
|                 ) | ||||
|                 { | ||||
|                     found = true; | ||||
|                     break; | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             // Compatible item not found but slot REQUIRES item, get random item from db
 | ||||
|             if (!found && itemSlotTemplate._required) | ||||
|             { | ||||
|                 modTpl = this.getRandomModTplFromItemDb(modTpl, itemSlotTemplate, modSlotName, equipment); | ||||
|                 found = !!modTpl; | ||||
|             } | ||||
| 
 | ||||
|             // Compatible item not found + not required
 | ||||
|             if (!(found || itemSlotTemplate._required)) | ||||
|             { | ||||
|                 // Don't add item
 | ||||
|                 continue; | ||||
|             } | ||||
| 
 | ||||
|             const modTemplate = this.itemHelper.getItem(modTpl); | ||||
|             if (!this.isModValidForSlot(modTemplate, itemSlotTemplate, modSlotName, parentTemplate, botRole)) | ||||
|             { | ||||
|                 continue; | ||||
|             } | ||||
| 
 | ||||
|             // Generate new id to ensure all items are unique on bot
 | ||||
|             const modId = this.hashUtil.generate(); | ||||
|             equipment.push(this.createModItem(modId, modTpl, parentId, modSlotName, modTemplate[1], botRole)); | ||||
| 
 | ||||
|             // Does the item being added have possible child mods?
 | ||||
|             if (Object.keys(actualModPool).includes(modTpl)) | ||||
|             { | ||||
|                 // Call self recursively with item being checkced item we just added to bot
 | ||||
|                 this.generateModsForEquipment( | ||||
|                     equipment, | ||||
|                     modId, | ||||
|                     modTemplate[1], | ||||
|                     settings, | ||||
|                     specificBlacklist, | ||||
|                     forceSpawn | ||||
|                 ); | ||||
|             } | ||||
|         } | ||||
|          | ||||
|         // This is for testing...
 | ||||
|         if (this.modInformation.testMode && this.modInformation.testBotRole.includes(botRole.toLowerCase())) | ||||
|         { | ||||
|             const tables = this.databaseService.getTables(); | ||||
|             const assortEquipment = this.cloner.clone(equipment); | ||||
|             for (const item in assortEquipment) | ||||
|             { | ||||
|                 const oldID = assortEquipment[item]._id | ||||
|                 const newID = this.hashUtil.generate(); | ||||
|                 assortEquipment[item]._id = newID; | ||||
|                  | ||||
|                 // Loop array again to fix parentID
 | ||||
|                 for (const i in assortEquipment) | ||||
|                 { | ||||
|                     if (assortEquipment[i].parentId == oldID)  | ||||
|                     { | ||||
|                         assortEquipment[i].parentId = newID | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|             this.apbsTester.createComplexAssortItem(assortEquipment) | ||||
|                 .addUnlimitedStackCount() | ||||
|                 .addMoneyCost(Money.ROUBLES, 20000) | ||||
|                 .addBuyRestriction(3) | ||||
|                 .addLoyaltyLevel(1) | ||||
|                 .export(tables.traders[this.modInformation.testTrader]); | ||||
|         } | ||||
| 
 | ||||
|         return equipment; | ||||
|     } | ||||
| 
 | ||||
|     protected override filterPlateModsForSlotByLevel(settings: IGenerateEquipmentProperties, modSlot: string, existingPlateTplPool: string[], armorItem: ITemplateItem): IFilterPlateModsForSlotByLevelResult | ||||
|     { | ||||
|         const result: IFilterPlateModsForSlotByLevelResult = { result: Result.UNKNOWN_FAILURE, plateModTpls: undefined }; | ||||
| 
 | ||||
|         // Not pmc or not a plate slot, return original mod pool array
 | ||||
|         if (!this.itemHelper.isRemovablePlateSlot(modSlot)) | ||||
|         { | ||||
|             result.result = Result.NOT_PLATE_HOLDING_SLOT; | ||||
|             result.plateModTpls = existingPlateTplPool; | ||||
| 
 | ||||
|             return result; | ||||
|         } | ||||
| 
 | ||||
|         // Get the front/back/side weights based on bots level
 | ||||
|         const plateSlotWeights = settings.botEquipmentConfig?.armorPlateWeighting?.find( | ||||
|             (armorWeight) => | ||||
|                 settings.botData.level >= armorWeight.levelRange.min && settings.botData.level <= armorWeight.levelRange.max); | ||||
|         if (!plateSlotWeights) | ||||
|         { | ||||
|             // No weights, return original array of plate tpls
 | ||||
|             result.result = Result.LACKS_PLATE_WEIGHTS; | ||||
|             result.plateModTpls = existingPlateTplPool; | ||||
| 
 | ||||
|             return result; | ||||
|         } | ||||
| 
 | ||||
|         // Get the specific plate slot weights (front/back/side)
 | ||||
|         const plateWeights: Record<string, number> = plateSlotWeights[modSlot]; | ||||
|         if (!plateWeights) | ||||
|         { | ||||
|             // No weights, return original array of plate tpls
 | ||||
|             result.result = Result.LACKS_PLATE_WEIGHTS; | ||||
|             result.plateModTpls = existingPlateTplPool; | ||||
| 
 | ||||
|             return result; | ||||
|         } | ||||
| 
 | ||||
|         // Choose a plate level based on weighting
 | ||||
|         let chosenArmorPlateLevel = this.weightedRandomHelper.getWeightedValue<string>(plateWeights); | ||||
| 
 | ||||
|         // Convert the array of ids into database items
 | ||||
|         let platesFromDb = existingPlateTplPool.map((plateTpl) => this.itemHelper.getItem(plateTpl)[1]); | ||||
| 
 | ||||
|         // Filter plates to the chosen level based on its armorClass property
 | ||||
|         let platesOfDesiredLevel = platesFromDb.filter((item) => item._props.armorClass === chosenArmorPlateLevel); | ||||
|         let tries = 0; | ||||
|         while (platesOfDesiredLevel.length === 0) | ||||
|         { | ||||
|             tries++; | ||||
|             chosenArmorPlateLevel = (parseInt(chosenArmorPlateLevel)+1).toString() | ||||
|             if (parseInt(chosenArmorPlateLevel) > 6)  | ||||
|             { | ||||
|                 chosenArmorPlateLevel = "3" | ||||
|             }             | ||||
|             platesFromDb = existingPlateTplPool.map((plateTpl) => this.itemHelper.getItem(plateTpl)[1]); | ||||
|             platesOfDesiredLevel = platesFromDb.filter((item) => item._props.armorClass === chosenArmorPlateLevel); | ||||
| 
 | ||||
|             if (platesOfDesiredLevel.length > 0) break; | ||||
|             if (tries >= 3) break; | ||||
|         } | ||||
| 
 | ||||
|         if (platesOfDesiredLevel.length === 0) | ||||
|         { | ||||
|             this.logger.debug(`${settings.botData.role} - Plate filter was too restrictive for armor: ${armorItem._id}. Tried ${tries} times. Using mod items default plate.`); | ||||
| 
 | ||||
|             const relatedItemDbModSlot = armorItem._props.Slots.find((slot) => slot._name.toLowerCase() === modSlot); | ||||
|             const defaultPlate = relatedItemDbModSlot._props.filters[0].Plate; | ||||
|             if (!defaultPlate) | ||||
|             { | ||||
|                 // No relevant plate found after filtering AND no default plate
 | ||||
| 
 | ||||
|                 // Last attempt, get default preset and see if it has a plate default
 | ||||
|                 const defaultPreset = this.presetHelper.getDefaultPreset(armorItem._id); | ||||
|                 if (defaultPreset) | ||||
|                 { | ||||
|                     const relatedPresetSlot = defaultPreset._items.find( | ||||
|                         (item) => item.slotId?.toLowerCase() === modSlot); | ||||
|                     if (relatedPresetSlot) | ||||
|                     { | ||||
|                         result.result = Result.SUCCESS; | ||||
|                         result.plateModTpls = [relatedPresetSlot._tpl]; | ||||
| 
 | ||||
|                         return result; | ||||
|                     } | ||||
|                 } | ||||
|                 // Return Default Preset cause didn't have default plates
 | ||||
|                 result.result = Result.NO_DEFAULT_FILTER; | ||||
| 
 | ||||
|                 return result; | ||||
|             } | ||||
|             // Return Default Plates cause couldn't get lowest level available from original selection
 | ||||
|             result.result = Result.SUCCESS; | ||||
|             result.plateModTpls = [defaultPlate]; | ||||
| 
 | ||||
|             return result; | ||||
|         } | ||||
| 
 | ||||
|         // Only return the items ids
 | ||||
|         result.result = Result.SUCCESS; | ||||
|         result.plateModTpls = platesOfDesiredLevel.map((item) => item._id); | ||||
| 
 | ||||
|         return result; | ||||
|     } | ||||
| 
 | ||||
|     protected override getCompatibleModFromPool( | ||||
|         modPool: string[], | ||||
|         modSpawnType: ModSpawn, | ||||
|         weapon: IItem[] | ||||
|     ): IChooseRandomCompatibleModResult  | ||||
|     { | ||||
|         // Create exhaustable pool to pick mod item from
 | ||||
|         const exhaustableModPool = this.createExhaustableArray(modPool); | ||||
| 
 | ||||
|         // Create default response if no compatible item is found below
 | ||||
|         const chosenModResult: IChooseRandomCompatibleModResult = { | ||||
|             incompatible: true, | ||||
|             found: false, | ||||
|             reason: "unknown" | ||||
|         }; | ||||
| 
 | ||||
|         // Limit how many attempts to find a compatible mod can occur before giving up
 | ||||
|         const maxBlockedAttempts = Math.round(modPool.length); // 75% of pool size
 | ||||
|         let blockedAttemptCount = 0; | ||||
|         let chosenTpl: string; | ||||
|         while (exhaustableModPool.hasValues())  | ||||
|         { | ||||
|             chosenTpl = exhaustableModPool.getRandomValue(); | ||||
|             const pickedItemDetails = this.itemHelper.getItem(chosenTpl); | ||||
|             if (!pickedItemDetails[0])  | ||||
|             { | ||||
|                 // Not valid item, try again
 | ||||
|                 continue; | ||||
|             } | ||||
| 
 | ||||
|             if (!pickedItemDetails[1]._props)  | ||||
|             { | ||||
|                 // no props data, try again
 | ||||
|                 continue; | ||||
|             } | ||||
| 
 | ||||
|             // Success - Default wanted + only 1 item in pool
 | ||||
|             if (modSpawnType === ModSpawn.DEFAULT_MOD && modPool.length === 1)  | ||||
|             { | ||||
|                 chosenModResult.found = true; | ||||
|                 chosenModResult.incompatible = false; | ||||
|                 chosenModResult.chosenTpl = chosenTpl; | ||||
| 
 | ||||
|                 break; | ||||
|             } | ||||
| 
 | ||||
|             // Check if existing weapon mods are incompatible with chosen item
 | ||||
|             const existingItemBlockingChoice = weapon.find((item) => | ||||
|                 pickedItemDetails[1]._props.ConflictingItems?.includes(item._tpl) | ||||
|             ); | ||||
|             if (existingItemBlockingChoice)  | ||||
|             { | ||||
|                 // Give max of x attempts of picking a mod if blocked by another
 | ||||
|                 if (blockedAttemptCount > maxBlockedAttempts)  | ||||
|                 { | ||||
|                     blockedAttemptCount = 0; // reset
 | ||||
|                     break; | ||||
|                 } | ||||
| 
 | ||||
|                 blockedAttemptCount++; | ||||
| 
 | ||||
|                 // Not compatible - Try again
 | ||||
|                 continue; | ||||
|             } | ||||
| 
 | ||||
|             // Edge case- Some mod combos will never work, make sure this isnt the case
 | ||||
|             if (this.weaponModComboIsIncompatible(weapon, chosenTpl))  | ||||
|             { | ||||
|                 chosenModResult.reason = `Chosen weapon mod: ${chosenTpl} can never be compatible with existing weapon mods`; | ||||
|                 break; | ||||
|             } | ||||
| 
 | ||||
|             // Success
 | ||||
|             chosenModResult.found = true; | ||||
|             chosenModResult.incompatible = false; | ||||
|             chosenModResult.chosenTpl = chosenTpl; | ||||
| 
 | ||||
|             break; | ||||
|         } | ||||
| 
 | ||||
|         return chosenModResult; | ||||
|     } | ||||
|      | ||||
|     public apbsGenerateModsForWeapon(sessionId: string, request: IGenerateWeaponRequest, isPmc: boolean): IItem[]  | ||||
|     { | ||||
|         const pmcProfile = this.profileHelper.getPmcProfile(sessionId); | ||||
| 
 | ||||
|         // Get pool of mods that fit weapon
 | ||||
|         const compatibleModsPool = request.modPool[request.parentTemplate._id]; | ||||
| 
 | ||||
|         if ( | ||||
|             !( | ||||
|                 request.parentTemplate._props.Slots.length || | ||||
|                 request.parentTemplate._props.Cartridges?.length || | ||||
|                 request.parentTemplate._props.Chambers?.length | ||||
|             ) | ||||
|         )  | ||||
|         { | ||||
|             this.logger.error( | ||||
|                 this.localisationService.getText("bot-unable_to_add_mods_to_weapon_missing_ammo_slot", { | ||||
|                     weaponName: request.parentTemplate._name, | ||||
|                     weaponId: request.parentTemplate._id, | ||||
|                     botRole: request.botData.role | ||||
|                 }) | ||||
|             ); | ||||
| 
 | ||||
|             return request.weapon; | ||||
|         } | ||||
| 
 | ||||
|         const botEquipConfig = this.botConfig.equipment[request.botData.equipmentRole]; | ||||
|         const botEquipBlacklist = this.botEquipmentFilterService.getBotEquipmentBlacklist( | ||||
|             request.botData.equipmentRole, | ||||
|             pmcProfile.Info.Level | ||||
|         ); | ||||
|         const botWeaponSightWhitelist = this.botEquipmentFilterService.getBotWeaponSightWhitelist( | ||||
|             request.botData.equipmentRole | ||||
|         ); | ||||
|         const randomisationSettings = this.botHelper.getBotRandomizationDetails(request.botData.level, botEquipConfig); | ||||
| 
 | ||||
|         // Iterate over mod pool and choose mods to attach
 | ||||
|         const sortedModKeys = this.sortModKeys(Object.keys(compatibleModsPool), request.parentTemplate._id); | ||||
|         for (const modSlot of sortedModKeys)  | ||||
|         { | ||||
|             // Check weapon has slot for mod to fit in
 | ||||
|             const modsParentSlot = this.getModItemSlotFromDb(modSlot, request.parentTemplate); | ||||
|             if (!modsParentSlot)  | ||||
|             { | ||||
|                 this.logger.error( | ||||
|                     this.localisationService.getText("bot-weapon_missing_mod_slot", { | ||||
|                         modSlot: modSlot, | ||||
|                         weaponId: request.parentTemplate._id, | ||||
|                         weaponName: request.parentTemplate._name, | ||||
|                         botRole: request.botData.role | ||||
|                     }) | ||||
|                 ); | ||||
| 
 | ||||
|                 continue; | ||||
|             } | ||||
| 
 | ||||
|             // Check spawn chance of mod
 | ||||
|             const modSpawnResult = this.shouldModBeSpawned( | ||||
|                 modsParentSlot, | ||||
|                 modSlot, | ||||
|                 request.modSpawnChances, | ||||
|                 botEquipConfig | ||||
|             ); | ||||
|             if (modSpawnResult === ModSpawn.SKIP)  | ||||
|             { | ||||
|                 continue; | ||||
|             } | ||||
| 
 | ||||
|             const isRandomisableSlot = randomisationSettings?.randomisedWeaponModSlots?.includes(modSlot) ?? false; | ||||
|             const modToSpawnRequest: IModToSpawnRequest = { | ||||
|                 modSlot: modSlot, | ||||
|                 isRandomisableSlot: isRandomisableSlot, | ||||
|                 randomisationSettings: randomisationSettings, | ||||
|                 botWeaponSightWhitelist: botWeaponSightWhitelist, | ||||
|                 botEquipBlacklist: botEquipBlacklist, | ||||
|                 itemModPool: compatibleModsPool, | ||||
|                 weapon: request.weapon, | ||||
|                 ammoTpl: request.ammoTpl, | ||||
|                 parentTemplate: request.parentTemplate, | ||||
|                 modSpawnResult: modSpawnResult, | ||||
|                 weaponStats: request.weaponStats, | ||||
|                 conflictingItemTpls: request.conflictingItemTpls, | ||||
|                 botData: request.botData | ||||
|             }; | ||||
|             const modToAdd = this.chooseModToPutIntoSlot(modToSpawnRequest); | ||||
| 
 | ||||
|             // Compatible mod not found
 | ||||
|             if (!modToAdd || typeof modToAdd === "undefined")  | ||||
|             { | ||||
|                 continue; | ||||
|             } | ||||
| 
 | ||||
|             if ( | ||||
|                 !this.isModValidForSlot(modToAdd, modsParentSlot, modSlot, request.parentTemplate, request.botData.role) | ||||
|             )  | ||||
|             { | ||||
|                 continue; | ||||
|             } | ||||
| 
 | ||||
|             const modToAddTemplate = modToAdd[1]; | ||||
|             // Skip adding mod to weapon if type limit reached
 | ||||
|             if ( | ||||
|                 this.botWeaponModLimitService.weaponModHasReachedLimit( | ||||
|                     request.botData.equipmentRole, | ||||
|                     modToAddTemplate, | ||||
|                     request.modLimits, | ||||
|                     request.parentTemplate, | ||||
|                     request.weapon | ||||
|                 ) | ||||
|             )  | ||||
|             { | ||||
|                 continue; | ||||
|             } | ||||
| 
 | ||||
|             if (vanillaButtpads.includes(modToAddTemplate._id)) | ||||
|             { | ||||
|                 if (!this.randomUtil.getChance100(ModConfig.config.stockButtpadChance)) | ||||
|                 { | ||||
|                     continue; | ||||
|                 } | ||||
|             } | ||||
|              | ||||
|             // If item is a mount for scopes, set scope chance to 100%, this helps fix empty mounts appearing on weapons
 | ||||
|             if (this.modSlotCanHoldScope(modSlot, modToAddTemplate._parent))  | ||||
|             { | ||||
|                 // mod_mount was picked to be added to weapon, force scope chance to ensure its filled
 | ||||
|                 let scopeSlots = ["mod_scope", "mod_scope_000", "mod_scope_001", "mod_scope_002", "mod_scope_003"]; | ||||
|                 if (isPmc) scopeSlots =  ["mod_scope", "mod_scope_000"] | ||||
|                  | ||||
|                 this.adjustSlotSpawnChances(request.modSpawnChances, scopeSlots, 100); | ||||
| 
 | ||||
|                 // Hydrate pool of mods that fit into mount as its a randomisable slot
 | ||||
|                 if (isRandomisableSlot)  | ||||
|                 { | ||||
|                     // Add scope mods to modPool dictionary to ensure the mount has a scope in the pool to pick
 | ||||
|                     this.addCompatibleModsForProvidedMod( | ||||
|                         "mod_scope", | ||||
|                         modToAddTemplate, | ||||
|                         request.modPool, | ||||
|                         botEquipBlacklist | ||||
|                     ); | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|              | ||||
|             if (ModConfig.config.forceChildrenMuzzle) | ||||
|             { | ||||
|                 // If picked item is muzzle adapter that can hold a child, adjust spawn chance
 | ||||
|                 if (this.modSlotCanHoldMuzzleDevices(modSlot, modToAddTemplate._parent))  | ||||
|                 { | ||||
|                     const muzzleSlots = ["mod_muzzle", "mod_muzzle_000", "mod_muzzle_001"]; | ||||
|                     this.adjustSlotSpawnChances(request.modSpawnChances, muzzleSlots, 100); | ||||
|                 } | ||||
|             } | ||||
|              | ||||
|             // If front/rear sight are to be added, set opposite to 100% chance
 | ||||
|             if (this.modIsFrontOrRearSight(modSlot, modToAddTemplate._id))  | ||||
|             { | ||||
|                 request.modSpawnChances.mod_sight_front = 100; | ||||
|                 request.modSpawnChances.mod_sight_rear = 100; | ||||
|             } | ||||
| 
 | ||||
|             // 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.some((slot) => slot._name === "mod_handguard") && | ||||
|                 !request.weapon.some((item) => item.slotId === "mod_launcher") | ||||
|             )  | ||||
|             { | ||||
|                 // Needed for handguards with lower
 | ||||
|                 request.modSpawnChances.mod_handguard = 100; | ||||
|             } | ||||
| 
 | ||||
|             // 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 (this.shouldForceSubStockSlots(modSlot, botEquipConfig, modToAddTemplate))  | ||||
|             { | ||||
|                 // Stock mod can take additional stocks, could be a locking device, force 100% chance
 | ||||
|                 const subStockSlots = ["mod_stock", "mod_stock_000", "mod_stock_001", "mod_stock_akms"]; | ||||
|                 this.adjustSlotSpawnChances(request.modSpawnChances, subStockSlots, 100); | ||||
|             } | ||||
| 
 | ||||
|             // Gather stats on mods being added to weapon
 | ||||
|             if (this.itemHelper.isOfBaseclass(modToAddTemplate._id, BaseClasses.IRON_SIGHT))  | ||||
|             { | ||||
|                 if (modSlot === "mod_sight_front")  | ||||
|                 { | ||||
|                     request.weaponStats.hasFrontIronSight = true; | ||||
|                 } | ||||
|                 else if (modSlot === "mod_sight_rear")  | ||||
|                 { | ||||
|                     request.weaponStats.hasRearIronSight = true; | ||||
|                 } | ||||
|             } | ||||
|             else if ( | ||||
|                 !request.weaponStats.hasOptic && | ||||
|                 this.itemHelper.isOfBaseclass(modToAddTemplate._id, BaseClasses.SIGHTS) | ||||
|             )  | ||||
|             { | ||||
|                 request.weaponStats.hasOptic = true; | ||||
|             } | ||||
| 
 | ||||
|             const modId = this.hashUtil.generate(); | ||||
|             request.weapon.push( | ||||
|                 this.createModItem( | ||||
|                     modId, | ||||
|                     modToAddTemplate._id, | ||||
|                     request.weaponId, | ||||
|                     modSlot, | ||||
|                     modToAddTemplate, | ||||
|                     request.botData.role | ||||
|                 ) | ||||
|             ); | ||||
| 
 | ||||
|             // Update conflicting item list now item has been chosen
 | ||||
|             for (const conflictingItem of modToAddTemplate._props.ConflictingItems)  | ||||
|             { | ||||
|                 request.conflictingItemTpls.add(conflictingItem); | ||||
|             } | ||||
| 
 | ||||
|             // I first thought we could use the recursive generateModsForItems as previously for cylinder magazines.
 | ||||
|             // However, the recursion doesn't go over the slots of the parent mod but over the modPool which is given by the bot config
 | ||||
|             // where we decided to keep cartridges instead of camoras. And since a CylinderMagazine only has one cartridge entry and
 | ||||
|             // this entry is not to be filled, we need a special handling for the CylinderMagazine
 | ||||
|             const modParentItem = this.itemHelper.getItem(modToAddTemplate._parent)[1]; | ||||
|             if (this.botWeaponGeneratorHelper.magazineIsCylinderRelated(modParentItem._name))  | ||||
|             { | ||||
|                 // We don't have child mods, we need to create the camoras for the magazines instead
 | ||||
|                 this.fillCamora(request.weapon, request.modPool, modId, modToAddTemplate); | ||||
|             } | ||||
|             else  | ||||
|             { | ||||
|                 let containsModInPool = Object.keys(request.modPool).includes(modToAddTemplate._id); | ||||
| 
 | ||||
|                 // Sometimes randomised slots are missing sub-mods, if so, get values from mod pool service
 | ||||
|                 // Check for a randomisable slot + without data in modPool + item being added as additional slots
 | ||||
|                 if (isRandomisableSlot && !containsModInPool && modToAddTemplate._props.Slots.length > 0)  | ||||
|                 { | ||||
|                     const modFromService = this.botEquipmentModPoolService.getModsForWeaponSlot(modToAddTemplate._id); | ||||
|                     if (Object.keys(modFromService ?? {}).length > 0)  | ||||
|                     { | ||||
|                         request.modPool[modToAddTemplate._id] = modFromService; | ||||
|                         containsModInPool = true; | ||||
|                     } | ||||
|                 } | ||||
|                 if (containsModInPool)  | ||||
|                 { | ||||
|                     const recursiveRequestData: IGenerateWeaponRequest = { | ||||
|                         weapon: request.weapon, | ||||
|                         modPool: request.modPool, | ||||
|                         weaponId: modId, | ||||
|                         parentTemplate: modToAddTemplate, | ||||
|                         modSpawnChances: request.modSpawnChances, | ||||
|                         ammoTpl: request.ammoTpl, | ||||
|                         botData: { | ||||
|                             role: request.botData.role, | ||||
|                             level: request.botData.level, | ||||
|                             equipmentRole: request.botData.equipmentRole | ||||
|                         }, | ||||
|                         modLimits: request.modLimits, | ||||
|                         weaponStats: request.weaponStats, | ||||
|                         conflictingItemTpls: request.conflictingItemTpls | ||||
|                     }; | ||||
|                     // Call self recursively to add mods to this mod
 | ||||
|                     this.apbsGenerateModsForWeapon(sessionId, recursiveRequestData, isPmc); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         return request.weapon; | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,118 @@ | |||
| import { inject, injectable } from "tsyringe"; | ||||
| 
 | ||||
| import { BotHelper } from "@spt/helpers/BotHelper"; | ||||
| import { ProfileHelper } from "@spt/helpers/ProfileHelper"; | ||||
| import { WeightedRandomHelper } from "@spt/helpers/WeightedRandomHelper"; | ||||
| import { ILogger } from "@spt/models/spt/utils/ILogger"; | ||||
| import { ConfigServer } from "@spt/servers/ConfigServer"; | ||||
| import { BotEquipmentFilterService } from "@spt/services/BotEquipmentFilterService"; | ||||
| import { DatabaseService } from "@spt/services/DatabaseService"; | ||||
| import { ItemFilterService } from "@spt/services/ItemFilterService"; | ||||
| import { HashUtil } from "@spt/utils/HashUtil"; | ||||
| import { RandomUtil } from "@spt/utils/RandomUtil"; | ||||
| import { ICloner } from "@spt/utils/cloners/ICloner"; | ||||
| 
 | ||||
| import { APBSEquipmentGetter } from "../Utils/APBSEquipmentGetter"; | ||||
| import { APBSTierGetter } from "../Utils/APBSTierGetter"; | ||||
| import { BotGenerator } from "@spt/generators/BotGenerator"; | ||||
| import { BotInventoryGenerator } from "@spt/generators/BotInventoryGenerator"; | ||||
| import { BotLevelGenerator } from "@spt/generators/BotLevelGenerator"; | ||||
| import { SeasonalEventService } from "@spt/services/SeasonalEventService"; | ||||
| import { TimeUtil } from "@spt/utils/TimeUtil"; | ||||
| import { IBotBase } from "@spt/models/eft/common/tables/IBotBase"; | ||||
| import { IAppearance } from "@spt/models/eft/common/tables/IBotType"; | ||||
| import { IBotGenerationDetails } from "@spt/models/spt/bots/BotGenerationDetails"; | ||||
| import { IWildBody } from "@spt/models/eft/common/IGlobals"; | ||||
| import { BotNameService } from "@spt/services/BotNameService"; | ||||
| import { BotGeneratorHelper } from "@spt/helpers/BotGeneratorHelper"; | ||||
| import { ModConfig } from "../Globals/ModConfig"; | ||||
| 
 | ||||
| /** Handle profile related client events */ | ||||
| @injectable() | ||||
| export class APBSBotGenerator extends BotGenerator | ||||
| { | ||||
| 
 | ||||
|     constructor( | ||||
|         @inject("PrimaryLogger") protected logger: ILogger, | ||||
|         @inject("HashUtil") protected hashUtil: HashUtil, | ||||
|         @inject("RandomUtil") protected randomUtil: RandomUtil, | ||||
|         @inject("TimeUtil") protected timeUtil: TimeUtil, | ||||
|         @inject("ProfileHelper") protected profileHelper: ProfileHelper, | ||||
|         @inject("DatabaseService") protected databaseService: DatabaseService, | ||||
|         @inject("BotInventoryGenerator") protected botInventoryGenerator: BotInventoryGenerator, | ||||
|         @inject("BotLevelGenerator") protected botLevelGenerator: BotLevelGenerator, | ||||
|         @inject("BotEquipmentFilterService") protected botEquipmentFilterService: BotEquipmentFilterService, | ||||
|         @inject("WeightedRandomHelper") protected weightedRandomHelper: WeightedRandomHelper, | ||||
|         @inject("BotHelper") protected botHelper: BotHelper, | ||||
|         @inject("BotGeneratorHelper") protected botGeneratorHelper: BotGeneratorHelper, | ||||
|         @inject("SeasonalEventService") protected seasonalEventService: SeasonalEventService, | ||||
|         @inject("ItemFilterService") protected itemFilterService: ItemFilterService, | ||||
|         @inject("BotNameService") protected botNameService: BotNameService, | ||||
|         @inject("ConfigServer") protected configServer: ConfigServer, | ||||
|         @inject("PrimaryCloner") protected cloner: ICloner, | ||||
|         @inject("APBSEquipmentGetter") protected apbsEquipmentGetter: APBSEquipmentGetter, | ||||
|         @inject("APBSTierGetter") protected apbsTierGetter: APBSTierGetter | ||||
|     ) | ||||
|     { | ||||
|         super(logger,  | ||||
|             hashUtil,  | ||||
|             randomUtil,  | ||||
|             timeUtil,  | ||||
|             profileHelper,  | ||||
|             databaseService,  | ||||
|             botInventoryGenerator,  | ||||
|             botLevelGenerator,  | ||||
|             botEquipmentFilterService,  | ||||
|             weightedRandomHelper,  | ||||
|             botHelper,  | ||||
|             botGeneratorHelper, | ||||
|             seasonalEventService, | ||||
|             itemFilterService,  | ||||
|             botNameService, | ||||
|             configServer,  | ||||
|             cloner) | ||||
|     } | ||||
| 
 | ||||
|     protected override setBotAppearance(bot: IBotBase, appearance: IAppearance, botGenerationDetails: IBotGenerationDetails): void | ||||
|     { | ||||
|         if (botGenerationDetails.isPmc) | ||||
|         { | ||||
|             const tier = this.apbsTierGetter.getTierByLevel(bot.Info.Level) | ||||
|             const role = bot.Info.Settings.Role | ||||
|             const getSeasonalAppearance = ModConfig.config.seasonalPmcAppearance ? true : false; | ||||
|             const appearanceJson = this.apbsEquipmentGetter.getPmcAppearance(role, tier, getSeasonalAppearance); | ||||
| 
 | ||||
|             bot.Customization.Head = this.weightedRandomHelper.getWeightedValue<string>(appearanceJson.head); | ||||
|             bot.Customization.Hands = this.weightedRandomHelper.getWeightedValue<string>(appearanceJson.hands); | ||||
|             bot.Customization.Body = this.weightedRandomHelper.getWeightedValue<string>(appearanceJson.body); | ||||
|             bot.Customization.Feet = this.weightedRandomHelper.getWeightedValue<string>(appearanceJson.feet); | ||||
| 
 | ||||
|             const bodyGlobalDict = this.databaseService.getGlobals().config.Customization.SavageBody; | ||||
|             const chosenBodyTemplate = this.databaseService.getCustomization()[bot.Customization.Body]; | ||||
|      | ||||
|             // Find the body/hands mapping
 | ||||
|             const matchingBody: IWildBody = bodyGlobalDict[chosenBodyTemplate?._name]; | ||||
|             if (matchingBody?.isNotRandom)  | ||||
|             { | ||||
|                 // Has fixed hands for this body, set them
 | ||||
|                 bot.Customization.Hands = matchingBody.hands; | ||||
|             } | ||||
|             return; | ||||
|         } | ||||
|         bot.Customization.Head = this.weightedRandomHelper.getWeightedValue<string>(appearance.head); | ||||
|         bot.Customization.Body = this.weightedRandomHelper.getWeightedValue<string>(appearance.body); | ||||
|         bot.Customization.Feet = this.weightedRandomHelper.getWeightedValue<string>(appearance.feet); | ||||
|         bot.Customization.Hands = this.weightedRandomHelper.getWeightedValue<string>(appearance.hands); | ||||
| 
 | ||||
|         const bodyGlobalDict = this.databaseService.getGlobals().config.Customization.SavageBody; | ||||
|         const chosenBodyTemplate = this.databaseService.getCustomization()[bot.Customization.Body]; | ||||
| 
 | ||||
|         // Find the body/hands mapping
 | ||||
|         const matchingBody: IWildBody = bodyGlobalDict[chosenBodyTemplate?._name]; | ||||
|         if (matchingBody?.isNotRandom)  | ||||
|         { | ||||
|             // Has fixed hands for this body, set them
 | ||||
|             bot.Customization.Hands = matchingBody.hands; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,70 @@ | |||
| import { inject, injectable } from "tsyringe"; | ||||
| 
 | ||||
| import { ILogger } from "@spt/models/spt/utils/ILogger"; | ||||
| import { ConfigServer } from "@spt/servers/ConfigServer"; | ||||
| import { DatabaseService } from "@spt/services/DatabaseService"; | ||||
| import { RandomUtil } from "@spt/utils/RandomUtil"; | ||||
| 
 | ||||
| import { BotGeneratorHelper } from "@spt/helpers/BotGeneratorHelper"; | ||||
| import { ApplicationContext } from "@spt/context/ApplicationContext"; | ||||
| import { ContextVariableType } from "@spt/context/ContextVariableType"; | ||||
| import { ContainerHelper } from "@spt/helpers/ContainerHelper"; | ||||
| import { DurabilityLimitsHelper } from "@spt/helpers/DurabilityLimitsHelper"; | ||||
| import { InventoryHelper } from "@spt/helpers/InventoryHelper"; | ||||
| import { ItemHelper } from "@spt/helpers/ItemHelper"; | ||||
| import { IUpd } from "@spt/models/eft/common/tables/IItem"; | ||||
| import { ITemplateItem } from "@spt/models/eft/common/tables/ITemplateItem"; | ||||
| import { IGetRaidConfigurationRequestData } from "@spt/models/eft/match/IGetRaidConfigurationRequestData"; | ||||
| import { BaseClasses } from "@spt/models/enums/BaseClasses"; | ||||
| import { LocalisationService } from "@spt/services/LocalisationService"; | ||||
| import { IRandomisedResourceValues } from "@spt/models/spt/config/IBotConfig"; | ||||
| 
 | ||||
| /** Handle profile related client events */ | ||||
| @injectable() | ||||
| export class APBSBotGeneratorHelper extends BotGeneratorHelper | ||||
| { | ||||
| 
 | ||||
|     constructor( | ||||
|         @inject("PrimaryLogger") protected logger: ILogger, | ||||
|         @inject("RandomUtil") protected randomUtil: RandomUtil, | ||||
|         @inject("DatabaseService") protected databaseService: DatabaseService, | ||||
|         @inject("DurabilityLimitsHelper") protected durabilityLimitsHelper: DurabilityLimitsHelper, | ||||
|         @inject("ItemHelper") protected itemHelper: ItemHelper, | ||||
|         @inject("InventoryHelper") protected inventoryHelper: InventoryHelper, | ||||
|         @inject("ContainerHelper") protected containerHelper: ContainerHelper, | ||||
|         @inject("ApplicationContext") protected applicationContext: ApplicationContext, | ||||
|         @inject("LocalisationService") protected localisationService: LocalisationService, | ||||
|         @inject("ConfigServer") protected configServer: ConfigServer | ||||
|     ) | ||||
|     { | ||||
|         super(logger,  | ||||
|             randomUtil,  | ||||
|             databaseService,  | ||||
|             durabilityLimitsHelper,  | ||||
|             itemHelper,  | ||||
|             inventoryHelper,  | ||||
|             containerHelper,  | ||||
|             applicationContext,  | ||||
|             localisationService,  | ||||
|             configServer) | ||||
|     } | ||||
| 
 | ||||
|     protected override getRandomizedResourceValue(maxResource: number, randomizationValues: IRandomisedResourceValues): number | ||||
|     { | ||||
|         if (!randomizationValues)  | ||||
|         { | ||||
|             return maxResource; | ||||
|         } | ||||
| 
 | ||||
|         if (this.randomUtil.getChance100(randomizationValues.chanceMaxResourcePercent))  | ||||
|         { | ||||
|             return maxResource; | ||||
|         } | ||||
| 
 | ||||
|         const newResourceValue = this.randomUtil.getInt( | ||||
|             this.randomUtil.getPercentOfValue(randomizationValues.resourcePercent, maxResource, 0), | ||||
|             maxResource | ||||
|         ) | ||||
|         return newResourceValue ? newResourceValue : 1; | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,375 @@ | |||
| import { inject, injectable } from "tsyringe"; | ||||
| 
 | ||||
| import { BotEquipmentModGenerator } from "@spt/generators/BotEquipmentModGenerator"; | ||||
| import { BotLootGenerator } from "@spt/generators/BotLootGenerator"; | ||||
| import { BotWeaponGenerator } from "@spt/generators/BotWeaponGenerator"; | ||||
| import { BotGeneratorHelper } from "@spt/helpers/BotGeneratorHelper"; | ||||
| import { BotHelper } from "@spt/helpers/BotHelper"; | ||||
| import { ItemHelper } from "@spt/helpers/ItemHelper"; | ||||
| import { ContextVariableType } from "@spt/context/ContextVariableType"; | ||||
| import { WeightedRandomHelper } from "@spt/helpers/WeightedRandomHelper"; | ||||
| import { IInventory as PmcInventory } from "@spt/models/eft/common/tables/IBotBase"; | ||||
| import { IChances, IGeneration, IBotType, IInventory } from "@spt/models/eft/common/tables/IBotType"; | ||||
| import { ITemplateItem } from "@spt/models/eft/common/tables/ITemplateItem"; | ||||
| import { EquipmentSlots } from "@spt/models/enums/EquipmentSlots"; | ||||
| import { IGenerateEquipmentProperties } from "@spt/models/spt/bots/IGenerateEquipmentProperties"; | ||||
| import { ILogger } from "@spt/models/spt/utils/ILogger"; | ||||
| import { ConfigServer } from "@spt/servers/ConfigServer"; | ||||
| import { BotEquipmentModPoolService } from "@spt/services/BotEquipmentModPoolService"; | ||||
| import { DatabaseService } from "@spt/services/DatabaseService"; | ||||
| import { LocalisationService } from "@spt/services/LocalisationService"; | ||||
| import { HashUtil } from "@spt/utils/HashUtil"; | ||||
| import { RandomUtil } from "@spt/utils/RandomUtil"; | ||||
| 
 | ||||
| import { BotInventoryGenerator } from "@spt/generators/BotInventoryGenerator"; | ||||
| import { APBSEquipmentGetter } from "../Utils/APBSEquipmentGetter"; | ||||
| import { APBSTierGetter } from "../Utils/APBSTierGetter"; | ||||
| import { ModConfig } from "../Globals/ModConfig"; | ||||
| import { APBSBotWeaponGenerator } from "../ClassExtensions/APBSBotWeaponGenerator"; | ||||
| import { ApplicationContext } from "@spt/context/ApplicationContext"; | ||||
| import { ProfileHelper } from "@spt/helpers/ProfileHelper"; | ||||
| import { WeatherHelper } from "@spt/helpers/WeatherHelper"; | ||||
| import { BotEquipmentFilterService } from "@spt/services/BotEquipmentFilterService"; | ||||
| import { IGetRaidConfigurationRequestData } from "@spt/models/eft/match/IGetRaidConfigurationRequestData"; | ||||
| import { RaidInformation } from "../Globals/RaidInformation"; | ||||
| import { APBSLogger } from "../Utils/APBSLogger"; | ||||
| import { Logging } from "../Enums/Logging"; | ||||
| 
 | ||||
| /** Handle profile related client events */ | ||||
| @injectable() | ||||
| export class APBSBotInventoryGenerator extends BotInventoryGenerator | ||||
| { | ||||
|     constructor( | ||||
|         @inject("PrimaryLogger") protected logger: ILogger, | ||||
|         @inject("HashUtil") protected hashUtil: HashUtil, | ||||
|         @inject("RandomUtil") protected randomUtil: RandomUtil, | ||||
|         @inject("DatabaseService") protected databaseService: DatabaseService, | ||||
|         @inject("ApplicationContext") protected applicationContext: ApplicationContext, | ||||
|         @inject("BotWeaponGenerator") protected botWeaponGenerator: BotWeaponGenerator, | ||||
|         @inject("BotLootGenerator") protected botLootGenerator: BotLootGenerator, | ||||
|         @inject("BotGeneratorHelper") protected botGeneratorHelper: BotGeneratorHelper, | ||||
|         @inject("ProfileHelper") protected profileHelper: ProfileHelper, | ||||
|         @inject("BotHelper") protected botHelper: BotHelper, | ||||
|         @inject("WeightedRandomHelper") protected weightedRandomHelper: WeightedRandomHelper, | ||||
|         @inject("ItemHelper") protected itemHelper: ItemHelper, | ||||
|         @inject("WeatherHelper") protected weatherHelper: WeatherHelper, | ||||
|         @inject("LocalisationService") protected localisationService: LocalisationService, | ||||
|         @inject("BotEquipmentFilterService") protected botEquipmentFilterService: BotEquipmentFilterService, | ||||
|         @inject("BotEquipmentModPoolService") protected botEquipmentModPoolService: BotEquipmentModPoolService, | ||||
|         @inject("BotEquipmentModGenerator") protected botEquipmentModGenerator: BotEquipmentModGenerator, | ||||
|         @inject("ConfigServer") protected configServer: ConfigServer, | ||||
|         @inject("APBSEquipmentGetter") protected apbsEquipmentGetter: APBSEquipmentGetter, | ||||
|         @inject("APBSTierGetter") protected apbsTierGetter: APBSTierGetter, | ||||
|         @inject("APBSBotWeaponGenerator") protected apbsBotWeaponGenerator: APBSBotWeaponGenerator, | ||||
|         @inject("RaidInformation") protected raidInformation: RaidInformation, | ||||
|         @inject("APBSLogger") protected apbsLogger: APBSLogger | ||||
|     ) | ||||
|     { | ||||
|         super(logger,  | ||||
|             hashUtil,  | ||||
|             randomUtil,  | ||||
|             databaseService,  | ||||
|             applicationContext, | ||||
|             botWeaponGenerator,  | ||||
|             botLootGenerator,  | ||||
|             botGeneratorHelper,  | ||||
|             profileHelper, | ||||
|             botHelper,  | ||||
|             weightedRandomHelper,  | ||||
|             itemHelper, | ||||
|             weatherHelper, | ||||
|             localisationService,  | ||||
|             botEquipmentFilterService, | ||||
|             botEquipmentModPoolService,  | ||||
|             botEquipmentModGenerator,  | ||||
|             configServer) | ||||
|     } | ||||
| 
 | ||||
|     public override generateInventory( | ||||
|         sessionId: string, | ||||
|         botJsonTemplate: IBotType, | ||||
|         botRole: string, | ||||
|         isPmc: boolean, | ||||
|         botLevel: number, | ||||
|         chosenGameVersion: string | ||||
|     ): PmcInventory  | ||||
|     { | ||||
|         const templateInventory = botJsonTemplate.inventory; | ||||
|         const wornItemChances = botJsonTemplate.chances; | ||||
|         const itemGenerationLimitsMinMax: IGeneration = botJsonTemplate.generation; | ||||
| 
 | ||||
|         // Generate base inventory with no items
 | ||||
|         const botInventory = this.generateInventoryBase(); | ||||
|          | ||||
|         const raidConfig = this.applicationContext | ||||
|             .getLatestValue(ContextVariableType.RAID_CONFIGURATION) | ||||
|             ?.getValue<IGetRaidConfigurationRequestData>(); | ||||
| 
 | ||||
|         this.generateAndAddEquipmentToBot( | ||||
|             sessionId, | ||||
|             templateInventory, | ||||
|             wornItemChances, | ||||
|             botRole, | ||||
|             botInventory, | ||||
|             botLevel, | ||||
|             chosenGameVersion, | ||||
|             raidConfig | ||||
|         ); | ||||
|          | ||||
|         if (!this.raidInformation.isBotEnabled(botRole)) | ||||
|         { | ||||
|             this.generateAndAddWeaponsToBot(templateInventory, wornItemChances, sessionId, botInventory, botRole, isPmc, itemGenerationLimitsMinMax, botLevel); | ||||
|             this.botLootGenerator.generateLoot(sessionId, botJsonTemplate, isPmc, botRole, botInventory, botLevel); | ||||
| 
 | ||||
|             return botInventory; | ||||
|         } | ||||
| 
 | ||||
|         // APBS generation chances instead
 | ||||
|         const tierInfo = this.apbsTierGetter.getTierByLevel(botLevel); | ||||
|         const chances = this.apbsEquipmentGetter.getSpawnChancesByBotRole(botRole, tierInfo); | ||||
|         const generation = chances.generation; | ||||
|          | ||||
|         this.generateAndAddWeaponsToBot(templateInventory, chances, sessionId, botInventory, botRole, isPmc, generation, botLevel); | ||||
|         this.botLootGenerator.generateLoot(sessionId, botJsonTemplate, isPmc, botRole, botInventory, botLevel); | ||||
| 
 | ||||
|         return botInventory; | ||||
|          | ||||
|     } | ||||
| 
 | ||||
|     protected override generateEquipment = (settings: IGenerateEquipmentProperties): boolean =>  | ||||
|     { | ||||
|         const equipmentSlot = settings.rootEquipmentSlot as string; | ||||
|         const botRole = settings.botData.role; | ||||
|         const botLevel = settings.botData.level; | ||||
|         const tierInfo = this.apbsTierGetter.getTierByLevel(botLevel); | ||||
|          | ||||
|         let equipmentPool = this.apbsEquipmentGetter.getEquipmentByBotRole(botRole, tierInfo, equipmentSlot); | ||||
|         let randomisationDetails = this.apbsEquipmentGetter.getSpawnChancesByBotRole(botRole, tierInfo); | ||||
|         let wornItemChances = this.apbsEquipmentGetter.getSpawnChancesByBotRole(botRole, tierInfo); | ||||
|         let modPool = this.apbsEquipmentGetter.getModsByBotRole(botRole, tierInfo); | ||||
|         let apbsBot = true; | ||||
| 
 | ||||
|         if (!this.raidInformation.isBotEnabled(botRole)) | ||||
|         { | ||||
|             equipmentPool = settings.rootEquipmentPool; | ||||
|             randomisationDetails = settings.randomisationDetails; | ||||
|             wornItemChances = settings.spawnChances; | ||||
|             modPool = settings.modPool; | ||||
|             apbsBot = false; | ||||
|         } | ||||
|          | ||||
|         if (apbsBot && equipmentSlot == EquipmentSlots.TACTICAL_VEST && !settings.inventory.items.find(e => e.slotId === "ArmorVest")) | ||||
|         { | ||||
|             equipmentPool = this.apbsEquipmentGetter.getEquipmentByBotRole(botRole, tierInfo, "ArmouredRig"); | ||||
|         } | ||||
|          | ||||
|         if (equipmentSlot == EquipmentSlots.POCKETS && Object.keys(settings.rootEquipmentPool).includes("65e080be269cbd5c5005e529")) | ||||
|         { | ||||
|             equipmentPool = settings.rootEquipmentPool; | ||||
|         } | ||||
| 
 | ||||
|         const spawnChance = ([EquipmentSlots.POCKETS, EquipmentSlots.SECURED_CONTAINER] as string[]).includes( | ||||
|             settings.rootEquipmentSlot | ||||
|         ) | ||||
|             ? 100 | ||||
|             : wornItemChances.equipment[settings.rootEquipmentSlot]; | ||||
| 
 | ||||
|         if (typeof spawnChance === "undefined")  | ||||
|         { | ||||
|             this.logger.warning( | ||||
|                 this.localisationService.getText( | ||||
|                     "bot-no_spawn_chance_defined_for_equipment_slot", | ||||
|                     settings.rootEquipmentSlot | ||||
|                 ) | ||||
|             ); | ||||
| 
 | ||||
|             return false; | ||||
|         } | ||||
| 
 | ||||
|         const shouldSpawn = this.randomUtil.getChance100(spawnChance); | ||||
|         if (shouldSpawn && Object.keys(equipmentPool).length)  | ||||
|         { | ||||
|             let pickedItemDb: ITemplateItem; | ||||
|             let found = false; | ||||
| 
 | ||||
|             const maxAttempts = Math.round(Object.keys(equipmentPool).length * 0.75); // Roughly 75% of pool size
 | ||||
|             let attempts = 0; | ||||
|             while (!found)  | ||||
|             { | ||||
|                 if (Object.values(equipmentPool).length === 0)  | ||||
|                 { | ||||
|                     return false; | ||||
|                 } | ||||
| 
 | ||||
|                 const chosenItemTpl = this.weightedRandomHelper.getWeightedValue<string>(equipmentPool); | ||||
|                 const dbResult = this.itemHelper.getItem(chosenItemTpl); | ||||
| 
 | ||||
|                 if (!dbResult[0])  | ||||
|                 { | ||||
|                     this.logger.error(this.localisationService.getText("bot-missing_item_template", chosenItemTpl)); | ||||
|                     this.logger.info(`EquipmentSlot -> ${settings.rootEquipmentSlot}`); | ||||
| 
 | ||||
| 
 | ||||
|                     attempts++; | ||||
| 
 | ||||
|                     continue; | ||||
|                 } | ||||
| 
 | ||||
|                 const compatabilityResult = this.botGeneratorHelper.isItemIncompatibleWithCurrentItems( | ||||
|                     settings.inventory.items, | ||||
|                     chosenItemTpl, | ||||
|                     settings.rootEquipmentSlot | ||||
|                 ); | ||||
|                 if (compatabilityResult.incompatible)  | ||||
|                 { | ||||
|                     // Tried x different items that failed, stop
 | ||||
|                     if (attempts > maxAttempts)  | ||||
|                     { | ||||
|                         return false; | ||||
|                     } | ||||
|                     attempts++; | ||||
|                 } | ||||
|                 else  | ||||
|                 { | ||||
|                     // Success
 | ||||
|                     found = true; | ||||
|                     pickedItemDb = dbResult[1]; | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             // Create root item
 | ||||
|             const id = this.hashUtil.generate(); | ||||
|             const item = { | ||||
|                 _id: id, | ||||
|                 _tpl: pickedItemDb._id, | ||||
|                 parentId: settings.inventory.equipment, | ||||
|                 slotId: settings.rootEquipmentSlot, | ||||
|                 ...this.botGeneratorHelper.generateExtraPropertiesForItem(pickedItemDb, settings.botData.role) | ||||
|             }; | ||||
| 
 | ||||
|             const botEquipBlacklist = this.botEquipmentFilterService.getBotEquipmentBlacklist( | ||||
|                 settings.botData.equipmentRole, | ||||
|                 settings.generatingPlayerLevel | ||||
|             ); | ||||
| 
 | ||||
|             // Edge case: Filter the armor items mod pool if bot exists in config dict + config has armor slot
 | ||||
|             if ( | ||||
|                 this.botConfig.equipment[settings.botData.equipmentRole] && | ||||
|                 randomisationDetails?.randomisedArmorSlots?.includes(settings.rootEquipmentSlot) | ||||
|             )  | ||||
|             { | ||||
|                 // Filter out mods from relevant blacklist
 | ||||
|                 modPool[pickedItemDb._id] = this.getFilteredDynamicModsForItem( | ||||
|                     pickedItemDb._id, | ||||
|                     botEquipBlacklist.equipment | ||||
|                 ); | ||||
|             } | ||||
| 
 | ||||
|             // Does item have slots for sub-mods to be inserted into
 | ||||
|             if (pickedItemDb._props.Slots?.length > 0 && !settings.generateModsBlacklist?.includes(pickedItemDb._id))  | ||||
|             { | ||||
|                 const childItemsToAdd = this.botEquipmentModGenerator.generateModsForEquipment( | ||||
|                     [item], | ||||
|                     id, | ||||
|                     pickedItemDb, | ||||
|                     settings, | ||||
|                     botEquipBlacklist | ||||
|                 ); | ||||
|                 settings.inventory.items.push(...childItemsToAdd); | ||||
|             }  | ||||
|             else  | ||||
|             { | ||||
|                 // No slots, add root item only
 | ||||
|                 settings.inventory.items.push(item); | ||||
|             } | ||||
| 
 | ||||
|             return true; | ||||
|         } | ||||
| 
 | ||||
|         return false; | ||||
|     } | ||||
| 
 | ||||
|     protected override generateAndAddWeaponsToBot( | ||||
|         templateInventory: IInventory,  | ||||
|         equipmentChances: IChances,  | ||||
|         sessionId: string,  | ||||
|         botInventory: PmcInventory,  | ||||
|         botRole: string,  | ||||
|         isPmc: boolean,  | ||||
|         itemGenerationLimitsMinMax: IGeneration,  | ||||
|         botLevel: number | ||||
|     ): void  | ||||
|     { | ||||
|         const weaponSlotsToFill = this.getDesiredWeaponsForBot(equipmentChances); | ||||
|         let hasBothPrimary = false; | ||||
|         if (weaponSlotsToFill[0].shouldSpawn && weaponSlotsToFill[1].shouldSpawn) | ||||
|         { | ||||
|             hasBothPrimary = true; | ||||
|         } | ||||
|         for (const weaponSlot of weaponSlotsToFill)  | ||||
|         { | ||||
|             // Add weapon to bot if true and bot json has something to put into the slot
 | ||||
|             if (weaponSlot.shouldSpawn && Object.keys(templateInventory.equipment[weaponSlot.slot]).length)  | ||||
|             { | ||||
|                 this.apbsAddWeaponAndMagazinesToInventory( | ||||
|                     sessionId, | ||||
|                     weaponSlot, | ||||
|                     templateInventory, | ||||
|                     botInventory, | ||||
|                     equipmentChances, | ||||
|                     botRole, | ||||
|                     isPmc, | ||||
|                     itemGenerationLimitsMinMax, | ||||
|                     botLevel, | ||||
|                     hasBothPrimary | ||||
|                 ); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private apbsAddWeaponAndMagazinesToInventory( | ||||
|         sessionId: string, | ||||
|         weaponSlot: { slot: EquipmentSlots; shouldSpawn: boolean }, | ||||
|         templateInventory: IInventory, | ||||
|         botInventory: PmcInventory, | ||||
|         equipmentChances: IChances, | ||||
|         botRole: string, | ||||
|         isPmc: boolean, | ||||
|         itemGenerationWeights: IGeneration, | ||||
|         botLevel: number, | ||||
|         hasBothPrimary: boolean | ||||
|     ): void  | ||||
|     { | ||||
|         const generatedWeapon = this.apbsBotWeaponGenerator.apbsGenerateRandomWeapon( | ||||
|             sessionId, | ||||
|             weaponSlot.slot, | ||||
|             templateInventory, | ||||
|             botInventory.equipment, | ||||
|             equipmentChances.weaponMods, | ||||
|             botRole, | ||||
|             isPmc, | ||||
|             botLevel, | ||||
|             hasBothPrimary | ||||
|         ); | ||||
| 
 | ||||
|         botInventory.items.push(...generatedWeapon.weapon); | ||||
|          | ||||
|         if (this.raidInformation.isBotEnabled(botRole) && ModConfig.config.enableBotsToRollAmmoAgain) | ||||
|         { | ||||
|             this.apbsBotWeaponGenerator.apbsAddExtraMagazinesToInventory( | ||||
|                 generatedWeapon, | ||||
|                 itemGenerationWeights.items.magazines, | ||||
|                 botInventory, | ||||
|                 botRole, | ||||
|                 botLevel | ||||
|             ); | ||||
|             return; | ||||
|         } | ||||
|         this.botWeaponGenerator.addExtraMagazinesToInventory( | ||||
|             generatedWeapon, | ||||
|             itemGenerationWeights.items.magazines, | ||||
|             botInventory, | ||||
|             botRole | ||||
|         ); | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,474 @@ | |||
| import { inject, injectable } from "tsyringe"; | ||||
| 
 | ||||
| import { ItemHelper } from "@spt/helpers/ItemHelper"; | ||||
| import { IBotType, IGenerationWeightingItems } from "@spt/models/eft/common/tables/IBotType"; | ||||
| 
 | ||||
| import { APBSEquipmentGetter } from "../Utils/APBSEquipmentGetter"; | ||||
| import { APBSTierGetter } from "../Utils/APBSTierGetter"; | ||||
| import { RagfairPriceService } from "@spt/services/RagfairPriceService"; | ||||
| import { PMCLootGenerator } from "@spt/generators/PMCLootGenerator"; | ||||
| import { BotLootCacheService } from "@spt/services/BotLootCacheService"; | ||||
| import { ILogger } from "@spt/models/spt/utils/ILogger"; | ||||
| import { DatabaseServer } from "@spt/servers/DatabaseServer"; | ||||
| import { LocalisationService } from "@spt/services/LocalisationService"; | ||||
| import { ICloner } from "@spt/utils/cloners/ICloner"; | ||||
| import { BaseClasses } from "@spt/models/enums/BaseClasses"; | ||||
| import { IBotLootCache, LootCacheType } from "@spt/models/spt/bots/IBotLootCache"; | ||||
| import { RaidInformation } from "../Globals/RaidInformation"; | ||||
| import { APBSLogger } from "../Utils/APBSLogger"; | ||||
| import { Logging } from "../Enums/Logging"; | ||||
| 
 | ||||
| @injectable() | ||||
| export class APBSBotLootCacheService extends BotLootCacheService | ||||
| { | ||||
|     protected apbsLootCache: Record<string, IBotLootCache>; | ||||
|      | ||||
|     constructor( | ||||
|         @inject("PrimaryLogger") protected logger: ILogger, | ||||
|         @inject("ItemHelper") protected itemHelper: ItemHelper, | ||||
|         @inject("DatabaseServer") protected databaseServer: DatabaseServer, | ||||
|         @inject("PMCLootGenerator") protected pmcLootGenerator: PMCLootGenerator, | ||||
|         @inject("LocalisationService") protected localisationService: LocalisationService, | ||||
|         @inject("RagfairPriceService") protected ragfairPriceService: RagfairPriceService, | ||||
|         @inject("PrimaryCloner") protected cloner: ICloner, | ||||
|         @inject("APBSEquipmentGetter") protected apbsEquipmentGetter: APBSEquipmentGetter, | ||||
|         @inject("APBSTierGetter") protected apbsTierGetter: APBSTierGetter, | ||||
|         @inject("RaidInformation") protected raidInformation: RaidInformation, | ||||
|         @inject("APBSLogger") protected apbsLogger: APBSLogger | ||||
|     ) | ||||
|     { | ||||
|         super(logger,  | ||||
|             itemHelper,  | ||||
|             databaseServer,  | ||||
|             pmcLootGenerator,  | ||||
|             localisationService,  | ||||
|             ragfairPriceService,  | ||||
|             cloner)             | ||||
|         this.apbsClearCache(); | ||||
|         this.clearCache(); | ||||
|     } | ||||
|      | ||||
|     public apbsClearCache(): void  | ||||
|     { | ||||
|         this.apbsLootCache = {}; | ||||
|     } | ||||
| 
 | ||||
|     public apbsBotRoleExistsInCache(combinedBotRoleTier: string): boolean  | ||||
|     { | ||||
|         return !!this.apbsLootCache[combinedBotRoleTier]; | ||||
|     } | ||||
| 
 | ||||
|     public apbsInitCacheForBotRole(combinedBotRoleTier: string): void  | ||||
|     { | ||||
|         this.apbsLootCache[combinedBotRoleTier] = { | ||||
|             backpackLoot: {}, | ||||
|             pocketLoot: {}, | ||||
|             vestLoot: {}, | ||||
|             secureLoot: {}, | ||||
|             combinedPoolLoot: {}, | ||||
| 
 | ||||
|             specialItems: {}, | ||||
|             grenadeItems: {}, | ||||
|             drugItems: {}, | ||||
|             foodItems: {}, | ||||
|             drinkItems: {}, | ||||
|             currencyItems: {}, | ||||
|             healingItems: {}, | ||||
|             stimItems: {} | ||||
|         }; | ||||
|     } | ||||
| 
 | ||||
|     public apbsGetLootFromCache( | ||||
|         botRole: string, | ||||
|         isPmc: boolean, | ||||
|         lootType: LootCacheType, | ||||
|         botJsonTemplate: IBotType, | ||||
|         botLevel: number | ||||
|     ): Record<string, number>  | ||||
|     { | ||||
|         const tierInfo = this.apbsTierGetter.getTierByLevel(botLevel).toString(); | ||||
|         const combinedBotRoleTier = botRole + tierInfo; | ||||
|         if (!this.apbsBotRoleExistsInCache(combinedBotRoleTier)) | ||||
|         { | ||||
|             this.apbsInitCacheForBotRole(combinedBotRoleTier); | ||||
| 
 | ||||
|             this.apbsAddLootToCache(botRole, isPmc, botJsonTemplate, botLevel); | ||||
|         } | ||||
| 
 | ||||
|         let result = undefined; | ||||
|         switch (lootType)  | ||||
|         { | ||||
|             case LootCacheType.SPECIAL: | ||||
|                 result = this.apbsLootCache[combinedBotRoleTier].specialItems; | ||||
|                 break; | ||||
|             case LootCacheType.BACKPACK: | ||||
|                 result = this.apbsLootCache[combinedBotRoleTier].backpackLoot; | ||||
|                 break; | ||||
|             case LootCacheType.POCKET: | ||||
|                 result = this.apbsLootCache[combinedBotRoleTier].pocketLoot; | ||||
|                 break; | ||||
|             case LootCacheType.VEST: | ||||
|                 result = this.apbsLootCache[combinedBotRoleTier].vestLoot; | ||||
|                 break; | ||||
|             case LootCacheType.SECURE: | ||||
|                 result = this.apbsLootCache[combinedBotRoleTier].secureLoot; | ||||
|                 break; | ||||
|             case LootCacheType.COMBINED: | ||||
|                 result = this.apbsLootCache[combinedBotRoleTier].combinedPoolLoot; | ||||
|                 break; | ||||
|             case LootCacheType.HEALING_ITEMS: | ||||
|                 result = this.apbsLootCache[combinedBotRoleTier].healingItems; | ||||
|                 break; | ||||
|             case LootCacheType.GRENADE_ITEMS: | ||||
|                 result = this.apbsLootCache[combinedBotRoleTier].grenadeItems; | ||||
|                 break; | ||||
|             case LootCacheType.DRUG_ITEMS: | ||||
|                 result = this.apbsLootCache[combinedBotRoleTier].drugItems; | ||||
|                 break; | ||||
|             case LootCacheType.FOOD_ITEMS: | ||||
|                 result = this.apbsLootCache[combinedBotRoleTier].foodItems; | ||||
|                 break; | ||||
|             case LootCacheType.DRINK_ITEMS: | ||||
|                 result = this.apbsLootCache[combinedBotRoleTier].drinkItems; | ||||
|                 break; | ||||
|             case LootCacheType.CURRENCY_ITEMS: | ||||
|                 result = this.apbsLootCache[combinedBotRoleTier].currencyItems; | ||||
|                 break; | ||||
|             case LootCacheType.STIM_ITEMS: | ||||
|                 result = this.apbsLootCache[combinedBotRoleTier].stimItems; | ||||
|                 break; | ||||
|             default: | ||||
|                 this.logger.error( | ||||
|                     this.localisationService.getText("bot-loot_type_not_found", { | ||||
|                         lootType: lootType, | ||||
|                         botRole: botRole, | ||||
|                         isPmc: isPmc | ||||
|                     }) | ||||
|                 ); | ||||
|                 break; | ||||
|         } | ||||
|          | ||||
|         return this.cloner.clone(result); | ||||
|     } | ||||
|      | ||||
|     public apbsAddLootToCache(botRole: string, isPmc: boolean, botJsonTemplate: IBotType, botLevel: number): void | ||||
|     { | ||||
|         const tierInfo = this.apbsTierGetter.getTierByLevel(botLevel); | ||||
|         const combinedBotRoleTier = botRole + tierInfo; | ||||
|         const chances = this.apbsEquipmentGetter.getSpawnChancesByBotRole(botRole, tierInfo); | ||||
|         let realWhitelist: IGenerationWeightingItems = chances.generation.items; | ||||
|          | ||||
|         if (!this.raidInformation.isBotEnabled(botRole)) | ||||
|         { | ||||
|             realWhitelist = botJsonTemplate.generation.items; | ||||
|         } | ||||
|          | ||||
|         // the full pool of loot we use to create the various sub-categories with
 | ||||
|         const lootPool = botJsonTemplate.inventory.items; | ||||
| 
 | ||||
|         // Flatten all individual slot loot pools into one big pool, while filtering out potentially missing templates
 | ||||
|         const specialLootPool: Record<string, number> = {}; | ||||
|         const backpackLootPool: Record<string, number> = {}; | ||||
|         const pocketLootPool: Record<string, number> = {}; | ||||
|         const vestLootPool: Record<string, number> = {}; | ||||
|         const secureLootTPool: Record<string, number> = {}; | ||||
|         const combinedLootPool: Record<string, number> = {}; | ||||
| 
 | ||||
|         if (isPmc)  | ||||
|         { | ||||
|             // Replace lootPool from bot json with our own generated list for PMCs
 | ||||
|             lootPool.Backpack = this.cloner.clone(this.pmcLootGenerator.generatePMCBackpackLootPool(botRole)); | ||||
|             lootPool.Pockets = this.cloner.clone(this.pmcLootGenerator.generatePMCPocketLootPool(botRole)); | ||||
|             lootPool.TacticalVest = this.cloner.clone(this.pmcLootGenerator.generatePMCVestLootPool(botRole)); | ||||
|         } | ||||
| 
 | ||||
|         // Backpack/Pockets etc
 | ||||
|         for (const [slot, pool] of Object.entries(lootPool))  | ||||
|         { | ||||
|             // No items to add, skip
 | ||||
|             if (Object.keys(pool).length === 0) | ||||
|             { | ||||
|                 continue; | ||||
|             } | ||||
| 
 | ||||
|             // Sort loot pool into separate buckets
 | ||||
|             switch (slot.toLowerCase())  | ||||
|             { | ||||
|                 case "specialloot": | ||||
|                     this.addItemsToPool(specialLootPool, pool); | ||||
|                     break; | ||||
|                 case "pockets": | ||||
|                     this.addItemsToPool(pocketLootPool, pool); | ||||
|                     break; | ||||
|                 case "tacticalvest": | ||||
|                     this.addItemsToPool(vestLootPool, pool); | ||||
|                     break; | ||||
|                 case "securedcontainer": | ||||
|                     this.addItemsToPool(secureLootTPool, pool); | ||||
|                     break; | ||||
|                 case "backpack": | ||||
|                     this.addItemsToPool(backpackLootPool, pool); | ||||
|                     break; | ||||
|                 default: | ||||
|                     this.logger.warning(`How did you get here ${slot}`); | ||||
|             } | ||||
| 
 | ||||
|             // Add all items (if any) to combined pool (excluding secure)
 | ||||
|             if (Object.keys(pool).length > 0 && slot.toLowerCase() !== "securedcontainer")  | ||||
|             { | ||||
|                 this.addItemsToPool(combinedLootPool, pool); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         // Assign whitelisted special items to bot if any exist
 | ||||
|         const specialLootItems: Record<string, number> = | ||||
|             Object.keys(realWhitelist.specialItems.whitelist)?.length > 0 | ||||
|                 ? realWhitelist.specialItems.whitelist | ||||
|                 : {}; | ||||
| 
 | ||||
|         // no whitelist, find and assign from combined item pool
 | ||||
|         if (Object.keys(specialLootItems).length === 0)  | ||||
|         { | ||||
|             for (const [tpl, weight] of Object.entries(specialLootPool))  | ||||
|             { | ||||
|                 const itemTemplate = this.itemHelper.getItem(tpl)[1]; | ||||
|                 if (!(this.isBulletOrGrenade(itemTemplate._props) || this.isMagazine(itemTemplate._props)))  | ||||
|                 { | ||||
|                     specialLootItems[tpl] = weight; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         // Assign whitelisted healing items to bot if any exist
 | ||||
|         const healingItems: Record<string, number> = | ||||
|             Object.keys(realWhitelist.healing.whitelist)?.length > 0 | ||||
|                 ? realWhitelist.healing.whitelist | ||||
|                 : {}; | ||||
| 
 | ||||
|         // No whitelist, find and assign from combined item pool
 | ||||
|         if (Object.keys(healingItems).length === 0)  | ||||
|         { | ||||
|             for (const [tpl, weight] of Object.entries(combinedLootPool))  | ||||
|             { | ||||
|                 const itemTemplate = this.itemHelper.getItem(tpl)[1]; | ||||
|                 if ( | ||||
|                     this.isMedicalItem(itemTemplate._props) && | ||||
|                     itemTemplate._parent !== BaseClasses.STIMULATOR && | ||||
|                     itemTemplate._parent !== BaseClasses.DRUGS | ||||
|                 )  | ||||
|                 { | ||||
|                     healingItems[tpl] = weight; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         // Assign whitelisted drugs to bot if any exist
 | ||||
|         const drugItems: Record<string, number> = | ||||
|             Object.keys(realWhitelist.drugs.whitelist)?.length > 0 | ||||
|                 ? realWhitelist.drugs.whitelist | ||||
|                 : {}; | ||||
| 
 | ||||
|         // no drugs whitelist, find and assign from combined item pool
 | ||||
|         if (Object.keys(drugItems).length === 0)  | ||||
|         { | ||||
|             for (const [tpl, weight] of Object.entries(combinedLootPool))  | ||||
|             { | ||||
|                 const itemTemplate = this.itemHelper.getItem(tpl)[1]; | ||||
|                 if (this.isMedicalItem(itemTemplate._props) && itemTemplate._parent === BaseClasses.DRUGS)  | ||||
|                 { | ||||
|                     drugItems[tpl] = weight; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         // Assign whitelisted food to bot if any exist
 | ||||
|         const foodItems: Record<string, number> = | ||||
|             Object.keys(realWhitelist.food.whitelist)?.length > 0 | ||||
|                 ? realWhitelist.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<string, number> = | ||||
|             Object.keys(realWhitelist.food.whitelist)?.length > 0 | ||||
|                 ? realWhitelist.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<string, number> = | ||||
|             Object.keys(realWhitelist.currency.whitelist)?.length > 0 | ||||
|                 ? realWhitelist.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<string, number> = | ||||
|             Object.keys(realWhitelist.stims.whitelist)?.length > 0 | ||||
|                 ? realWhitelist.stims.whitelist | ||||
|                 : {}; | ||||
| 
 | ||||
|         // No whitelist, find and assign from combined item pool
 | ||||
|         if (Object.keys(stimItems).length === 0)  | ||||
|         { | ||||
|             for (const [tpl, weight] of Object.entries(combinedLootPool))  | ||||
|             { | ||||
|                 const itemTemplate = this.itemHelper.getItem(tpl)[1]; | ||||
|                 if (this.isMedicalItem(itemTemplate._props) && itemTemplate._parent === BaseClasses.STIMULATOR)  | ||||
|                 { | ||||
|                     stimItems[tpl] = weight; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         // Assign whitelisted grenades to bot if any exist
 | ||||
|         const grenadeItems: Record<string, number> = | ||||
|             Object.keys(realWhitelist.grenades.whitelist)?.length > 0 | ||||
|                 ? realWhitelist.grenades.whitelist | ||||
|                 : {}; | ||||
| 
 | ||||
|         // no whitelist, find and assign from combined item pool
 | ||||
|         if (Object.keys(grenadeItems).length === 0)  | ||||
|         { | ||||
|             for (const [tpl, weight] of Object.entries(combinedLootPool))  | ||||
|             { | ||||
|                 const itemTemplate = this.itemHelper.getItem(tpl)[1]; | ||||
|                 if (this.isGrenade(itemTemplate._props))  | ||||
|                 { | ||||
|                     grenadeItems[tpl] = weight; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         // Get backpack loot (excluding magazines, bullets, grenades, drink, food and healing/stim items)
 | ||||
|         const filteredBackpackItems = {}; | ||||
|         for (const itemKey of Object.keys(backpackLootPool))  | ||||
|         { | ||||
|             const itemResult = this.itemHelper.getItem(itemKey); | ||||
|             if (!itemResult[0])  | ||||
|             { | ||||
|                 continue; | ||||
|             } | ||||
|             const itemTemplate = itemResult[1]; | ||||
|             if ( | ||||
|                 this.isBulletOrGrenade(itemTemplate._props) || | ||||
|                 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
 | ||||
|                 continue; | ||||
|             } | ||||
| 
 | ||||
|             filteredBackpackItems[itemKey] = backpackLootPool[itemKey]; | ||||
|         } | ||||
| 
 | ||||
|         // Get pocket loot (excluding magazines, bullets, grenades, drink, food medical and healing/stim items)
 | ||||
|         const filteredPocketItems = {}; | ||||
|         for (const itemKey of Object.keys(pocketLootPool))  | ||||
|         { | ||||
|             const itemResult = this.itemHelper.getItem(itemKey); | ||||
|             if (!itemResult[0])  | ||||
|             { | ||||
|                 continue; | ||||
|             } | ||||
|             const itemTemplate = itemResult[1]; | ||||
|             if ( | ||||
|                 this.isBulletOrGrenade(itemTemplate._props) || | ||||
|                 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
 | ||||
|             )  | ||||
|             { | ||||
|                 continue; | ||||
|             } | ||||
| 
 | ||||
|             filteredPocketItems[itemKey] = pocketLootPool[itemKey]; | ||||
|         } | ||||
| 
 | ||||
|         // Get vest loot (excluding magazines, bullets, grenades, medical and healing/stim items)
 | ||||
|         const filteredVestItems = {}; | ||||
|         for (const itemKey of Object.keys(vestLootPool))  | ||||
|         { | ||||
|             const itemResult = this.itemHelper.getItem(itemKey); | ||||
|             if (!itemResult[0])  | ||||
|             { | ||||
|                 continue; | ||||
|             } | ||||
|             const itemTemplate = itemResult[1]; | ||||
|             if ( | ||||
|                 this.isBulletOrGrenade(itemTemplate._props) || | ||||
|                 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; | ||||
|             } | ||||
| 
 | ||||
|             filteredVestItems[itemKey] = vestLootPool[itemKey]; | ||||
|         } | ||||
| 
 | ||||
|         this.apbsLootCache[combinedBotRoleTier].healingItems = healingItems; | ||||
|         this.apbsLootCache[combinedBotRoleTier].drugItems = drugItems; | ||||
|         this.apbsLootCache[combinedBotRoleTier].foodItems = foodItems; | ||||
|         this.apbsLootCache[combinedBotRoleTier].drinkItems = drinkItems; | ||||
|         this.apbsLootCache[combinedBotRoleTier].currencyItems = currencyItems; | ||||
|         this.apbsLootCache[combinedBotRoleTier].stimItems = stimItems; | ||||
|         this.apbsLootCache[combinedBotRoleTier].grenadeItems = grenadeItems; | ||||
| 
 | ||||
|         this.apbsLootCache[combinedBotRoleTier].specialItems = specialLootItems; | ||||
|         this.apbsLootCache[combinedBotRoleTier].backpackLoot = filteredBackpackItems; | ||||
|         this.apbsLootCache[combinedBotRoleTier].pocketLoot = filteredPocketItems; | ||||
|         this.apbsLootCache[combinedBotRoleTier].vestLoot = filteredVestItems; | ||||
|         this.apbsLootCache[combinedBotRoleTier].secureLoot = secureLootTPool; | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,418 @@ | |||
| import { inject, injectable } from "tsyringe"; | ||||
| 
 | ||||
| import { BotWeaponGenerator } from "@spt/generators/BotWeaponGenerator"; | ||||
| import { BotGeneratorHelper } from "@spt/helpers/BotGeneratorHelper"; | ||||
| import { BotHelper } from "@spt/helpers/BotHelper"; | ||||
| import { HandbookHelper } from "@spt/helpers/HandbookHelper"; | ||||
| import { InventoryHelper } from "@spt/helpers/InventoryHelper"; | ||||
| import { ItemHelper } from "@spt/helpers/ItemHelper"; | ||||
| import { WeightedRandomHelper } from "@spt/helpers/WeightedRandomHelper"; | ||||
| import { IInventory as PmcInventory } from "@spt/models/eft/common/tables/IBotBase"; | ||||
| import { IGenerationWeightingItems, IBotType } from "@spt/models/eft/common/tables/IBotType"; | ||||
| import { EquipmentSlots } from "@spt/models/enums/EquipmentSlots"; | ||||
| import { LootCacheType } from "@spt/models/spt/bots/IBotLootCache"; | ||||
| import { ILogger } from "@spt/models/spt/utils/ILogger"; | ||||
| import { ConfigServer } from "@spt/servers/ConfigServer"; | ||||
| import { BotLootCacheService } from "@spt/services/BotLootCacheService"; | ||||
| import { DatabaseService } from "@spt/services/DatabaseService"; | ||||
| import { LocalisationService } from "@spt/services/LocalisationService"; | ||||
| import { ICloner } from "@spt/utils/cloners/ICloner"; | ||||
| import { HashUtil } from "@spt/utils/HashUtil"; | ||||
| import { RandomUtil } from "@spt/utils/RandomUtil"; | ||||
| import { BotLootGenerator } from "@spt/generators/BotLootGenerator"; | ||||
| 
 | ||||
| import { APBSEquipmentGetter } from "../Utils/APBSEquipmentGetter"; | ||||
| import { APBSTierGetter } from "../Utils/APBSTierGetter"; | ||||
| import { APBSBotLootCacheService } from "./APBSBotLootCacheService"; | ||||
| import { RaidInformation } from "../Globals/RaidInformation"; | ||||
| import { APBSLogger } from "../Utils/APBSLogger"; | ||||
| import { Logging } from "../Enums/Logging"; | ||||
| import { ITemplateItem } from "@spt/models/eft/common/tables/ITemplateItem"; | ||||
| import { IItemSpawnLimitSettings } from "@spt/models/spt/bots/IItemSpawnLimitSettings"; | ||||
| 
 | ||||
| /** Handle profile related client events */ | ||||
| @injectable() | ||||
| export class APBSBotLootGenerator extends BotLootGenerator | ||||
| { | ||||
|     constructor( | ||||
|         @inject("PrimaryLogger") protected logger: ILogger, | ||||
|         @inject("HashUtil") protected hashUtil: HashUtil, | ||||
|         @inject("RandomUtil") protected randomUtil: RandomUtil, | ||||
|         @inject("ItemHelper") protected itemHelper: ItemHelper, | ||||
|         @inject("InventoryHelper") protected inventoryHelper: InventoryHelper, | ||||
|         @inject("DatabaseService") protected databaseService: DatabaseService, | ||||
|         @inject("HandbookHelper") protected handbookHelper: HandbookHelper, | ||||
|         @inject("BotGeneratorHelper") protected botGeneratorHelper: BotGeneratorHelper, | ||||
|         @inject("BotWeaponGenerator") protected botWeaponGenerator: BotWeaponGenerator, | ||||
|         @inject("WeightedRandomHelper") protected weightedRandomHelper: WeightedRandomHelper, | ||||
|         @inject("BotHelper") protected botHelper: BotHelper, | ||||
|         @inject("BotLootCacheService") protected botLootCacheService: BotLootCacheService, | ||||
|         @inject("LocalisationService") protected localisationService: LocalisationService, | ||||
|         @inject("ConfigServer") protected configServer: ConfigServer, | ||||
|         @inject("PrimaryCloner") protected cloner: ICloner, | ||||
|         @inject("APBSEquipmentGetter") protected apbsEquipmentGetter: APBSEquipmentGetter, | ||||
|         @inject("APBSTierGetter") protected apbsTierGetter: APBSTierGetter, | ||||
|         @inject("RaidInformation") protected raidInformation: RaidInformation, | ||||
|         @inject("APBSBotLootCacheService") protected apbsBotLootCacheService: APBSBotLootCacheService, | ||||
|         @inject("APBSLogger") protected apbsLogger: APBSLogger | ||||
|     ) | ||||
|     { | ||||
|         super(logger,  | ||||
|             hashUtil,  | ||||
|             randomUtil,  | ||||
|             itemHelper,  | ||||
|             inventoryHelper,  | ||||
|             databaseService,  | ||||
|             handbookHelper,  | ||||
|             botGeneratorHelper,  | ||||
|             botWeaponGenerator,  | ||||
|             weightedRandomHelper, | ||||
|             botHelper,  | ||||
|             botLootCacheService,  | ||||
|             localisationService,  | ||||
|             configServer, | ||||
|             cloner) | ||||
|     } | ||||
| 
 | ||||
|     public override generateLoot( | ||||
|         sessionId: string, | ||||
|         botJsonTemplate: IBotType, | ||||
|         isPmc: boolean, | ||||
|         botRole: string, | ||||
|         botInventory: PmcInventory, | ||||
|         botLevel: number | ||||
|     ): void | ||||
|     { | ||||
|         // Limits on item types to be added as loot
 | ||||
|         const tierInfo = this.apbsTierGetter.getTierByLevel(botLevel); | ||||
|         const chances = this.apbsEquipmentGetter.getSpawnChancesByBotRole(botRole, tierInfo); | ||||
|         let itemCounts: IGenerationWeightingItems = chances.generation.items; | ||||
|         let useOriginalLootCache = false; | ||||
| 
 | ||||
|         if (!this.raidInformation.isBotEnabled(botRole)) | ||||
|         { | ||||
|             itemCounts = botJsonTemplate.generation.items; | ||||
|             useOriginalLootCache = true; | ||||
|         } | ||||
| 
 | ||||
|         if ( | ||||
|             !itemCounts.backpackLoot.weights | ||||
|             || !itemCounts.pocketLoot.weights | ||||
|             || !itemCounts.vestLoot.weights | ||||
|             || !itemCounts.specialItems.weights | ||||
|             || !itemCounts.healing.weights | ||||
|             || !itemCounts.drugs.weights | ||||
|             || !itemCounts.food.weights | ||||
|             || !itemCounts.drink.weights | ||||
|             || !itemCounts.currency.weights | ||||
|             || !itemCounts.stims.weights | ||||
|             || !itemCounts.grenades.weights | ||||
|         ) | ||||
|         { | ||||
|             this.logger.warning(this.localisationService.getText("bot-unable_to_generate_bot_loot", botRole)); | ||||
| 
 | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         let backpackLootCount = Number( | ||||
|             this.weightedRandomHelper.getWeightedValue<number>(itemCounts.backpackLoot.weights) | ||||
|         ); | ||||
|         let pocketLootCount = Number(this.weightedRandomHelper.getWeightedValue<number>(itemCounts.pocketLoot.weights)); | ||||
|         let vestLootCount = this.weightedRandomHelper.getWeightedValue<number>(itemCounts.vestLoot.weights); | ||||
|         const specialLootItemCount = Number(this.weightedRandomHelper.getWeightedValue<number>(itemCounts.specialItems.weights)); | ||||
|         const healingItemCount = Number(this.weightedRandomHelper.getWeightedValue<number>(itemCounts.healing.weights)); | ||||
|         const drugItemCount = Number(this.weightedRandomHelper.getWeightedValue<number>(itemCounts.drugs.weights)); | ||||
| 
 | ||||
|         const foodItemCount = Number(this.weightedRandomHelper.getWeightedValue<number>(itemCounts.food.weights)); | ||||
|         const drinkItemCount = Number(this.weightedRandomHelper.getWeightedValue<number>(itemCounts.drink.weights)); | ||||
| 
 | ||||
|         let currencyItemCount = Number(this.weightedRandomHelper.getWeightedValue<number>(itemCounts.currency.weights)); | ||||
| 
 | ||||
|         const stimItemCount = Number(this.weightedRandomHelper.getWeightedValue<number>(itemCounts.stims.weights)); | ||||
|         const grenadeCount = Number(this.weightedRandomHelper.getWeightedValue<number>(itemCounts.grenades.weights)); | ||||
| 
 | ||||
|         // If bot has been flagged as not having loot, set below counts to 0
 | ||||
|         if (this.botConfig.disableLootOnBotTypes?.includes(botRole.toLowerCase())) | ||||
|         { | ||||
|             backpackLootCount = 0; | ||||
|             pocketLootCount = 0; | ||||
|             vestLootCount = 0; | ||||
|             currencyItemCount = 0; | ||||
|         } | ||||
| 
 | ||||
|         // Forced pmc healing loot into secure container
 | ||||
|         if (isPmc && this.pmcConfig.forceHealingItemsIntoSecure) | ||||
|         { | ||||
|             this.addForcedMedicalItemsToPmcSecure(botInventory, botRole); | ||||
|         } | ||||
| 
 | ||||
|         const botItemLimits = this.getItemSpawnLimitsForBot(botRole); | ||||
| 
 | ||||
|         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<string>(); | ||||
| 
 | ||||
|         // Special items
 | ||||
|         this.addLootFromPool( | ||||
|             useOriginalLootCache ? | ||||
|                 this.botLootCacheService.getLootFromCache(botRole, isPmc, LootCacheType.SPECIAL, botJsonTemplate) : | ||||
|                 this.apbsBotLootCacheService.apbsGetLootFromCache(botRole, isPmc, LootCacheType.SPECIAL, botJsonTemplate, botLevel), | ||||
|             containersBotHasAvailable, | ||||
|             specialLootItemCount, | ||||
|             botInventory, | ||||
|             botRole, | ||||
|             botItemLimits, | ||||
|             undefined, | ||||
|             undefined, | ||||
|             containersIdFull | ||||
|         ); | ||||
| 
 | ||||
|         // Healing items / Meds
 | ||||
|         this.addLootFromPool( | ||||
|             useOriginalLootCache ? | ||||
|                 this.botLootCacheService.getLootFromCache(botRole, isPmc, LootCacheType.HEALING_ITEMS, botJsonTemplate) :  | ||||
|                 this.apbsBotLootCacheService.apbsGetLootFromCache(botRole, isPmc, LootCacheType.HEALING_ITEMS, botJsonTemplate, botLevel), | ||||
|             containersBotHasAvailable, | ||||
|             healingItemCount, | ||||
|             botInventory, | ||||
|             botRole, | ||||
|             botItemLimits, | ||||
|             0, | ||||
|             isPmc, | ||||
|             containersIdFull | ||||
|         ); | ||||
| 
 | ||||
|         // Drugs
 | ||||
|         this.addLootFromPool( | ||||
|             useOriginalLootCache ? | ||||
|                 this.botLootCacheService.getLootFromCache(botRole, isPmc, LootCacheType.DRUG_ITEMS, botJsonTemplate) :  | ||||
|                 this.apbsBotLootCacheService.apbsGetLootFromCache(botRole, isPmc, LootCacheType.DRUG_ITEMS, botJsonTemplate, botLevel), | ||||
|             containersBotHasAvailable, | ||||
|             drugItemCount, | ||||
|             botInventory, | ||||
|             botRole, | ||||
|             botItemLimits, | ||||
|             0, | ||||
|             isPmc, | ||||
|             containersIdFull | ||||
|         ); | ||||
| 
 | ||||
|         // Food
 | ||||
|         this.addLootFromPool( | ||||
|             useOriginalLootCache ? | ||||
|                 this.botLootCacheService.getLootFromCache(botRole, isPmc, LootCacheType.FOOD_ITEMS, botJsonTemplate) :  | ||||
|                 this.apbsBotLootCacheService.apbsGetLootFromCache(botRole, isPmc, LootCacheType.FOOD_ITEMS, botJsonTemplate, botLevel), | ||||
|             containersBotHasAvailable, | ||||
|             foodItemCount, | ||||
|             botInventory, | ||||
|             botRole, | ||||
|             botItemLimits, | ||||
|             0, | ||||
|             isPmc, | ||||
|             containersIdFull | ||||
|         ); | ||||
| 
 | ||||
|         // Drink
 | ||||
|         this.addLootFromPool( | ||||
|             useOriginalLootCache ? | ||||
|                 this.botLootCacheService.getLootFromCache(botRole, isPmc, LootCacheType.DRINK_ITEMS, botJsonTemplate) :  | ||||
|                 this.apbsBotLootCacheService.apbsGetLootFromCache(botRole, isPmc, LootCacheType.DRINK_ITEMS, botJsonTemplate, botLevel), | ||||
|             containersBotHasAvailable, | ||||
|             drinkItemCount, | ||||
|             botInventory, | ||||
|             botRole, | ||||
|             botItemLimits, | ||||
|             0, | ||||
|             isPmc, | ||||
|             containersIdFull | ||||
|         ); | ||||
| 
 | ||||
|         // Currency
 | ||||
|         this.addLootFromPool( | ||||
|             useOriginalLootCache ? | ||||
|                 this.botLootCacheService.getLootFromCache(botRole, isPmc, LootCacheType.CURRENCY_ITEMS, botJsonTemplate) :  | ||||
|                 this.apbsBotLootCacheService.apbsGetLootFromCache(botRole, isPmc, LootCacheType.CURRENCY_ITEMS, botJsonTemplate, botLevel), | ||||
|             containersBotHasAvailable, | ||||
|             currencyItemCount, | ||||
|             botInventory, | ||||
|             botRole, | ||||
|             botItemLimits, | ||||
|             0, | ||||
|             isPmc, | ||||
|             containersIdFull | ||||
|         ); | ||||
| 
 | ||||
|         // Stims
 | ||||
|         this.addLootFromPool( | ||||
|             useOriginalLootCache ? | ||||
|                 this.botLootCacheService.getLootFromCache(botRole, isPmc, LootCacheType.STIM_ITEMS, botJsonTemplate) :  | ||||
|                 this.apbsBotLootCacheService.apbsGetLootFromCache(botRole, isPmc, LootCacheType.STIM_ITEMS, botJsonTemplate, botLevel), | ||||
|             containersBotHasAvailable, | ||||
|             stimItemCount, | ||||
|             botInventory, | ||||
|             botRole, | ||||
|             botItemLimits, | ||||
|             0, | ||||
|             isPmc, | ||||
|             containersIdFull | ||||
|         ); | ||||
| 
 | ||||
|         // Grenades
 | ||||
|         this.addLootFromPool( | ||||
|             useOriginalLootCache ? | ||||
|                 this.botLootCacheService.getLootFromCache(botRole, isPmc, LootCacheType.GRENADE_ITEMS, botJsonTemplate) :  | ||||
|                 this.apbsBotLootCacheService.apbsGetLootFromCache(botRole, isPmc, LootCacheType.GRENADE_ITEMS, botJsonTemplate, botLevel), | ||||
|             [EquipmentSlots.POCKETS, EquipmentSlots.TACTICAL_VEST], // Can't use containersBotHasEquipped as we dont want grenades added to backpack
 | ||||
|             grenadeCount, | ||||
|             botInventory, | ||||
|             botRole, | ||||
|             botItemLimits, | ||||
|             0, | ||||
|             isPmc, | ||||
|             containersIdFull | ||||
|         ); | ||||
| 
 | ||||
|         // Backpack - generate loot if they have one
 | ||||
|         if (containersBotHasAvailable.includes(EquipmentSlots.BACKPACK)) | ||||
|         { | ||||
|             // Add randomly generated weapon to PMC backpacks
 | ||||
|             if (isPmc && this.randomUtil.getChance100(this.pmcConfig.looseWeaponInBackpackChancePercent)) | ||||
|             { | ||||
|                 this.addLooseWeaponsToInventorySlot( | ||||
|                     sessionId, | ||||
|                     botInventory, | ||||
|                     EquipmentSlots.BACKPACK, | ||||
|                     botJsonTemplate.inventory, | ||||
|                     botJsonTemplate.chances.weaponMods, | ||||
|                     botRole, | ||||
|                     isPmc, | ||||
|                     botLevel, | ||||
|                     containersIdFull | ||||
|                 ); | ||||
|             } | ||||
| 
 | ||||
|             const backpackLootRoubleTotal = this.getBackpackRoubleTotalByLevel(botLevel, isPmc); | ||||
|             this.addLootFromPool( | ||||
|                 useOriginalLootCache ? | ||||
|                     this.botLootCacheService.getLootFromCache(botRole, isPmc, LootCacheType.BACKPACK, botJsonTemplate) :  | ||||
|                     this.apbsBotLootCacheService.apbsGetLootFromCache(botRole, isPmc, LootCacheType.BACKPACK, botJsonTemplate, botLevel), | ||||
|                 [EquipmentSlots.BACKPACK], | ||||
|                 backpackLootCount, | ||||
|                 botInventory, | ||||
|                 botRole, | ||||
|                 botItemLimits, | ||||
|                 backpackLootRoubleTotal, | ||||
|                 isPmc, | ||||
|                 containersIdFull | ||||
|             ); | ||||
|         } | ||||
| 
 | ||||
|         // TacticalVest - generate loot if they have one
 | ||||
|         if (containersBotHasAvailable.includes(EquipmentSlots.TACTICAL_VEST)) | ||||
|         { | ||||
|             // Vest
 | ||||
|             this.addLootFromPool( | ||||
|                 useOriginalLootCache ? | ||||
|                     this.botLootCacheService.getLootFromCache(botRole, isPmc, LootCacheType.VEST, botJsonTemplate) :  | ||||
|                     this.apbsBotLootCacheService.apbsGetLootFromCache(botRole, isPmc, LootCacheType.VEST, botJsonTemplate, botLevel), | ||||
|                 [EquipmentSlots.TACTICAL_VEST], | ||||
|                 vestLootCount, | ||||
|                 botInventory, | ||||
|                 botRole, | ||||
|                 botItemLimits, | ||||
|                 this.pmcConfig.maxVestLootTotalRub, | ||||
|                 isPmc, | ||||
|                 containersIdFull | ||||
|             ); | ||||
|         } | ||||
| 
 | ||||
|         // Pockets
 | ||||
|         this.addLootFromPool( | ||||
|             useOriginalLootCache ? | ||||
|                 this.botLootCacheService.getLootFromCache(botRole, isPmc, LootCacheType.POCKET, botJsonTemplate) :  | ||||
|                 this.apbsBotLootCacheService.apbsGetLootFromCache(botRole, isPmc, LootCacheType.POCKET, botJsonTemplate, botLevel), | ||||
|             [EquipmentSlots.POCKETS], | ||||
|             pocketLootCount, | ||||
|             botInventory, | ||||
|             botRole, | ||||
|             botItemLimits, | ||||
|             this.pmcConfig.maxPocketLootTotalRub, | ||||
|             isPmc, | ||||
|             containersIdFull | ||||
|         ); | ||||
| 
 | ||||
|         // Secure
 | ||||
| 
 | ||||
|         // only add if not a pmc or is pmc and flag is true
 | ||||
|         if (!isPmc || (isPmc && this.pmcConfig.addSecureContainerLootFromBotConfig)) | ||||
|         { | ||||
|             this.addLootFromPool( | ||||
|                 useOriginalLootCache ? | ||||
|                     this.botLootCacheService.getLootFromCache(botRole, isPmc, LootCacheType.SECURE, botJsonTemplate) :  | ||||
|                     this.apbsBotLootCacheService.apbsGetLootFromCache(botRole, isPmc, LootCacheType.SECURE, botJsonTemplate, botLevel), | ||||
|                 [EquipmentSlots.SECURED_CONTAINER], | ||||
|                 50, | ||||
|                 botInventory, | ||||
|                 botRole, | ||||
|                 undefined, | ||||
|                 -1, | ||||
|                 isPmc, | ||||
|                 containersIdFull | ||||
|             ); | ||||
|         } | ||||
|     }  | ||||
|      | ||||
|     protected override itemHasReachedSpawnLimit( | ||||
|         itemTemplate: ITemplateItem, | ||||
|         botRole: string, | ||||
|         itemSpawnLimits: IItemSpawnLimitSettings | ||||
|     ): boolean  | ||||
|     { | ||||
|         // PMCs and scavs have different sections of bot config for spawn limits
 | ||||
|         if (!!itemSpawnLimits && Object.keys(itemSpawnLimits.globalLimits).length === 0)  | ||||
|         { | ||||
|             // No items found in spawn limit, drop out
 | ||||
|             return false; | ||||
|         } | ||||
| 
 | ||||
|         // No spawn limits, skipping
 | ||||
|         if (!itemSpawnLimits)  | ||||
|         { | ||||
|             return false; | ||||
|         } | ||||
| 
 | ||||
|         const idToCheckFor = this.getMatchingIdFromSpawnLimits(itemTemplate, itemSpawnLimits.globalLimits); | ||||
|         if (!idToCheckFor)  | ||||
|         { | ||||
|             // ParentId or tplid not found in spawnLimits, not a spawn limited item, skip
 | ||||
|             return false; | ||||
|         } | ||||
| 
 | ||||
|         // Increment item count with this bot type
 | ||||
|         itemSpawnLimits.currentLimits[idToCheckFor]++; | ||||
| 
 | ||||
|         // Check if over limit
 | ||||
|         if (itemSpawnLimits.currentLimits[idToCheckFor] > itemSpawnLimits.globalLimits[idToCheckFor])  | ||||
|         { | ||||
|             // Prevent edge-case of small loot pools + code trying to add limited item over and over infinitely
 | ||||
|             if (itemSpawnLimits.currentLimits[idToCheckFor] > itemSpawnLimits.globalLimits[idToCheckFor] * 10)  | ||||
|             { | ||||
|                 this.logger.debug( | ||||
|                     this.localisationService.getText("bot-item_spawn_limit_reached_skipping_item", { | ||||
|                         botRole: botRole, | ||||
|                         itemName: itemTemplate._name, | ||||
|                         attempts: itemSpawnLimits.currentLimits[idToCheckFor] | ||||
|                     }) | ||||
|                 ); | ||||
| 
 | ||||
|                 return false; | ||||
|             } | ||||
| 
 | ||||
|             return true; | ||||
|         } | ||||
| 
 | ||||
|         return false; | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,394 @@ | |||
| import { inject, injectable, injectAll } from "tsyringe"; | ||||
| 
 | ||||
| import { DatabaseService } from "@spt/services/DatabaseService"; | ||||
| import { RandomUtil } from "@spt/utils/RandomUtil"; | ||||
| import { APBSLogger } from "../Utils/APBSLogger"; | ||||
| import { BotWeaponGenerator } from "@spt/generators/BotWeaponGenerator"; | ||||
| import { IInventory as PmcInventory } from "@spt/models/eft/common/tables/IBotBase"; | ||||
| import { IGenerationData, IInventory, IModsChances } from "@spt/models/eft/common/tables/IBotType"; | ||||
| import { WeightedRandomHelper } from "@spt/helpers/WeightedRandomHelper"; | ||||
| import { APBSTierGetter } from "../Utils/APBSTierGetter"; | ||||
| import { ILogger } from "@spt/models/spt/utils/ILogger"; | ||||
| import { ItemHelper } from "@spt/helpers/ItemHelper"; | ||||
| import { LocalisationService } from "@spt/services/LocalisationService"; | ||||
| import { IGenerateWeaponRequest } from "@spt/models/spt/bots/IGenerateWeaponRequest"; | ||||
| import { IGenerateWeaponResult } from "@spt/models/spt/bots/IGenerateWeaponResult"; | ||||
| import { HashUtil } from "@spt/utils/HashUtil"; | ||||
| import { ICloner } from "@spt/utils/cloners/ICloner"; | ||||
| import { ConfigServer } from "@spt/servers/ConfigServer"; | ||||
| import { IInventoryMagGen } from "@spt/generators/weapongen/IInventoryMagGen"; | ||||
| import { RepairService } from "@spt/services/RepairService"; | ||||
| import { BotWeaponModLimitService } from "@spt/services/BotWeaponModLimitService"; | ||||
| import { BotGeneratorHelper } from "@spt/helpers/BotGeneratorHelper"; | ||||
| import { BotEquipmentModGenerator } from "@spt/generators/BotEquipmentModGenerator"; | ||||
| import { BotWeaponGeneratorHelper } from "@spt/helpers/BotWeaponGeneratorHelper"; | ||||
| import { RaidInformation } from "../Globals/RaidInformation"; | ||||
| import { APBSEquipmentGetter } from "../Utils/APBSEquipmentGetter"; | ||||
| import { ModConfig } from "../Globals/ModConfig"; | ||||
| import { Logging } from "../Enums/Logging"; | ||||
| import { APBSTester } from "../Utils/APBSTester"; | ||||
| import { ModInformation } from "../Globals/ModInformation"; | ||||
| import { Money } from "@spt/models/enums/Money"; | ||||
| import { APBSBotEquipmentModGenerator } from "./APBSBotEquipmentModGenerator"; | ||||
| import { APBSInventoryMagGen } from "../InventoryMagGen/APBSInventoryMagGen"; | ||||
| import { APBSIInventoryMagGen } from "../InventoryMagGen/APBSIInventoryMagGen"; | ||||
| import { ITemplateItem } from "@spt/models/eft/common/tables/ITemplateItem"; | ||||
| 
 | ||||
| /** Handle profile related client events */ | ||||
| @injectable() | ||||
| export class APBSBotWeaponGenerator extends BotWeaponGenerator | ||||
| { | ||||
|     constructor( | ||||
|         @inject("PrimaryLogger") protected logger: ILogger, | ||||
|         @inject("HashUtil") protected hashUtil: HashUtil, | ||||
|         @inject("DatabaseService") protected databaseService: DatabaseService, | ||||
|         @inject("ItemHelper") protected itemHelper: ItemHelper, | ||||
|         @inject("WeightedRandomHelper") protected weightedRandomHelper: WeightedRandomHelper, | ||||
|         @inject("BotGeneratorHelper") protected botGeneratorHelper: BotGeneratorHelper, | ||||
|         @inject("RandomUtil") protected randomUtil: RandomUtil, | ||||
|         @inject("ConfigServer") protected configServer: ConfigServer, | ||||
|         @inject("BotWeaponGeneratorHelper") protected botWeaponGeneratorHelper: BotWeaponGeneratorHelper, | ||||
|         @inject("BotWeaponModLimitService") protected botWeaponModLimitService: BotWeaponModLimitService, | ||||
|         @inject("BotEquipmentModGenerator") protected botEquipmentModGenerator: BotEquipmentModGenerator, | ||||
|         @inject("LocalisationService") protected localisationService: LocalisationService, | ||||
|         @inject("RepairService") protected repairService: RepairService, | ||||
|         @injectAll("InventoryMagGen") protected inventoryMagGenComponents: IInventoryMagGen[], | ||||
|         @inject("PrimaryCloner") protected cloner: ICloner, | ||||
|         @inject("APBSLogger") protected apbsLogger: APBSLogger, | ||||
|         @inject("APBSTierGetter") protected apbsTierGetter: APBSTierGetter, | ||||
|         @inject("RaidInformation") protected raidInformation: RaidInformation, | ||||
|         @inject("APBSEquipmentGetter") protected apbsEquipmentGetter: APBSEquipmentGetter, | ||||
|         @inject("APBSTester") protected apbsTester: APBSTester, | ||||
|         @inject("APBSBotEquipmentModGenerator") protected apbsBotEquipmentModGenerator: APBSBotEquipmentModGenerator, | ||||
|         @inject("ModInformation") protected modInformation: ModInformation, | ||||
|         @injectAll("APBSInventoryMagGen") protected apbsInventoryMagGenComponents: APBSIInventoryMagGen[] | ||||
|     ) | ||||
|     { | ||||
|         super(logger,  | ||||
|             hashUtil,  | ||||
|             databaseService,  | ||||
|             itemHelper,  | ||||
|             weightedRandomHelper,  | ||||
|             botGeneratorHelper,  | ||||
|             randomUtil,  | ||||
|             configServer,  | ||||
|             botWeaponGeneratorHelper,  | ||||
|             botWeaponModLimitService, | ||||
|             botEquipmentModGenerator,  | ||||
|             localisationService,  | ||||
|             repairService,  | ||||
|             inventoryMagGenComponents, | ||||
|             cloner) | ||||
|     } | ||||
| 
 | ||||
|     public apbsGenerateRandomWeapon(sessionId: string, equipmentSlot: string, botTemplateInventory: IInventory, weaponParentId: string, modChances: IModsChances, botRole: string, isPmc: boolean, botLevel: number, hasBothPrimary: boolean): IGenerateWeaponResult  | ||||
|     { | ||||
|         // If the profile was just created, then use vanilla weapon gen
 | ||||
|         if (this.raidInformation.freshProfile) | ||||
|         { | ||||
|             const weaponTpl = this.pickWeightedWeaponTplFromPool(equipmentSlot, botTemplateInventory); | ||||
|             return this.generateWeaponByTpl(sessionId, weaponTpl, equipmentSlot, botTemplateInventory, weaponParentId, modChances, botRole, isPmc, botLevel); | ||||
|         } | ||||
| 
 | ||||
|         // Check if bot disabled, if it is - use SPT code
 | ||||
|         if (!this.raidInformation.isBotEnabled(botRole)) | ||||
|         { | ||||
|             const weaponTpl = this.pickWeightedWeaponTplFromPool(equipmentSlot, botTemplateInventory); | ||||
|             return this.generateWeaponByTpl(sessionId, weaponTpl, equipmentSlot, botTemplateInventory, weaponParentId, modChances, botRole, isPmc, botLevel); | ||||
|         } | ||||
| 
 | ||||
|         // If not disabled via config, all bots follow this custom generation
 | ||||
|         const tierInfo = this.apbsTierGetter.getTierByLevel(botLevel); | ||||
|         const weaponTpl =  | ||||
|             (hasBothPrimary && isPmc) | ||||
|                 ? this.apbsPickWeightedWeaponTplFromPoolHasBothPrimary(equipmentSlot, botLevel, botRole, tierInfo) | ||||
|                 : this.apbsPickWeightedWeaponTplFromPool(equipmentSlot, botLevel, botRole, tierInfo) | ||||
|         return this.apbsGenerateWeaponByTpl(sessionId, weaponTpl, equipmentSlot, botTemplateInventory, weaponParentId, modChances, botRole, isPmc, botLevel, tierInfo) | ||||
|     } | ||||
| 
 | ||||
|     private apbsPickWeightedWeaponTplFromPoolHasBothPrimary(equipmentSlot: string, botLevel: number, botRole: string, tierInfo: number): string | ||||
|     { | ||||
|         let rangeType = "ShortRange"; | ||||
|         if (equipmentSlot == "FirstPrimaryWeapon") | ||||
|         { | ||||
|             if (this.raidInformation.location == "Woods") rangeType = "LongRange"; | ||||
|             const weaponPool = this.apbsEquipmentGetter.getEquipmentByBotRole(botRole, tierInfo, equipmentSlot, rangeType); | ||||
|             return this.weightedRandomHelper.getWeightedValue<string>(weaponPool); | ||||
|         } | ||||
|         if (equipmentSlot == "SecondPrimaryWeapon") | ||||
|         { | ||||
|             if (this.raidInformation.location != "Woods") rangeType = "LongRange"; | ||||
|             const weaponPool = this.apbsEquipmentGetter.getEquipmentByBotRole(botRole, tierInfo, equipmentSlot, rangeType); | ||||
|             return this.weightedRandomHelper.getWeightedValue<string>(weaponPool); | ||||
|         } | ||||
|          | ||||
|         const weaponPool = this.apbsEquipmentGetter.getEquipmentByBotRole(botRole, tierInfo, equipmentSlot); | ||||
|         return this.weightedRandomHelper.getWeightedValue<string>(weaponPool); | ||||
|     } | ||||
| 
 | ||||
|     private apbsPickWeightedWeaponTplFromPool(equipmentSlot: string, botLevel: number, botRole: string, tierInfo: number): string | ||||
|     { | ||||
|         if (equipmentSlot == "FirstPrimaryWeapon" || equipmentSlot == "SecondPrimaryWeapon") | ||||
|         { | ||||
|             const rangeType = this.weightedRandomHelper.getWeightedValue<string>(this.raidInformation.mapWeights[this.raidInformation.location]); | ||||
|             const weaponPool = this.apbsEquipmentGetter.getEquipmentByBotRole(botRole, tierInfo, equipmentSlot, rangeType); | ||||
|             return this.weightedRandomHelper.getWeightedValue<string>(weaponPool); | ||||
|         } | ||||
|          | ||||
|         const weaponPool = this.apbsEquipmentGetter.getEquipmentByBotRole(botRole, tierInfo, equipmentSlot); | ||||
|         return this.weightedRandomHelper.getWeightedValue<string>(weaponPool); | ||||
|     } | ||||
| 
 | ||||
|     private apbsGenerateWeaponByTpl( | ||||
|         sessionId: string, | ||||
|         weaponTpl: string, | ||||
|         equipmentSlot: string, | ||||
|         botTemplateInventory: IInventory, | ||||
|         weaponParentId: string, | ||||
|         modChances: IModsChances, | ||||
|         botRole: string, | ||||
|         isPmc: boolean, | ||||
|         botLevel: number, | ||||
|         tierInfo: number | ||||
|     ): IGenerateWeaponResult | ||||
|     { | ||||
|         const modPool = this.apbsEquipmentGetter.getModsByBotRole(botRole, tierInfo); | ||||
|         const apbsModChances = this.apbsEquipmentGetter.getSpawnChancesByBotRole(botRole, tierInfo); | ||||
|         let weaponChances = apbsModChances.weaponMods; | ||||
|         const weaponItemTemplate = this.itemHelper.getItem(weaponTpl)[1]; | ||||
| 
 | ||||
|         if (ModConfig.config.enablePerWeaponTypeAttachmentChances) | ||||
|         { | ||||
|             switch (weaponItemTemplate._parent) | ||||
|             { | ||||
|                 case "5447b5fc4bdc2d87278b4567": | ||||
|                     weaponChances = apbsModChances.assaultCarbine; | ||||
|                     break; | ||||
|                 case "5447b6254bdc2dc3278b4568": | ||||
|                     weaponChances = apbsModChances.sniperRifle; | ||||
|                     break; | ||||
|                 case "5447b6194bdc2d67278b4567": | ||||
|                     weaponChances = apbsModChances.marksmanRifle; | ||||
|                     break; | ||||
|                 case "5447b5f14bdc2d61278b4567": | ||||
|                     weaponChances = apbsModChances.assaultRifle; | ||||
|                     break; | ||||
|                 case "5447bed64bdc2d97278b4568": | ||||
|                     weaponChances = apbsModChances.machinegun; | ||||
|                     break; | ||||
|                 case "5447b5e04bdc2d62278b4567": | ||||
|                     weaponChances = apbsModChances.smg; | ||||
|                     break; | ||||
|                 case "5447b5cf4bdc2d65278b4567": | ||||
|                     weaponChances = apbsModChances.handgun; | ||||
|                     break; | ||||
|                 case "617f1ef5e8b54b0998387733": | ||||
|                     weaponChances = apbsModChances.revolver; | ||||
|                     break; | ||||
|                 case "5447b6094bdc2dc3278b4567": | ||||
|                     weaponChances = apbsModChances.shotgun; | ||||
|                     break; | ||||
|                 case "5447bedf4bdc2d87278b4568": | ||||
|                     weaponChances = apbsModChances.weaponMods; | ||||
|                     break; | ||||
|                 default: | ||||
|                     weaponChances = apbsModChances.weaponMods; | ||||
|                     this.apbsLogger.log(Logging.WARN, `ItemTemplate._parent is missing classification - Report to acidphantasm - ${weaponItemTemplate._parent}`) | ||||
|                     break; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         if (!weaponItemTemplate) | ||||
|         { | ||||
|             this.logger.error(this.localisationService.getText("bot-missing_item_template", weaponTpl)); | ||||
|             this.logger.error(`WeaponSlot -> ${equipmentSlot}`); | ||||
| 
 | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         // Find ammo to use when filling magazines/chamber
 | ||||
|         if (!botTemplateInventory.Ammo) | ||||
|         { | ||||
|             this.logger.error(this.localisationService.getText("bot-no_ammo_found_in_bot_json", botRole)); | ||||
| 
 | ||||
|             throw new Error(this.localisationService.getText("bot-generation_failed")); | ||||
|         } | ||||
|         const ammoTable = this.apbsEquipmentGetter.getAmmoByBotRole(botRole, tierInfo) | ||||
|         const ammoTpl = this.getWeightedCompatibleAmmo(ammoTable, weaponItemTemplate); | ||||
| 
 | ||||
|         // Create with just base weapon item
 | ||||
|         let weaponWithModsArray = this.constructWeaponBaseArray( | ||||
|             weaponTpl, | ||||
|             weaponParentId, | ||||
|             equipmentSlot, | ||||
|             weaponItemTemplate, | ||||
|             botRole | ||||
|         ); | ||||
| 
 | ||||
|         // Chance to add randomised weapon enhancement
 | ||||
|         if (isPmc && this.randomUtil.getChance100(this.pmcConfig.weaponHasEnhancementChancePercent)) | ||||
|         { | ||||
|             const weaponConfig = this.repairConfig.repairKit.weapon; | ||||
|             this.repairService.addBuff(weaponConfig, weaponWithModsArray[0]); | ||||
|         } | ||||
| 
 | ||||
|         // Add mods to weapon base
 | ||||
|         if (Object.keys(modPool).includes(weaponTpl)) | ||||
|         { | ||||
|             const botEquipmentRole = this.botGeneratorHelper.getBotEquipmentRole(botRole); | ||||
|             const modLimits = this.botWeaponModLimitService.getWeaponModLimits(botEquipmentRole); | ||||
| 
 | ||||
|             const generateWeaponModsRequest: IGenerateWeaponRequest = { | ||||
|                 weapon: weaponWithModsArray, // Will become hydrated array of weapon + mods
 | ||||
|                 modPool: modPool, | ||||
|                 weaponId: weaponWithModsArray[0]._id, // Weapon root id
 | ||||
|                 parentTemplate: weaponItemTemplate, | ||||
|                 modSpawnChances: weaponChances, | ||||
|                 ammoTpl: ammoTpl, | ||||
|                 botData: { role: botRole, level: botLevel, equipmentRole: botEquipmentRole }, | ||||
|                 modLimits: modLimits, | ||||
|                 weaponStats: {}, | ||||
|                 conflictingItemTpls: new Set() | ||||
|             }; | ||||
|             weaponWithModsArray = this.apbsBotEquipmentModGenerator.apbsGenerateModsForWeapon( | ||||
|                 sessionId, | ||||
|                 generateWeaponModsRequest, | ||||
|                 isPmc | ||||
|             ); | ||||
|         } | ||||
| 
 | ||||
|         // Use weapon preset from globals.json if weapon isnt valid
 | ||||
|         if (!this.isWeaponValid(weaponWithModsArray, botRole)) | ||||
|         { | ||||
|             // Weapon is bad, fall back to weapons preset
 | ||||
|             weaponWithModsArray = this.getPresetWeaponMods( | ||||
|                 weaponTpl, | ||||
|                 equipmentSlot, | ||||
|                 weaponParentId, | ||||
|                 weaponItemTemplate, | ||||
|                 botRole | ||||
|             ); | ||||
|         } | ||||
| 
 | ||||
|         // Fill existing magazines to full and sync ammo type
 | ||||
|         for (const magazine of weaponWithModsArray.filter((item) => item.slotId === this.modMagazineSlotId)) | ||||
|         { | ||||
|             this.fillExistingMagazines(weaponWithModsArray, magazine, ammoTpl); | ||||
|         } | ||||
| 
 | ||||
|         // Add cartridge(s) to gun chamber(s)
 | ||||
|         if ( | ||||
|             weaponItemTemplate._props.Chambers?.length > 0 | ||||
|             && weaponItemTemplate._props.Chambers[0]?._props?.filters[0]?.Filter?.includes(ammoTpl) | ||||
|         ) | ||||
|         { | ||||
|             // Guns have variety of possible Chamber ids, patron_in_weapon/patron_in_weapon_000/patron_in_weapon_001
 | ||||
|             const chamberSlotNames = weaponItemTemplate._props.Chambers.map((x) => x._name); | ||||
|             this.addCartridgeToChamber(weaponWithModsArray, ammoTpl, chamberSlotNames); | ||||
|         } | ||||
| 
 | ||||
|         // Fill UBGL if found
 | ||||
|         const ubglMod = weaponWithModsArray.find((x) => x.slotId === "mod_launcher"); | ||||
|         let ubglAmmoTpl: string = undefined; | ||||
|         if (ubglMod) | ||||
|         { | ||||
|             const ubglTemplate = this.itemHelper.getItem(ubglMod._tpl)[1]; | ||||
|             ubglAmmoTpl = this.getWeightedCompatibleAmmo(botTemplateInventory.Ammo, ubglTemplate); | ||||
|             this.fillUbgl(weaponWithModsArray, ubglMod, ubglAmmoTpl); | ||||
|         } | ||||
|          | ||||
|         // This is for testing...
 | ||||
|         if (this.modInformation.testMode && this.modInformation.testBotRole.includes(botRole.toLowerCase())) | ||||
|         { | ||||
|             const tables = this.databaseService.getTables(); | ||||
|             const assortWeapon = this.cloner.clone(weaponWithModsArray); | ||||
|             for (const item in assortWeapon) | ||||
|             { | ||||
|                 const oldID = assortWeapon[item]._id | ||||
|                 const newID = this.hashUtil.generate(); | ||||
|                 assortWeapon[item]._id = newID; | ||||
|                  | ||||
|                 // Loop array again to fix parentID
 | ||||
|                 for (const i in assortWeapon) | ||||
|                 { | ||||
|                     if (assortWeapon[i].parentId == oldID)  | ||||
|                     { | ||||
|                         assortWeapon[i].parentId = newID | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|             this.apbsTester.createComplexAssortItem(assortWeapon) | ||||
|                 .addUnlimitedStackCount() | ||||
|                 .addMoneyCost(Money.ROUBLES, 20000) | ||||
|                 .addBuyRestriction(3) | ||||
|                 .addLoyaltyLevel(1) | ||||
|                 .export(tables.traders[this.modInformation.testTrader]); | ||||
|         } | ||||
| 
 | ||||
|         return { | ||||
|             weapon: weaponWithModsArray, | ||||
|             chosenAmmoTpl: ammoTpl, | ||||
|             chosenUbglAmmoTpl: ubglAmmoTpl, | ||||
|             weaponMods: modPool, | ||||
|             weaponTemplate: weaponItemTemplate | ||||
|         }; | ||||
|     } | ||||
| 
 | ||||
|     public apbsAddExtraMagazinesToInventory( | ||||
|         generatedWeaponResult: IGenerateWeaponResult, | ||||
|         magWeights: IGenerationData, | ||||
|         inventory: PmcInventory, | ||||
|         botRole: string, | ||||
|         botLevel: number | ||||
|     ): void  | ||||
|     { | ||||
|         const weaponAndMods = generatedWeaponResult.weapon; | ||||
|         const weaponTemplate = generatedWeaponResult.weaponTemplate; | ||||
|         const magazineTpl = this.getMagazineTplFromWeaponTemplate(weaponAndMods, weaponTemplate, botRole); | ||||
| 
 | ||||
|         const magTemplate = this.itemHelper.getItem(magazineTpl)[1]; | ||||
|         if (!magTemplate)  | ||||
|         { | ||||
|             this.logger.error(this.localisationService.getText("bot-unable_to_find_magazine_item", magazineTpl)); | ||||
| 
 | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         const ammoTemplate = this.itemHelper.getItem(generatedWeaponResult.chosenAmmoTpl)[1]; | ||||
|         if (!ammoTemplate)  | ||||
|         { | ||||
|             this.logger.error( | ||||
|                 this.localisationService.getText("bot-unable_to_find_ammo_item", generatedWeaponResult.chosenAmmoTpl) | ||||
|             ); | ||||
| 
 | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         // Has an UBGL
 | ||||
|         if (generatedWeaponResult.chosenUbglAmmoTpl)  | ||||
|         { | ||||
|             this.addUbglGrenadesToBotInventory(weaponAndMods, generatedWeaponResult, inventory); | ||||
|         } | ||||
| 
 | ||||
|         const apbsInventoryMagGenModel = new APBSInventoryMagGen( | ||||
|             magWeights, | ||||
|             magTemplate, | ||||
|             weaponTemplate, | ||||
|             ammoTemplate, | ||||
|             inventory, | ||||
|             botRole, | ||||
|             botLevel | ||||
|         ); | ||||
|         this.apbsInventoryMagGenComponents | ||||
|             .find((v) => v.canHandleInventoryMagGen(apbsInventoryMagGenModel)) | ||||
|             .process(apbsInventoryMagGenModel); | ||||
| 
 | ||||
|         // Add x stacks of bullets to SecuredContainer (bots use a magic mag packing skill to reload instantly)
 | ||||
|         this.addAmmoToSecureContainer( | ||||
|             this.botConfig.secureContainerAmmoStackCount, | ||||
|             generatedWeaponResult.chosenAmmoTpl, | ||||
|             ammoTemplate._props.StackMaxSize, | ||||
|             inventory | ||||
|         ); | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,143 @@ | |||
| import { inject, injectable } from "tsyringe"; | ||||
| 
 | ||||
| import { BotGenerator } from "@spt/generators/BotGenerator"; | ||||
| import { BotGeneratorHelper } from "@spt/helpers/BotGeneratorHelper"; | ||||
| import { BotHelper } from "@spt/helpers/BotHelper"; | ||||
| import { ItemHelper } from "@spt/helpers/ItemHelper"; | ||||
| import { ProfileHelper } from "@spt/helpers/ProfileHelper"; | ||||
| import { IPmcData } from "@spt/models/eft/common/IPmcData"; | ||||
| import { IBotInfoSettings } from "@spt/models/eft/common/tables/IBotBase"; | ||||
| import { IBotType } from "@spt/models/eft/common/tables/IBotType"; | ||||
| import { MemberCategory } from "@spt/models/enums/MemberCategory"; | ||||
| import { ILogger } from "@spt/models/spt/utils/ILogger"; | ||||
| import { ConfigServer } from "@spt/servers/ConfigServer"; | ||||
| import { SaveServer } from "@spt/servers/SaveServer"; | ||||
| import { BotLootCacheService } from "@spt/services/BotLootCacheService"; | ||||
| import { DatabaseService } from "@spt/services/DatabaseService"; | ||||
| import { FenceService } from "@spt/services/FenceService"; | ||||
| import { LocalisationService } from "@spt/services/LocalisationService"; | ||||
| import { HashUtil } from "@spt/utils/HashUtil"; | ||||
| import { RandomUtil } from "@spt/utils/RandomUtil"; | ||||
| import { ICloner } from "@spt/utils/cloners/ICloner"; | ||||
| import { PlayerScavGenerator } from "@spt/generators/PlayerScavGenerator"; | ||||
| import { APBSBotLootCacheService } from "./APBSBotLootCacheService"; | ||||
| 
 | ||||
| @injectable() | ||||
| export class APBSPlayerScavGenerator extends PlayerScavGenerator | ||||
| { | ||||
|     constructor( | ||||
|         @inject("PrimaryLogger") protected logger: ILogger, | ||||
|         @inject("RandomUtil") protected randomUtil: RandomUtil, | ||||
|         @inject("DatabaseService") protected databaseService: DatabaseService, | ||||
|         @inject("HashUtil") protected hashUtil: HashUtil, | ||||
|         @inject("ItemHelper") protected itemHelper: ItemHelper, | ||||
|         @inject("BotGeneratorHelper") protected botGeneratorHelper: BotGeneratorHelper, | ||||
|         @inject("SaveServer") protected saveServer: SaveServer, | ||||
|         @inject("ProfileHelper") protected profileHelper: ProfileHelper, | ||||
|         @inject("BotHelper") protected botHelper: BotHelper, | ||||
|         @inject("FenceService") protected fenceService: FenceService, | ||||
|         @inject("BotLootCacheService") protected botLootCacheService: BotLootCacheService, | ||||
|         @inject("LocalisationService") protected localisationService: LocalisationService, | ||||
|         @inject("BotGenerator") protected botGenerator: BotGenerator, | ||||
|         @inject("ConfigServer") protected configServer: ConfigServer, | ||||
|         @inject("PrimaryCloner") protected cloner: ICloner, | ||||
|         @inject("APBSBotLootCacheService") protected apbsBotLootCacheService: APBSBotLootCacheService | ||||
|     ) | ||||
|     { | ||||
|         super(logger,  | ||||
|             randomUtil,  | ||||
|             databaseService,  | ||||
|             hashUtil,  | ||||
|             itemHelper, | ||||
|             botGeneratorHelper,  | ||||
|             saveServer,  | ||||
|             profileHelper,  | ||||
|             botHelper, | ||||
|             fenceService,  | ||||
|             botLootCacheService,  | ||||
|             localisationService, | ||||
|             botGenerator, | ||||
|             configServer,  | ||||
|             cloner) | ||||
|     } | ||||
| 
 | ||||
|     public generate(sessionID: string): IPmcData  | ||||
|     { | ||||
|         // get karma level from profile
 | ||||
|         const profile = this.saveServer.getProfile(sessionID); | ||||
|         const profileCharactersClone = this.cloner.clone(profile.characters); | ||||
|         const pmcDataClone = profileCharactersClone.pmc; | ||||
|         const existingScavDataClone = profileCharactersClone.scav; | ||||
| 
 | ||||
|         const scavKarmaLevel = this.getScavKarmaLevel(pmcDataClone); | ||||
| 
 | ||||
|         // use karma level to get correct karmaSettings
 | ||||
|         const playerScavKarmaSettings = this.playerScavConfig.karmaLevel[scavKarmaLevel]; | ||||
|         if (!playerScavKarmaSettings)  | ||||
|         { | ||||
|             this.logger.error(this.localisationService.getText("scav-missing_karma_settings", scavKarmaLevel)); | ||||
|         } | ||||
| 
 | ||||
|         this.logger.debug(`generated player scav loadout with karma level ${scavKarmaLevel}`); | ||||
| 
 | ||||
|         // Edit baseBotNode values
 | ||||
|         const baseBotNode: IBotType = this.constructBotBaseTemplate(playerScavKarmaSettings.botTypeForLoot); | ||||
|         this.adjustBotTemplateWithKarmaSpecificSettings(playerScavKarmaSettings, baseBotNode); | ||||
| 
 | ||||
|         let scavData = this.botGenerator.generatePlayerScav( | ||||
|             sessionID, | ||||
|             playerScavKarmaSettings.botTypeForLoot.toLowerCase(), | ||||
|             "easy", | ||||
|             baseBotNode, | ||||
|             pmcDataClone | ||||
|         ); | ||||
| 
 | ||||
|         // Remove cached bot data after scav was generated
 | ||||
|         this.botLootCacheService.clearCache(); | ||||
|         this.apbsBotLootCacheService.apbsClearCache(); | ||||
| 
 | ||||
|         // Add scav metadata
 | ||||
|         scavData.savage = undefined; | ||||
|         scavData.aid = pmcDataClone.aid; | ||||
|         scavData.TradersInfo = pmcDataClone.TradersInfo; | ||||
|         scavData.Info.Settings = {} as IBotInfoSettings; | ||||
|         scavData.Info.Bans = []; | ||||
|         scavData.Info.RegistrationDate = pmcDataClone.Info.RegistrationDate; | ||||
|         scavData.Info.GameVersion = pmcDataClone.Info.GameVersion; | ||||
|         scavData.Info.MemberCategory = MemberCategory.UNIQUE_ID; | ||||
|         scavData.Info.lockedMoveCommands = true; | ||||
|         scavData.RagfairInfo = pmcDataClone.RagfairInfo; | ||||
|         scavData.UnlockedInfo = pmcDataClone.UnlockedInfo; | ||||
| 
 | ||||
|         // Persist previous scav data into new scav
 | ||||
|         scavData._id = existingScavDataClone._id ?? pmcDataClone.savage; | ||||
|         scavData.sessionId = existingScavDataClone.sessionId ?? pmcDataClone.sessionId; | ||||
|         scavData.Skills = this.getScavSkills(existingScavDataClone); | ||||
|         scavData.Stats = this.getScavStats(existingScavDataClone); | ||||
|         scavData.Info.Level = this.getScavLevel(existingScavDataClone); | ||||
|         scavData.Info.Experience = this.getScavExperience(existingScavDataClone); | ||||
|         scavData.Quests = existingScavDataClone.Quests ?? []; | ||||
|         scavData.TaskConditionCounters = existingScavDataClone.TaskConditionCounters ?? {}; | ||||
|         scavData.Notes = existingScavDataClone.Notes ?? { Notes: [] }; | ||||
|         scavData.WishList = existingScavDataClone.WishList ?? {}; | ||||
|         scavData.Encyclopedia = pmcDataClone.Encyclopedia ?? {}; | ||||
| 
 | ||||
|         // Add additional items to player scav as loot
 | ||||
|         this.addAdditionalLootToPlayerScavContainers(playerScavKarmaSettings.lootItemsToAddChancePercent, scavData, [ | ||||
|             "TacticalVest", | ||||
|             "Pockets", | ||||
|             "Backpack" | ||||
|         ]); | ||||
| 
 | ||||
|         // Remove secure container
 | ||||
|         scavData = this.profileHelper.removeSecureContainer(scavData); | ||||
| 
 | ||||
|         // Set cooldown timer
 | ||||
|         scavData = this.setScavCooldownTimer(scavData, pmcDataClone); | ||||
| 
 | ||||
|         // Add scav to the profile
 | ||||
|         this.saveServer.getProfile(sessionID).characters.scav = scavData; | ||||
| 
 | ||||
|         return scavData; | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,21 @@ | |||
| export enum Logging  | ||||
| { | ||||
|     SCAV = "scav_generation", | ||||
|     PMC = "pmc_generation", | ||||
|     RAIDER = "raider_generation", | ||||
|     BOSS = "boss_generation", | ||||
|     EVENT = "event_generation", | ||||
|     WARN = "warnings", | ||||
|     ERR = "errors", | ||||
|     DEBUG = "debug" | ||||
| } | ||||
| 
 | ||||
| export enum LoggingFolders  | ||||
| { | ||||
|     DEBUG = "debug", | ||||
|     SCAV = "scav_generation", | ||||
|     PMC = "pmc_generation", | ||||
|     RAIDER = "raider_generation", | ||||
|     BOSS = "boss_generation", | ||||
|     EVENT = "event_generation" | ||||
| } | ||||
|  | @ -0,0 +1,149 @@ | |||
| import { DependencyContainer, inject, injectable } from "tsyringe"; | ||||
| 
 | ||||
| import { DatabaseService } from "@spt/services/DatabaseService"; | ||||
| import { RandomUtil } from "@spt/utils/RandomUtil"; | ||||
| import { BotLevelGenerator } from "@spt/generators/BotLevelGenerator"; | ||||
| import { MinMax } from "@spt/models/common/MinMax"; | ||||
| import { IRandomisedBotLevelResult } from "@spt/models/eft/bot/IRandomisedBotLevelResult"; | ||||
| import { IBotGenerationDetails } from "@spt/models/spt/bots/BotGenerationDetails"; | ||||
| import { APBSLogger } from "../Utils/APBSLogger"; | ||||
| import { Logging } from "../Enums/Logging"; | ||||
| import { ProfileHelper } from "@spt/helpers/ProfileHelper"; | ||||
| import { APBSIBotBase } from "../Interface/APBSIBotBase"; | ||||
| import { RaidInformation } from "../Globals/RaidInformation"; | ||||
| import { APBSTierGetter } from "../Utils/APBSTierGetter"; | ||||
| import { ModConfig } from "../Globals/ModConfig"; | ||||
| import { APBSEquipmentGetter } from "../Utils/APBSEquipmentGetter"; | ||||
| import { ModInformation } from "../Globals/ModInformation"; | ||||
| 
 | ||||
| /** Handle profile related client events */ | ||||
| @injectable() | ||||
| export class APBSBotLevelGenerator | ||||
| { | ||||
|     constructor( | ||||
|         @inject("RandomUtil") protected randomUtil: RandomUtil, | ||||
|         @inject("DatabaseService") protected databaseService: DatabaseService, | ||||
|         @inject("BotLevelGenerator") protected botLevelGenerator: BotLevelGenerator, | ||||
|         @inject("APBSLogger") protected apbsLogger: APBSLogger, | ||||
|         @inject("ProfileHelper") protected profileHelper: ProfileHelper, | ||||
|         @inject("APBSTierGetter") protected apbsTierGetter: APBSTierGetter, | ||||
|         @inject("RaidInformation") protected raidInformation: RaidInformation, | ||||
|         @inject("ModInformation") protected modInformation: ModInformation, | ||||
|         @inject("APBSEquipmentGetter") protected apbsEquipmentGetter: APBSEquipmentGetter | ||||
|     ) | ||||
|     {} | ||||
| 
 | ||||
|     public registerBotLevelGenerator(container: DependencyContainer): void  | ||||
|     {     | ||||
|         container.afterResolution("BotLevelGenerator", (_t, result: BotLevelGenerator) =>  | ||||
|         { | ||||
|             result.generateBotLevel = (levelDetails: MinMax, botGenerationDetails: IBotGenerationDetails, bot: APBSIBotBase): IRandomisedBotLevelResult =>  | ||||
|             {                 | ||||
|                 if (this.modInformation.testMode && this.modInformation.testBotRole.includes(botGenerationDetails.role.toLowerCase())) | ||||
|                 { | ||||
|                     const level = this.profileHelper.getPmcProfile(this.raidInformation.sessionId)?.Info?.Level; | ||||
|                     const exp = this.profileHelper.getExperience(level); | ||||
|                     const tier = this.apbsTierGetter.getTierByLevel(level); | ||||
|                     bot.Info.Tier = this.chadOrChill(tier.toString()); | ||||
|                      | ||||
|                     const result: IRandomisedBotLevelResult = { | ||||
|                         level, | ||||
|                         exp  | ||||
|                     }; | ||||
|                     return result; | ||||
|                 } | ||||
| 
 | ||||
|                 if (botGenerationDetails.isPlayerScav) | ||||
|                 { | ||||
|                     let level = this.raidInformation.freshProfile == true ? 1 : this.profileHelper.getPmcProfile(this.raidInformation.sessionId)?.Info?.Level; | ||||
| 
 | ||||
|                     // Level only stays undefined when a Fika dedicated profile is created due to this.raidInformation.freshProfile never being set.
 | ||||
|                     // As Fika never calls /client/profile/status
 | ||||
|                     if (level === undefined) | ||||
|                     { | ||||
|                         this.raidInformation.freshProfile = true; | ||||
|                         level = 1; | ||||
|                     } | ||||
|                      | ||||
|                     const exp = this.profileHelper.getExperience(level); | ||||
|                     const tier = this.apbsTierGetter.getTierByLevel(level); | ||||
|                     bot.Info.Tier = this.chadOrChill(tier.toString()); | ||||
|                     const result: IRandomisedBotLevelResult = { | ||||
|                         level, | ||||
|                         exp  | ||||
|                     }; | ||||
|                     return result;                     | ||||
|                 } | ||||
| 
 | ||||
|                 const expTable = this.databaseService.getGlobals().config.exp.level.exp_table; | ||||
|                 const botLevelRange = this.apbsGetRelativeBotLevelRange(botGenerationDetails, levelDetails, expTable.length); | ||||
|                 const min = botLevelRange.min <= 0 ? 1 : botLevelRange.min; | ||||
|                 const max = botLevelRange.max >= 79 ? 79 : botLevelRange.max; | ||||
|                 const level = this.randomUtil.getInt(min, max); | ||||
|                 const exp = this.profileHelper.getExperience(level); | ||||
|                 const tier = this.apbsTierGetter.getTierByLevel(level); | ||||
|                 bot.Info.Tier = this.chadOrChill(tier.toString()); | ||||
|                  | ||||
|                 const result: IRandomisedBotLevelResult = { | ||||
|                     level, | ||||
|                     exp  | ||||
|                 }; | ||||
|                 return result; | ||||
|             }; | ||||
|         }, | ||||
|         { frequency: "Always" } | ||||
|         ); | ||||
|         this.apbsLogger.log(Logging.DEBUG, "Bot Level Generator registered"); | ||||
|     } | ||||
| 
 | ||||
|     private chadOrChill(tierInfo: string): string | ||||
|     { | ||||
|         if (ModConfig.config.onlyChads && ModConfig.config.tarkovAndChill) | ||||
|         { | ||||
|             return "?"; | ||||
|         } | ||||
|         if (ModConfig.config.onlyChads) return "7"; | ||||
|         if (ModConfig.config.tarkovAndChill) return "1"; | ||||
|         if (ModConfig.config.blickyMode) return "0"; | ||||
| 
 | ||||
|         return tierInfo; | ||||
|     } | ||||
| 
 | ||||
|     protected apbsGetRelativeBotLevelRange( | ||||
|         botGenerationDetails: IBotGenerationDetails, | ||||
|         levelDetails: MinMax, | ||||
|         maxAvailableLevel: number | ||||
|     ): MinMax  | ||||
|     { | ||||
|         const minPossibleLevel = | ||||
|             botGenerationDetails.isPmc && botGenerationDetails.locationSpecificPmcLevelOverride | ||||
|                 ? Math.min( | ||||
|                     Math.max(levelDetails.min, botGenerationDetails.locationSpecificPmcLevelOverride.min), // Biggest between json min and the botgen min
 | ||||
|                     maxAvailableLevel // Fallback if value above is crazy (default is 79)
 | ||||
|                 ) | ||||
|                 : Math.min(levelDetails.min, maxAvailableLevel); // Not pmc with override or non-pmc
 | ||||
| 
 | ||||
|         const maxPossibleLevel = | ||||
|             botGenerationDetails.isPmc && botGenerationDetails.locationSpecificPmcLevelOverride | ||||
|                 ? Math.min(botGenerationDetails.locationSpecificPmcLevelOverride.max, maxAvailableLevel) // Was a PMC and they have a level override
 | ||||
|                 : Math.min(levelDetails.max, maxAvailableLevel); // Not pmc with override or non-pmc
 | ||||
| 
 | ||||
|         let minLevel = botGenerationDetails.playerLevel - this.apbsTierGetter.getTierLowerLevelDeviation(botGenerationDetails.playerLevel); | ||||
|         let maxLevel = botGenerationDetails.playerLevel + this.apbsTierGetter.getTierUpperLevelDeviation(botGenerationDetails.playerLevel); | ||||
| 
 | ||||
|         if (ModConfig.config.enableScavCustomLevelDeltas && !botGenerationDetails.isPmc && !botGenerationDetails.isPlayerScav && (botGenerationDetails.role.includes("assault") || botGenerationDetails.role == "marksman")) | ||||
|         { | ||||
|             minLevel = botGenerationDetails.playerLevel - this.apbsTierGetter.getScavTierLowerLevelDeviation(botGenerationDetails.playerLevel); | ||||
|             maxLevel = botGenerationDetails.playerLevel + this.apbsTierGetter.getScavTierUpperLevelDeviation(botGenerationDetails.playerLevel); | ||||
|         } | ||||
| 
 | ||||
|         // Bound the level to the min/max possible
 | ||||
|         maxLevel = Math.min(Math.max(maxLevel, minPossibleLevel), maxPossibleLevel); | ||||
|         minLevel = Math.min(Math.max(minLevel, minPossibleLevel), maxPossibleLevel); | ||||
| 
 | ||||
|         return { | ||||
|             min: minLevel, | ||||
|             max: maxLevel | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,154 @@ | |||
| /* eslint-disable @typescript-eslint/naming-convention */ | ||||
| import { VFS } from "@spt/utils/VFS"; | ||||
| import { inject, injectable } from "tsyringe"; | ||||
| import jsonc from "jsonc"; | ||||
| import path from "path"; | ||||
| import { TierInformation } from "./TierInformation"; | ||||
| import { APBSLogger } from "../Utils/APBSLogger"; | ||||
| import { ILogger } from "@spt/models/spt/utils/ILogger"; | ||||
| 
 | ||||
| @injectable() | ||||
| export class ModConfig | ||||
| { | ||||
|     public static config: Config; | ||||
| 
 | ||||
|     constructor( | ||||
|         @inject("APBSLogger") protected apbsLogger: APBSLogger, | ||||
|         @inject("PrimaryLogger") protected logger: ILogger, | ||||
|         @inject("TierInformation") protected tierInformation: TierInformation, | ||||
|         @inject("VFS") protected vfs: VFS | ||||
|     ) | ||||
|     { | ||||
|         ModConfig.config = jsonc.parse(this.vfs.readFile(path.resolve(__dirname, "../../config/config.jsonc"))); | ||||
|     } | ||||
| 
 | ||||
|     public serverLogDetails(): void | ||||
|     { | ||||
|         this.logger.debug("[APBS] Mod Config - FOR SUPPORT FOLKS ❤❤") | ||||
|         this.logger.debug(`[APBS] Import Mod Weapons: ${ModConfig.config.enableModdedWeapons} <- MUST BE FALSE FOR SUPPORT`) | ||||
|         this.logger.debug(`[APBS] Import Mod Equipment: ${ModConfig.config.enableModdedEquipment} <- MUST BE FALSE FOR SUPPORT`) | ||||
|         this.logger.debug(`[APBS] Import Mod Clothing: ${ModConfig.config.enableModdedClothing} <- MUST BE FALSE FOR SUPPORT`) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| export interface Config | ||||
| { | ||||
|     usePreset: boolean, | ||||
|     presetName: string, | ||||
|     enableModdedWeapons: boolean, | ||||
|     enableModdedEquipment: boolean, | ||||
|     enableModdedClothing: boolean, | ||||
|     initalTierAppearance: number, | ||||
|     pmcWeaponWeights: number, | ||||
|     scavWeaponWeights: number, | ||||
|     followerWeaponWeights: number, | ||||
|     enableSafeGuard: boolean, | ||||
|     seasonalPmcAppearance: boolean, | ||||
|     disableRealismGasMasks: boolean, | ||||
|     onlyChads: boolean, | ||||
|     tarkovAndChill: boolean, | ||||
|     blickyMode: boolean, | ||||
|     disableScavTierGeneration: boolean, | ||||
|     disablePMCTierGeneration: boolean, | ||||
|     disableBossTierGeneration: boolean, | ||||
|     disableBossFollowerTierGeneration: boolean, | ||||
|     disableRaiderRogueTierGeneration: boolean, | ||||
|     enableBotsToRollAmmoAgain: boolean, | ||||
|     chanceToRollAmmoAgain: number, | ||||
|     gameVersionWeight: boolean,  | ||||
|     standard: number,  | ||||
|     left_behind: number,  | ||||
|     prepare_for_escape: number,  | ||||
|     edge_of_darkness: number,  | ||||
|     unheard_edition: number, | ||||
|     enablePMCAmmoTierSliding: boolean, | ||||
|     slideAmount: number, | ||||
|     slideChance: number, | ||||
|     enablePerWeaponTypeAttachmentChances: boolean, | ||||
|     forceStock: boolean, | ||||
|     stockButtpadChance: number, | ||||
|     forceDustCover: boolean, | ||||
|     forceScopeSlot: boolean, | ||||
|     forceMuzzle: boolean, | ||||
|     muzzleChance: [ number, number, number, number, number, number, number ], | ||||
|     forceChildrenMuzzle: boolean, | ||||
|     pmcLoot: boolean, | ||||
|     pmcLootBlacklistItems: string[], | ||||
|     scavLoot: boolean, | ||||
|     enableScavAttachmentTiering: boolean, | ||||
|     enableScavEqualEquipmentTiering: boolean, | ||||
|     forceWeaponModLimits: boolean, | ||||
|     scopeLimit: number, | ||||
|     tacticalLimit: number, | ||||
|     enableT7Thermals: boolean, | ||||
|     startTier: number, | ||||
|     scavWeaponDurability: [ number, number, number, number ], | ||||
|     pmcWeaponDurability: [ number, number, number, number ], | ||||
|     bossWeaponDurability: [ number, number, number, number ], | ||||
|     guardWeaponDurability: [ number, number, number, number ], | ||||
|     raiderWeaponDurability: [ number, number, number, number ], | ||||
|     enableCustomPlateChances: boolean, | ||||
|     scavMainPlateChance: [ number, number, number, number, number, number, number ], | ||||
|     scavSidePlateChance: [ number, number, number, number, number, number, number ], | ||||
|     pmcMainPlateChance: [ number, number, number, number, number, number, number ], | ||||
|     pmcSidePlateChance: [ number, number, number, number, number, number, number ], | ||||
|     bossMainPlateChance: [ number, number, number, number, number, number, number ], | ||||
|     bossSidePlateChance: [ number, number, number, number, number, number, number ], | ||||
|     guardMainPlateChance: [ number, number, number, number, number, number, number ], | ||||
|     guardSidePlateChance: [ number, number, number, number, number, number, number ], | ||||
|     raiderMainPlateChance: [ number, number, number, number, number, number, number ], | ||||
|     raiderSidePlateChance: [ number, number, number, number, number, number, number ], | ||||
|     addAllKeysToScavs: boolean, | ||||
|     addOnlyMechanicalKeysToScavs: boolean, | ||||
|     addOnlyKeyCardsToScavs: boolean, | ||||
|     enableConsumableResourceRandomization: boolean, | ||||
|     scavFoodRates: [ number, number ] | ||||
|     scavMedRates: [ number, number ] | ||||
|     pmcFoodRates: [ number, number ] | ||||
|     pmcMedRates: [ number, number ] | ||||
|     tier1AmmoBlacklist: string[], | ||||
|     tier2AmmoBlacklist: string[], | ||||
|     tier3AmmoBlacklist: string[], | ||||
|     tier4AmmoBlacklist: string[], | ||||
|     tier5AmmoBlacklist: string[], | ||||
|     tier6AmmoBlacklist: string[], | ||||
|     tier7AmmoBlacklist: string[], | ||||
|     tier1EquipmentBlacklist: string[], | ||||
|     tier2EquipmentBlacklist: string[], | ||||
|     tier3EquipmentBlacklist: string[], | ||||
|     tier4EquipmentBlacklist: string[], | ||||
|     tier5EquipmentBlacklist: string[], | ||||
|     tier6EquipmentBlacklist: string[], | ||||
|     tier7EquipmentBlacklist: string[], | ||||
|     tier1WeaponBlacklist: string[], | ||||
|     tier2WeaponBlacklist: string[], | ||||
|     tier3WeaponBlacklist: string[], | ||||
|     tier4WeaponBlacklist: string[], | ||||
|     tier5WeaponBlacklist: string[], | ||||
|     tier6WeaponBlacklist: string[], | ||||
|     tier7WeaponBlacklist: string[], | ||||
|     tier1AttachmentBlacklist: string[], | ||||
|     tier2AttachmentBlacklist: string[], | ||||
|     tier3AttachmentBlacklist: string[], | ||||
|     tier4AttachmentBlacklist: string[], | ||||
|     tier5AttachmentBlacklist: string[], | ||||
|     tier6AttachmentBlacklist: string[], | ||||
|     tier7AttachmentBlacklist: string[], | ||||
|     enableCustomLevelDeltas: boolean, | ||||
|     tier1LevelDelta: [ number, number ], | ||||
|     tier2LevelDelta: [ number, number ], | ||||
|     tier3LevelDelta: [ number, number ], | ||||
|     tier4LevelDelta: [ number, number ], | ||||
|     tier5LevelDelta: [ number, number ], | ||||
|     tier6LevelDelta: [ number, number ], | ||||
|     tier7LevelDelta: [ number, number ], | ||||
|     enableScavCustomLevelDeltas: boolean, | ||||
|     tier1ScavLevelDelta: [ number, number ], | ||||
|     tier2ScavLevelDelta: [ number, number ], | ||||
|     tier3ScavLevelDelta: [ number, number ], | ||||
|     tier4ScavLevelDelta: [ number, number ], | ||||
|     tier5ScavLevelDelta: [ number, number ], | ||||
|     tier6ScavLevelDelta: [ number, number ], | ||||
|     tier7ScavLevelDelta: [ number, number ], | ||||
|     enableDebugLog: boolean, | ||||
| } | ||||
|  | @ -0,0 +1,16 @@ | |||
| import * as path from "path"; | ||||
| import modPackage = require("../../package.json"); | ||||
| 
 | ||||
| export class ModInformation | ||||
| { | ||||
|     public modPath: string = path.join(path.dirname(__filename), "..", ".."); | ||||
|     public logPath: string = path.join(path.dirname(__filename), "..", "..", "logs"); | ||||
|     public profilePath: string = path.join(path.dirname(__filename), "..", "..", "..", "..", "profiles"); | ||||
|     public versionNumber: string = modPackage.version; | ||||
| 
 | ||||
|     public testMode: boolean = false; | ||||
|     public testBotRole: (string)[] = [ "pmcusec", "pmcbear" ] | ||||
|     public testTrader: string = "6741449944c5b44c53741ccc" | ||||
|     public clearAssortPreRaid: boolean = true; | ||||
| } | ||||
| 
 | ||||
|  | @ -0,0 +1,169 @@ | |||
| import { injectable } from "tsyringe"; | ||||
| import { ModConfig } from "./ModConfig"; | ||||
| 
 | ||||
| @injectable() | ||||
| export class RaidInformation | ||||
| { | ||||
|     constructor( | ||||
| 
 | ||||
|     ) | ||||
|     {} | ||||
| 
 | ||||
|     public freshProfile: boolean; | ||||
| 
 | ||||
|     public location: string; | ||||
|     public currentTime: string; | ||||
|     public timeVariant: string; | ||||
|     public nightTime: boolean; | ||||
| 
 | ||||
|     public sessionId: string; | ||||
| 
 | ||||
|     public usingDefaultDB: boolean; | ||||
| 
 | ||||
|     public mapWeights = { | ||||
|         "bigmap": | ||||
|         { | ||||
|             "LongRange": 20, | ||||
|             "ShortRange": 80 | ||||
|         }, | ||||
|         "RezervBase": | ||||
|         { | ||||
|             "LongRange": 20, | ||||
|             "ShortRange": 80 | ||||
|         }, | ||||
|         "laboratory": | ||||
|         { | ||||
|             "LongRange": 10, | ||||
|             "ShortRange": 90 | ||||
|         }, | ||||
|         "factory4_night": | ||||
|         { | ||||
|             "LongRange": 5, | ||||
|             "ShortRange": 95 | ||||
|         }, | ||||
|         "factory4_day": | ||||
|         { | ||||
|             "LongRange": 5, | ||||
|             "ShortRange": 95 | ||||
|         }, | ||||
|         "Interchange": | ||||
|         { | ||||
|             "LongRange": 20, | ||||
|             "ShortRange": 80 | ||||
|         }, | ||||
|         "Sandbox": | ||||
|         { | ||||
|             "LongRange": 15, | ||||
|             "ShortRange": 85 | ||||
|         }, | ||||
|         "Sandbox_high": | ||||
|         { | ||||
|             "LongRange": 15, | ||||
|             "ShortRange": 85 | ||||
|         }, | ||||
|         "Woods": | ||||
|         { | ||||
|             "LongRange": 60, | ||||
|             "ShortRange": 40 | ||||
|         }, | ||||
|         "Shoreline": | ||||
|         { | ||||
|             "LongRange": 50, | ||||
|             "ShortRange": 50 | ||||
|         }, | ||||
|         "Lighthouse": | ||||
|         { | ||||
|             "LongRange": 30, | ||||
|             "ShortRange": 70 | ||||
|         }, | ||||
|         "TarkovStreets": | ||||
|         { | ||||
|             "LongRange": 20, | ||||
|             "ShortRange": 80 | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     public alwaysDisabledBots = [ | ||||
|         "shooterbtr", | ||||
|         "skier", | ||||
|         "peacemaker", | ||||
|         "gifter", | ||||
|         "infectedassault", | ||||
|         "infectedcivil", | ||||
|         "infectedlaborant", | ||||
|         "infectedpmc", | ||||
|         "infectedtagilla", | ||||
|         "bosslegion", | ||||
|         "bosspunisher" | ||||
|     ] | ||||
|     public isBotEnabled(botType: string): boolean | ||||
|     { | ||||
|         botType = botType.toLowerCase(); | ||||
|         switch (botType)  | ||||
|         { | ||||
|             case "pmcbear": | ||||
|             case "pmcusec": | ||||
|                 if (ModConfig.config.disablePMCTierGeneration) return false; | ||||
|                 return true; | ||||
|             case "cursedassault": | ||||
|             case "marksman": | ||||
|             case "assault": | ||||
|                 if (ModConfig.config.disableScavTierGeneration) return false; | ||||
|                 return true; | ||||
|             case "arenafighterevent": | ||||
|             case "exusec": | ||||
|                 if (ModConfig.config.disableRaiderRogueTierGeneration) return false; | ||||
|                 return true; | ||||
|             case "bossbully": | ||||
|             case "bosstagilla": | ||||
|             case "bosspartisan": | ||||
|             case "bossgluhar": | ||||
|             case "bosskilla": | ||||
|             case "bosskojaniy": | ||||
|             case "bosssanitar": | ||||
|             case "bossknight": | ||||
|             case "bosszryachiy": | ||||
|             case "bosstest": | ||||
|             case "bosskolontay": | ||||
|             case "bossboar": | ||||
|             case "bossboarSniper": | ||||
|             case "sectantpriest": | ||||
|                 if (ModConfig.config.disableBossTierGeneration) return false; | ||||
|                 return true; | ||||
|             case "sectantwarrior": | ||||
|             case "followerboarblose1": | ||||
|             case "followerboarclose2": | ||||
|             case "followerkolontayassault": | ||||
|             case "followerkolontaysecurity": | ||||
|             case "followerbully": | ||||
|             case "followergluharassault": | ||||
|             case "followergluharscout": | ||||
|             case "followergluharsecurity": | ||||
|             case "followergluharsnipe": | ||||
|             case "followerkojaniy": | ||||
|             case "followersanitar": | ||||
|             case "followertagilla": | ||||
|             case "followerbirdeye": | ||||
|             case "followerbigpipe": | ||||
|             case "followerzryachiy": | ||||
|             case "followertest": | ||||
|             case "followerboar": | ||||
|                 if (ModConfig.config.disableBossFollowerTierGeneration) return false; | ||||
|                 return true; | ||||
|             case "shooterbtr": | ||||
|             case "skier": | ||||
|             case "peacemaker": | ||||
|             case "gifter": | ||||
|             case "infectedassault": | ||||
|             case "infectedcivil": | ||||
|             case "infectedlaborant": | ||||
|             case "infectedpmc": | ||||
|             case "infectedtagilla": | ||||
|             case "bosslegion": | ||||
|             case "bosspunisher": | ||||
|                 return false; | ||||
|             default: | ||||
|                 return false; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,373 @@ | |||
| /* eslint-disable @typescript-eslint/naming-convention */ | ||||
| export class TierInformation | ||||
| { | ||||
|     public tier0; | ||||
|     public tier1; | ||||
|     public tier2; | ||||
|     public tier3; | ||||
|     public tier4; | ||||
|     public tier5; | ||||
|     public tier6; | ||||
|     public tier7; | ||||
| 
 | ||||
|     public tier0mods; | ||||
|     public tier1mods; | ||||
|     public tier2mods; | ||||
|     public tier3mods; | ||||
|     public tier4mods; | ||||
|     public tier5mods; | ||||
|     public tier6mods; | ||||
|     public tier7mods; | ||||
| 
 | ||||
|     public tier0chances; | ||||
|     public tier1chances; | ||||
|     public tier2chances; | ||||
|     public tier3chances; | ||||
|     public tier4chances; | ||||
|     public tier5chances; | ||||
|     public tier6chances; | ||||
|     public tier7chances; | ||||
| 
 | ||||
|     public tier0ammo; | ||||
|     public tier1ammo; | ||||
|     public tier2ammo; | ||||
|     public tier3ammo; | ||||
|     public tier4ammo; | ||||
|     public tier5ammo; | ||||
|     public tier6ammo; | ||||
|     public tier7ammo; | ||||
| 
 | ||||
|     public tier0appearance; | ||||
|     public tier1appearance; | ||||
|     public tier2appearance; | ||||
|     public tier3appearance; | ||||
|     public tier4appearance; | ||||
|     public tier5appearance; | ||||
|     public tier6appearance; | ||||
|     public tier7appearance; | ||||
| 
 | ||||
|     public tiers = [ | ||||
|         { | ||||
|             tier: 1, | ||||
|             playerMinimumLevel: 1, | ||||
|             playerMaximumLevel: 10, | ||||
|             botMinLevelVariance: 10, | ||||
|             botMaxLevelVariance: 5, | ||||
|             scavMinLevelVariance: 10, | ||||
|             scavMaxLevelVariance: 5 | ||||
|         }, | ||||
|         { | ||||
|             tier: 2, | ||||
|             playerMinimumLevel: 11, | ||||
|             playerMaximumLevel: 20, | ||||
|             botMinLevelVariance: 10, | ||||
|             botMaxLevelVariance: 5, | ||||
|             scavMinLevelVariance: 10, | ||||
|             scavMaxLevelVariance: 5 | ||||
|         }, | ||||
|         { | ||||
|             tier: 3, | ||||
|             playerMinimumLevel: 21, | ||||
|             playerMaximumLevel: 30, | ||||
|             botMinLevelVariance: 15, | ||||
|             botMaxLevelVariance: 7, | ||||
|             scavMinLevelVariance: 15, | ||||
|             scavMaxLevelVariance: 7 | ||||
|         }, | ||||
|         { | ||||
|             tier: 4, | ||||
|             playerMinimumLevel: 31, | ||||
|             playerMaximumLevel: 40, | ||||
|             botMinLevelVariance: 20, | ||||
|             botMaxLevelVariance: 10, | ||||
|             scavMinLevelVariance: 20, | ||||
|             scavMaxLevelVariance: 10 | ||||
|         }, | ||||
|         { | ||||
|             tier: 5, | ||||
|             playerMinimumLevel: 41, | ||||
|             playerMaximumLevel: 50, | ||||
|             botMinLevelVariance: 30, | ||||
|             botMaxLevelVariance: 15, | ||||
|             scavMinLevelVariance: 30, | ||||
|             scavMaxLevelVariance: 15 | ||||
|         }, | ||||
|         { | ||||
|             tier: 6, | ||||
|             playerMinimumLevel: 51, | ||||
|             playerMaximumLevel: 60, | ||||
|             botMinLevelVariance: 40, | ||||
|             botMaxLevelVariance: 20, | ||||
|             scavMinLevelVariance: 40, | ||||
|             scavMaxLevelVariance: 20 | ||||
|         }, | ||||
|         { | ||||
|             tier: 7, | ||||
|             playerMinimumLevel: 61, | ||||
|             playerMaximumLevel: 100, | ||||
|             botMinLevelVariance: 50, | ||||
|             botMaxLevelVariance: 20, | ||||
|             scavMinLevelVariance: 50, | ||||
|             scavMaxLevelVariance: 20 | ||||
|         } | ||||
|     ] | ||||
| 
 | ||||
|     public armorPlateWeights = [ | ||||
|         { | ||||
|             "levelRange": { | ||||
|                 "min": 1, | ||||
|                 "max": 10 | ||||
|             }, | ||||
|             "front_plate": { | ||||
|                 "2": 10, | ||||
|                 "3": 80, | ||||
|                 "4": 10 | ||||
|             }, | ||||
|             "back_plate": { | ||||
|                 "2": 10, | ||||
|                 "3": 80, | ||||
|                 "4": 10 | ||||
|             }, | ||||
|             "side_plate": { | ||||
|                 "2": 10, | ||||
|                 "3": 80, | ||||
|                 "4": 10 | ||||
|             }, | ||||
|             "left_side_plate": { | ||||
|                 "2": 10, | ||||
|                 "3": 80, | ||||
|                 "4": 10 | ||||
|             }, | ||||
|             "right_side_plate": { | ||||
|                 "2": 10, | ||||
|                 "3": 80, | ||||
|                 "4": 10 | ||||
|             } | ||||
|         }, | ||||
|         { | ||||
|             "levelRange": { | ||||
|                 "min": 11, | ||||
|                 "max": 20 | ||||
|             }, | ||||
|             "front_plate": { | ||||
|                 "3": 65, | ||||
|                 "4": 32, | ||||
|                 "5": 3 | ||||
|             }, | ||||
|             "back_plate": { | ||||
|                 "3": 65, | ||||
|                 "4": 32, | ||||
|                 "5": 3 | ||||
|             }, | ||||
|             "side_plate": { | ||||
|                 "3": 65, | ||||
|                 "4": 32, | ||||
|                 "5": 3 | ||||
|             }, | ||||
|             "left_side_plate": { | ||||
|                 "3": 65, | ||||
|                 "4": 32, | ||||
|                 "5": 3 | ||||
|             }, | ||||
|             "right_side_plate": { | ||||
|                 "3": 65, | ||||
|                 "4": 32, | ||||
|                 "5": 3 | ||||
|             } | ||||
|         }, | ||||
|         { | ||||
|             "levelRange": { | ||||
|                 "min": 21, | ||||
|                 "max": 30 | ||||
|             }, | ||||
|             "front_plate": { | ||||
|                 "3": 15, | ||||
|                 "4": 70, | ||||
|                 "5": 10, | ||||
|                 "6": 5 | ||||
|             }, | ||||
|             "back_plate": { | ||||
|                 "3": 15, | ||||
|                 "4": 70, | ||||
|                 "5": 10, | ||||
|                 "6": 5 | ||||
|             }, | ||||
|             "side_plate": { | ||||
|                 "3": 15, | ||||
|                 "4": 70, | ||||
|                 "5": 10, | ||||
|                 "6": 5 | ||||
|             }, | ||||
|             "left_side_plate": { | ||||
|                 "3": 15, | ||||
|                 "4": 70, | ||||
|                 "5": 10, | ||||
|                 "6": 5 | ||||
|             }, | ||||
|             "right_side_plate": { | ||||
|                 "3": 15, | ||||
|                 "4": 70, | ||||
|                 "5": 10, | ||||
|                 "6": 5 | ||||
|             } | ||||
|         }, | ||||
|         { | ||||
|             "levelRange": { | ||||
|                 "min": 31, | ||||
|                 "max": 40 | ||||
|             }, | ||||
|             "front_plate": { | ||||
|                 "4": 30, | ||||
|                 "5": 50, | ||||
|                 "6": 20 | ||||
|             }, | ||||
|             "back_plate": { | ||||
|                 "4": 30, | ||||
|                 "5": 50, | ||||
|                 "6": 20 | ||||
|             }, | ||||
|             "side_plate": { | ||||
|                 "4": 30, | ||||
|                 "5": 50, | ||||
|                 "6": 20 | ||||
|             }, | ||||
|             "left_side_plate": { | ||||
|                 "4": 30, | ||||
|                 "5": 50, | ||||
|                 "6": 20 | ||||
|             }, | ||||
|             "right_side_plate": { | ||||
|                 "4": 30, | ||||
|                 "5": 50, | ||||
|                 "6": 20 | ||||
|             } | ||||
|         }, | ||||
|         { | ||||
|             "levelRange": { | ||||
|                 "min": 41, | ||||
|                 "max": 50 | ||||
|             }, | ||||
|             "front_plate": { | ||||
|                 "4": 10, | ||||
|                 "5": 45, | ||||
|                 "6": 45 | ||||
|             }, | ||||
|             "back_plate": { | ||||
|                 "4": 10, | ||||
|                 "5": 45, | ||||
|                 "6": 45 | ||||
|             }, | ||||
|             "side_plate": { | ||||
|                 "4": 10, | ||||
|                 "5": 45, | ||||
|                 "6": 45 | ||||
|             }, | ||||
|             "left_side_plate": { | ||||
|                 "4": 10, | ||||
|                 "5": 45, | ||||
|                 "6": 45 | ||||
|             }, | ||||
|             "right_side_plate": { | ||||
|                 "4": 10, | ||||
|                 "5": 45, | ||||
|                 "6": 45 | ||||
|             } | ||||
|         }, | ||||
|         { | ||||
|             "levelRange": { | ||||
|                 "min": 51, | ||||
|                 "max": 60 | ||||
|             }, | ||||
|             "front_plate": { | ||||
|                 "4": 5, | ||||
|                 "5": 30, | ||||
|                 "6": 65 | ||||
|             }, | ||||
|             "back_plate": { | ||||
|                 "4": 5, | ||||
|                 "5": 30, | ||||
|                 "6": 65 | ||||
|             }, | ||||
|             "side_plate": { | ||||
|                 "4": 5, | ||||
|                 "5": 30, | ||||
|                 "6": 65 | ||||
|             }, | ||||
|             "left_side_plate": { | ||||
|                 "4": 5, | ||||
|                 "5": 30, | ||||
|                 "6": 65 | ||||
|             }, | ||||
|             "right_side_plate": { | ||||
|                 "4": 5, | ||||
|                 "5": 30, | ||||
|                 "6": 65 | ||||
|             } | ||||
|         }, | ||||
|         { | ||||
|             "levelRange": { | ||||
|                 "min": 61, | ||||
|                 "max": 100 | ||||
|             }, | ||||
|             "front_plate": { | ||||
|                 "4": 1, | ||||
|                 "5": 19, | ||||
|                 "6": 80 | ||||
|             }, | ||||
|             "back_plate": { | ||||
|                 "4": 1, | ||||
|                 "5": 19, | ||||
|                 "6": 80 | ||||
|             }, | ||||
|             "side_plate": { | ||||
|                 "4": 1, | ||||
|                 "5": 19, | ||||
|                 "6": 80 | ||||
|             }, | ||||
|             "left_side_plate": { | ||||
|                 "4": 1, | ||||
|                 "5": 19, | ||||
|                 "6": 80 | ||||
|             }, | ||||
|             "right_side_plate": { | ||||
|                 "4": 1, | ||||
|                 "5": 19, | ||||
|                 "6": 80 | ||||
|             } | ||||
|         } | ||||
|     ] | ||||
| 
 | ||||
|     public scavArmorPlateWeights = [ | ||||
|         { | ||||
|             "levelRange": { | ||||
|                 "min": 1, | ||||
|                 "max": 100 | ||||
|             }, | ||||
|             "front_plate": { | ||||
|                 "2": 15, | ||||
|                 "3": 35, | ||||
|                 "4": 5 | ||||
|             }, | ||||
|             "back_plate": { | ||||
|                 "2": 15, | ||||
|                 "3": 35, | ||||
|                 "4": 5 | ||||
|             }, | ||||
|             "side_plate": { | ||||
|                 "2": 15, | ||||
|                 "3": 35, | ||||
|                 "4": 5 | ||||
|             }, | ||||
|             "left_side_plate": { | ||||
|                 "2": 15, | ||||
|                 "3": 35, | ||||
|                 "4": 5 | ||||
|             }, | ||||
|             "right_side_plate": { | ||||
|                 "2": 15, | ||||
|                 "3": 35, | ||||
|                 "4": 5 | ||||
|             } | ||||
|         } | ||||
|     ] | ||||
| } | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							|  | @ -0,0 +1,275 @@ | |||
| import { injectable, inject } from "tsyringe"; | ||||
| import { APBSEquipmentGetter } from "../Utils/APBSEquipmentGetter"; | ||||
| import { ITemplateItem } from "@spt/models/eft/common/tables/ITemplateItem"; | ||||
| import { DatabaseService } from "@spt/services/DatabaseService"; | ||||
| import { APBSLogger } from "../Utils/APBSLogger"; | ||||
| import { Logging } from "../Enums/Logging"; | ||||
| import { ModConfig } from "../Globals/ModConfig"; | ||||
| 
 | ||||
| @injectable() | ||||
| export class BlacklistHelper | ||||
| { | ||||
|     constructor( | ||||
|         @inject("DatabaseService") protected database: DatabaseService, | ||||
|         @inject("APBSEquipmentGetter") protected apbsEquipmentGetter: APBSEquipmentGetter, | ||||
|         @inject("APBSLogger") protected apbsLogger: APBSLogger | ||||
|     ) | ||||
|     {} | ||||
| 
 | ||||
|     private invalidAmmoIDs: string[] = []; | ||||
|     private invalidEquipmentIDs: string[] = []; | ||||
|     private invalidWeaponIDs: string[] = []; | ||||
|     private invalidAttachmentIDs: string[] = []; | ||||
| 
 | ||||
|     public initialize(): void | ||||
|     { | ||||
|         if (ModConfig.config.tier1AmmoBlacklist.length > 0) this.removeBlacklistedAmmo(ModConfig.config.tier1AmmoBlacklist, 1); | ||||
|         if (ModConfig.config.tier2AmmoBlacklist.length > 0) this.removeBlacklistedAmmo(ModConfig.config.tier2AmmoBlacklist, 2); | ||||
|         if (ModConfig.config.tier3AmmoBlacklist.length > 0) this.removeBlacklistedAmmo(ModConfig.config.tier3AmmoBlacklist, 3); | ||||
|         if (ModConfig.config.tier4AmmoBlacklist.length > 0) this.removeBlacklistedAmmo(ModConfig.config.tier4AmmoBlacklist, 4); | ||||
|         if (ModConfig.config.tier5AmmoBlacklist.length > 0) this.removeBlacklistedAmmo(ModConfig.config.tier5AmmoBlacklist, 5); | ||||
|         if (ModConfig.config.tier6AmmoBlacklist.length > 0) this.removeBlacklistedAmmo(ModConfig.config.tier6AmmoBlacklist, 6); | ||||
|         if (ModConfig.config.tier7AmmoBlacklist.length > 0) this.removeBlacklistedAmmo(ModConfig.config.tier7AmmoBlacklist, 7); | ||||
|         if (ModConfig.config.tier1EquipmentBlacklist.length > 0) this.removeBlacklistedEquipment(ModConfig.config.tier1EquipmentBlacklist, 1); | ||||
|         if (ModConfig.config.tier2EquipmentBlacklist.length > 0) this.removeBlacklistedEquipment(ModConfig.config.tier2EquipmentBlacklist, 2); | ||||
|         if (ModConfig.config.tier3EquipmentBlacklist.length > 0) this.removeBlacklistedEquipment(ModConfig.config.tier3EquipmentBlacklist, 3); | ||||
|         if (ModConfig.config.tier4EquipmentBlacklist.length > 0) this.removeBlacklistedEquipment(ModConfig.config.tier4EquipmentBlacklist, 4); | ||||
|         if (ModConfig.config.tier5EquipmentBlacklist.length > 0) this.removeBlacklistedEquipment(ModConfig.config.tier5EquipmentBlacklist, 5); | ||||
|         if (ModConfig.config.tier6EquipmentBlacklist.length > 0) this.removeBlacklistedEquipment(ModConfig.config.tier6EquipmentBlacklist, 6); | ||||
|         if (ModConfig.config.tier7EquipmentBlacklist.length > 0) this.removeBlacklistedEquipment(ModConfig.config.tier7EquipmentBlacklist, 7); | ||||
|         if (ModConfig.config.tier1WeaponBlacklist.length > 0) this.removeBlacklistedWeapons(ModConfig.config.tier1WeaponBlacklist, 1); | ||||
|         if (ModConfig.config.tier2WeaponBlacklist.length > 0) this.removeBlacklistedWeapons(ModConfig.config.tier2WeaponBlacklist, 2); | ||||
|         if (ModConfig.config.tier3WeaponBlacklist.length > 0) this.removeBlacklistedWeapons(ModConfig.config.tier3WeaponBlacklist, 3); | ||||
|         if (ModConfig.config.tier4WeaponBlacklist.length > 0) this.removeBlacklistedWeapons(ModConfig.config.tier4WeaponBlacklist, 4); | ||||
|         if (ModConfig.config.tier5WeaponBlacklist.length > 0) this.removeBlacklistedWeapons(ModConfig.config.tier5WeaponBlacklist, 5); | ||||
|         if (ModConfig.config.tier6WeaponBlacklist.length > 0) this.removeBlacklistedWeapons(ModConfig.config.tier6WeaponBlacklist, 6); | ||||
|         if (ModConfig.config.tier7WeaponBlacklist.length > 0) this.removeBlacklistedWeapons(ModConfig.config.tier7WeaponBlacklist, 7); | ||||
|         if (ModConfig.config.tier1AttachmentBlacklist.length > 0) this.removeBlacklistedAttachments(ModConfig.config.tier1AttachmentBlacklist, 1); | ||||
|         if (ModConfig.config.tier2AttachmentBlacklist.length > 0) this.removeBlacklistedAttachments(ModConfig.config.tier2AttachmentBlacklist, 2); | ||||
|         if (ModConfig.config.tier3AttachmentBlacklist.length > 0) this.removeBlacklistedAttachments(ModConfig.config.tier3AttachmentBlacklist, 3); | ||||
|         if (ModConfig.config.tier4AttachmentBlacklist.length > 0) this.removeBlacklistedAttachments(ModConfig.config.tier4AttachmentBlacklist, 4); | ||||
|         if (ModConfig.config.tier5AttachmentBlacklist.length > 0) this.removeBlacklistedAttachments(ModConfig.config.tier5AttachmentBlacklist, 5); | ||||
|         if (ModConfig.config.tier6AttachmentBlacklist.length > 0) this.removeBlacklistedAttachments(ModConfig.config.tier6AttachmentBlacklist, 6); | ||||
|         if (ModConfig.config.tier7AttachmentBlacklist.length > 0) this.removeBlacklistedAttachments(ModConfig.config.tier7AttachmentBlacklist, 7); | ||||
| 
 | ||||
|         this.validateBlacklist(); | ||||
|     } | ||||
| 
 | ||||
|     private removeBlacklistedAmmo(ammoBlacklist: string[], tier: number): void | ||||
|     { | ||||
|         const tierJSON = this.apbsEquipmentGetter.getTierAmmoJson(tier, true); | ||||
|         for (const item in ammoBlacklist) | ||||
|         { | ||||
|             const itemDetails = this.getItem(ammoBlacklist[item]) | ||||
|             if (itemDetails != undefined && itemDetails._parent == "5485a8684bdc2da71d8b4567") | ||||
|             { | ||||
|                 for (const botType in tierJSON) | ||||
|                 { | ||||
|                     for (const ammo in tierJSON[botType]) | ||||
|                     { | ||||
|                         if (Object.keys(tierJSON[botType][ammo]).includes(itemDetails._id)) | ||||
|                         { | ||||
|                             if (Object.keys(tierJSON[botType][ammo]).length > 1) | ||||
|                             { | ||||
|                                 delete tierJSON[botType][ammo][itemDetails._id] | ||||
|                                 this.apbsLogger.log(Logging.DEBUG, `[Tier${tier}] Removed "${itemDetails._id}" from "${botType}" ${ammo} pool.`) | ||||
|                                 continue; | ||||
|                             } | ||||
|                             this.apbsLogger.log(Logging.WARN, `Did not blacklist "${itemDetails._id}" as it would make the Tier${tier} "${botType}" ${ammo} pool empty`) | ||||
|                             continue; | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|             if (itemDetails == undefined || itemDetails._parent != "5485a8684bdc2da71d8b4567") | ||||
|             { | ||||
|                 if (!this.invalidAmmoIDs.includes(ammoBlacklist[item])) this.invalidAmmoIDs.push(ammoBlacklist[item]) | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private removeBlacklistedEquipment(equipmentBlacklist: string[], tier: number): void | ||||
|     { | ||||
|         const tierJSON = this.apbsEquipmentGetter.getTierJson(tier, true); | ||||
|         for (const item in equipmentBlacklist) | ||||
|         { | ||||
|             const itemDetails = this.getItem(equipmentBlacklist[item]) | ||||
|             if (itemDetails != undefined) | ||||
|             { | ||||
|                 for (const botType in tierJSON) | ||||
|                 { | ||||
|                     for (const equipmentSlot in tierJSON[botType].equipment) | ||||
|                     { | ||||
|                         if (Object.keys(tierJSON[botType].equipment[equipmentSlot]).includes(itemDetails._id)) | ||||
|                         { | ||||
|                             if (Object.keys(tierJSON[botType].equipment[equipmentSlot]).length > 1) | ||||
|                             { | ||||
|                                 delete tierJSON[botType].equipment[equipmentSlot][itemDetails._id] | ||||
|                                 this.apbsLogger.log(Logging.DEBUG, `[Tier${tier}] Removed "${itemDetails._id}" from "${botType}" ${equipmentSlot} pool.`) | ||||
|                                 continue; | ||||
|                             } | ||||
|                             this.apbsLogger.log(Logging.WARN, `Did not blacklist "${itemDetails._id}" as it would make the Tier${tier} "${botType}" ${equipmentSlot} pool empty.`) | ||||
|                             continue; | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|             if (itemDetails == undefined) | ||||
|             { | ||||
|                 if (!this.invalidEquipmentIDs.includes(equipmentBlacklist[item])) this.invalidEquipmentIDs.push(equipmentBlacklist[item]) | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private removeBlacklistedWeapons(weaponBlacklist: string[], tier: number): void | ||||
|     { | ||||
|         const tierJSON = this.apbsEquipmentGetter.getTierJson(tier, true); | ||||
|         for (const item in weaponBlacklist) | ||||
|         { | ||||
|             const itemDetails = this.getItem(weaponBlacklist[item]) | ||||
|             if (itemDetails != undefined) | ||||
|             { | ||||
|                 for (const botType in tierJSON) | ||||
|                 { | ||||
|                     for (const equipmentSlot in tierJSON[botType].equipment.FirstPrimaryWeapon) | ||||
|                     { | ||||
|                         if (Object.keys(tierJSON[botType].equipment.FirstPrimaryWeapon[equipmentSlot]).includes(itemDetails._id)) | ||||
|                         { | ||||
|                             if (Object.keys(tierJSON[botType].equipment.FirstPrimaryWeapon[equipmentSlot]).length > 1) | ||||
|                             { | ||||
|                                 delete tierJSON[botType].equipment.FirstPrimaryWeapon[equipmentSlot][itemDetails._id] | ||||
|                                 this.apbsLogger.log(Logging.DEBUG, `[Tier${tier}] Removed "${itemDetails._id}" from "${botType}" ${equipmentSlot} pool.`) | ||||
|                                 continue; | ||||
|                             } | ||||
|                             this.apbsLogger.log(Logging.WARN, `Did not blacklist "${itemDetails._id}" as it would make the Tier${tier} "${botType}" ${equipmentSlot} pool empty.`) | ||||
|                             continue; | ||||
|                         } | ||||
|                     } | ||||
|                     for (const equipmentSlot in tierJSON[botType].equipment.SecondPrimaryWeapon) | ||||
|                     { | ||||
|                         if (Object.keys(tierJSON[botType].equipment.SecondPrimaryWeapon[equipmentSlot]).includes(itemDetails._id)) | ||||
|                         { | ||||
|                             if (Object.keys(tierJSON[botType].equipment.SecondPrimaryWeapon[equipmentSlot]).length > 1) | ||||
|                             { | ||||
|                                 delete tierJSON[botType].equipment.SecondPrimaryWeapon[equipmentSlot][itemDetails._id] | ||||
|                                 this.apbsLogger.log(Logging.DEBUG, `[Tier${tier}] Removed "${itemDetails._id}" from "${botType}" ${equipmentSlot} pool.`) | ||||
|                                 continue; | ||||
|                             } | ||||
|                             this.apbsLogger.log(Logging.WARN, `Did not blacklist "${itemDetails._id}" as it would make the Tier${tier} "${botType}" ${equipmentSlot} pool empty.`) | ||||
|                             continue; | ||||
|                         } | ||||
|                     } | ||||
|                     if (Object.keys(tierJSON[botType].equipment.Holster).includes(itemDetails._id)) | ||||
|                     { | ||||
|                         if (Object.keys(tierJSON[botType].equipment.Holster).length > 1) | ||||
|                         { | ||||
|                             delete tierJSON[botType].equipment.Holster[itemDetails._id] | ||||
|                             this.apbsLogger.log(Logging.DEBUG, `[Tier${tier}] Removed "${itemDetails._id}" from "${botType}" Holster pool.`) | ||||
|                             continue; | ||||
|                         } | ||||
|                         this.apbsLogger.log(Logging.WARN, `Did not blacklist "${itemDetails._id}" as it would make the Tier${tier} "${botType}" Holster pool empty.`) | ||||
|                         continue; | ||||
|                     } | ||||
|                     if (Object.keys(tierJSON[botType].equipment.Scabbard).includes(itemDetails._id)) | ||||
|                     { | ||||
|                         if (Object.keys(tierJSON[botType].equipment.Scabbard).length > 1) | ||||
|                         { | ||||
|                             delete tierJSON[botType].equipment.Scabbard[itemDetails._id] | ||||
|                             this.apbsLogger.log(Logging.DEBUG, `[Tier${tier}] Removed "${itemDetails._id}" from "${botType}" Scabbard pool.`) | ||||
|                             continue; | ||||
|                         } | ||||
|                         this.apbsLogger.log(Logging.WARN, `Did not blacklist "${itemDetails._id}" as it would make the Tier${tier} "${botType}" Scabbard pool empty.`) | ||||
|                         continue; | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|             if (itemDetails == undefined) | ||||
|             { | ||||
|                 if (!this.invalidWeaponIDs.includes(weaponBlacklist[item])) this.invalidWeaponIDs.push(weaponBlacklist[item]) | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private removeBlacklistedAttachments(attachmentBlacklist: string[], tier: number): void | ||||
|     { | ||||
|         const tierJSON = this.apbsEquipmentGetter.getTierModsJson(tier, true); | ||||
|         for (const item in attachmentBlacklist) | ||||
|         { | ||||
|             const itemDetails = this.getItem(attachmentBlacklist[item]) | ||||
|             if (itemDetails != undefined) | ||||
|             { | ||||
|                 for (const parentID in tierJSON) | ||||
|                 { | ||||
|                     const parentItemName = this.getItem(parentID); | ||||
|                     const parentItemID = tierJSON[parentID] | ||||
|                     for (const slotName in parentItemID) | ||||
|                     { | ||||
|                         const itemSlotName = tierJSON[parentID][slotName] | ||||
|                         if (itemSlotName.includes(itemDetails._id)) | ||||
|                         { | ||||
|                             if (itemSlotName.length == 1) | ||||
|                             { | ||||
|                                 delete tierJSON[parentID][slotName]; | ||||
|                                 this.apbsLogger.log(Logging.DEBUG, `[Tier${tier}] Removed slot "${slotName}" from "${parentItemName._name}" because array is now empty.`); | ||||
|                                 continue; | ||||
|                             } | ||||
|                             const index = itemSlotName.indexOf(itemDetails._id); | ||||
|                             if (index > -1) | ||||
|                             { | ||||
|                                 itemSlotName.splice(index, 1) | ||||
|                                 this.apbsLogger.log(Logging.DEBUG, `[Tier${tier}] Removed "${itemDetails._id}" from "${parentItemName._name}" slot "${slotName}".`); | ||||
|                                 continue; | ||||
|                             } | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|             if (itemDetails == undefined) | ||||
|             { | ||||
|                 if (!this.invalidAttachmentIDs.includes(attachmentBlacklist[item])) this.invalidAttachmentIDs.push(attachmentBlacklist[item]) | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|      | ||||
|     private getItem(tpl: string): ITemplateItem | ||||
|     { | ||||
|         if (tpl in this.database.getItems()) | ||||
|         { | ||||
|             return this.database.getItems()[tpl]; | ||||
|         } | ||||
| 
 | ||||
|         return undefined; | ||||
|     } | ||||
| 
 | ||||
|     private validateBlacklist(): void | ||||
|     { | ||||
|         if (this.invalidAmmoIDs.length > 0)  | ||||
|         { | ||||
|             for (const item in this.invalidAmmoIDs) | ||||
|             { | ||||
|                 this.apbsLogger.log(Logging.WARN, `"${this.invalidAmmoIDs[item]}" in Ammo Blacklist is an invalid item ID.`) | ||||
|             } | ||||
|         } | ||||
|         if (this.invalidEquipmentIDs.length > 0)  | ||||
|         { | ||||
|             for (const item in this.invalidEquipmentIDs) | ||||
|             { | ||||
|                 this.apbsLogger.log(Logging.WARN, `"${this.invalidEquipmentIDs[item]}" in Equipment Blacklist is an invalid item ID.`) | ||||
|             } | ||||
|         } | ||||
|         if (this.invalidWeaponIDs.length > 0)  | ||||
|         { | ||||
|             for (const item in this.invalidWeaponIDs) | ||||
|             { | ||||
|                 this.apbsLogger.log(Logging.WARN, `"${this.invalidWeaponIDs[item]}" in Weapon Blacklist is an invalid item ID.`) | ||||
|             } | ||||
|         } | ||||
|         if (this.invalidAttachmentIDs.length > 0)  | ||||
|         { | ||||
|             for (const item in this.invalidAttachmentIDs) | ||||
|             { | ||||
|                 this.apbsLogger.log(Logging.WARN, `"${this.invalidAttachmentIDs[item]}" in Attachment Blacklist is an invalid item ID.`) | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,328 @@ | |||
| import { injectable, inject } from "tsyringe"; | ||||
| import * as path from "path"; | ||||
| import * as fs from "fs"; | ||||
| 
 | ||||
| import { TierInformation } from "../Globals/TierInformation"; | ||||
| import { RaidInformation } from "../Globals/RaidInformation"; | ||||
| import { APBSLogger } from "../Utils/APBSLogger"; | ||||
| import { Logging } from "../Enums/Logging"; | ||||
| 
 | ||||
| import Tier0equipment = require("../db/Tier0_equipment.json"); | ||||
| import Tier1equipment = require("../db/Tier1_equipment.json"); | ||||
| import Tier2equipment = require("../db/Tier2_equipment.json"); | ||||
| import Tier3equipment = require("../db/Tier3_equipment.json"); | ||||
| import Tier4equipment = require("../db/Tier4_equipment.json"); | ||||
| import Tier5equipment = require("../db/Tier5_equipment.json"); | ||||
| import Tier6equipment = require("../db/Tier6_equipment.json"); | ||||
| import Tier7equipment = require("../db/Tier7_equipment.json"); | ||||
| 
 | ||||
| import Tier0mods = require("../db/Tier0_mods.json"); | ||||
| import Tier1mods = require("../db/Tier1_mods.json"); | ||||
| import Tier2mods = require("../db/Tier2_mods.json"); | ||||
| import Tier3mods = require("../db/Tier3_mods.json"); | ||||
| import Tier4mods = require("../db/Tier4_mods.json"); | ||||
| import Tier5mods = require("../db/Tier5_mods.json"); | ||||
| import Tier6mods = require("../db/Tier6_mods.json"); | ||||
| import Tier7mods = require("../db/Tier7_mods.json"); | ||||
| 
 | ||||
| import Tier0chances = require("../db/Tier0_chances.json"); | ||||
| import Tier1chances = require("../db/Tier1_chances.json"); | ||||
| import Tier2chances = require("../db/Tier2_chances.json"); | ||||
| import Tier3chances = require("../db/Tier3_chances.json"); | ||||
| import Tier4chances = require("../db/Tier4_chances.json"); | ||||
| import Tier5chances = require("../db/Tier5_chances.json"); | ||||
| import Tier6chances = require("../db/Tier6_chances.json"); | ||||
| import Tier7chances = require("../db/Tier7_chances.json"); | ||||
| 
 | ||||
| import Tier0ammo = require("../db/Tier0_ammo.json"); | ||||
| import Tier1ammo = require("../db/Tier1_ammo.json"); | ||||
| import Tier2ammo = require("../db/Tier2_ammo.json"); | ||||
| import Tier3ammo = require("../db/Tier3_ammo.json"); | ||||
| import Tier4ammo = require("../db/Tier4_ammo.json"); | ||||
| import Tier5ammo = require("../db/Tier5_ammo.json"); | ||||
| import Tier6ammo = require("../db/Tier6_ammo.json"); | ||||
| import Tier7ammo = require("../db/Tier7_ammo.json"); | ||||
| 
 | ||||
| import Tier0appearance = require("../db/Tier0_appearance.json"); | ||||
| import Tier1appearance = require("../db/Tier1_appearance.json"); | ||||
| import Tier2appearance = require("../db/Tier2_appearance.json"); | ||||
| import Tier3appearance = require("../db/Tier3_appearance.json"); | ||||
| import Tier4appearance = require("../db/Tier4_appearance.json"); | ||||
| import Tier5appearance = require("../db/Tier5_appearance.json"); | ||||
| import Tier6appearance = require("../db/Tier6_appearance.json"); | ||||
| import Tier7appearance = require("../db/Tier7_appearance.json"); | ||||
| 
 | ||||
| @injectable() | ||||
| export class JSONHelper | ||||
| { | ||||
|     count: number; | ||||
|     constructor( | ||||
|         @inject("TierInformation") protected tierInformation: TierInformation, | ||||
|         @inject("RaidInformation") protected raidInformation: RaidInformation, | ||||
|         @inject("APBSLogger") protected apbsLogger: APBSLogger | ||||
|     ) | ||||
|     { | ||||
|         this.count = 0 | ||||
|     } | ||||
| 
 | ||||
|     public buildTierJson(): void | ||||
|     { | ||||
|         this.tierInformation.tier0 = Tier0equipment; | ||||
|         this.tierInformation.tier1 = Tier1equipment; | ||||
|         this.tierInformation.tier2 = Tier2equipment; | ||||
|         this.tierInformation.tier3 = Tier3equipment; | ||||
|         this.tierInformation.tier4 = Tier4equipment; | ||||
|         this.tierInformation.tier5 = Tier5equipment; | ||||
|         this.tierInformation.tier6 = Tier6equipment; | ||||
|         this.tierInformation.tier7 = Tier7equipment; | ||||
| 
 | ||||
|         this.tierInformation.tier0mods = Tier0mods; | ||||
|         this.tierInformation.tier1mods = Tier1mods; | ||||
|         this.tierInformation.tier2mods = Tier2mods; | ||||
|         this.tierInformation.tier3mods = Tier3mods; | ||||
|         this.tierInformation.tier4mods = Tier4mods; | ||||
|         this.tierInformation.tier5mods = Tier5mods; | ||||
|         this.tierInformation.tier6mods = Tier6mods; | ||||
|         this.tierInformation.tier7mods = Tier7mods; | ||||
| 
 | ||||
|         this.tierInformation.tier0chances = Tier0chances; | ||||
|         this.tierInformation.tier1chances = Tier1chances; | ||||
|         this.tierInformation.tier2chances = Tier2chances; | ||||
|         this.tierInformation.tier3chances = Tier3chances; | ||||
|         this.tierInformation.tier4chances = Tier4chances; | ||||
|         this.tierInformation.tier5chances = Tier5chances; | ||||
|         this.tierInformation.tier6chances = Tier6chances; | ||||
|         this.tierInformation.tier7chances = Tier7chances; | ||||
| 
 | ||||
|         this.tierInformation.tier0ammo = Tier0ammo; | ||||
|         this.tierInformation.tier1ammo = Tier1ammo; | ||||
|         this.tierInformation.tier2ammo = Tier2ammo; | ||||
|         this.tierInformation.tier3ammo = Tier3ammo; | ||||
|         this.tierInformation.tier4ammo = Tier4ammo; | ||||
|         this.tierInformation.tier5ammo = Tier5ammo; | ||||
|         this.tierInformation.tier6ammo = Tier6ammo; | ||||
|         this.tierInformation.tier7ammo = Tier7ammo; | ||||
| 
 | ||||
|         this.tierInformation.tier0appearance = Tier0appearance; | ||||
|         this.tierInformation.tier1appearance = Tier1appearance; | ||||
|         this.tierInformation.tier2appearance = Tier2appearance; | ||||
|         this.tierInformation.tier3appearance = Tier3appearance; | ||||
|         this.tierInformation.tier4appearance = Tier4appearance; | ||||
|         this.tierInformation.tier5appearance = Tier5appearance; | ||||
|         this.tierInformation.tier6appearance = Tier6appearance; | ||||
|         this.tierInformation.tier7appearance = Tier7appearance; | ||||
|     } | ||||
| 
 | ||||
|     public usePreset(presetName: string): void | ||||
|     { | ||||
|         const folderName = presetName; | ||||
|         const presetFolder = path.join(path.dirname(__filename), "..", "..", "presets"); | ||||
|         const folderPath = path.join(presetFolder, folderName); | ||||
| 
 | ||||
|         if (!fs.existsSync(folderPath))  | ||||
|         { | ||||
|             this.missingPresetFolder(folderName, presetFolder); | ||||
|             return; | ||||
|         } | ||||
|         const files = fs.readdirSync(folderPath); | ||||
|         if (files.length < 35) | ||||
|         { | ||||
|             this.missingFileCount(folderName, 0); | ||||
|             return; | ||||
|         } | ||||
|         if (files.length > 35) | ||||
|         { | ||||
|             this.missingFileCount(folderName, 1); | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         this.raidInformation.usingDefaultDB = false; | ||||
|         for (const item of files) | ||||
|         { | ||||
|             const filePath = path.join(folderPath, item); | ||||
|             this.mapFileToTierType(filePath, folderName, item) | ||||
|         } | ||||
|          | ||||
|         if (this.count == 35) this.apbsLogger.log(Logging.WARN, `"${folderName}" preset loaded...`); | ||||
|     } | ||||
| 
 | ||||
|     private mapFileToTierType(filePath: string, folderName: string,  item: string): void | ||||
|     { | ||||
|         let tier = 0; | ||||
|         let type = "none"; | ||||
|         if (item.includes("1")) tier = 1; | ||||
|         if (item.includes("2")) tier = 2; | ||||
|         if (item.includes("3")) tier = 3; | ||||
|         if (item.includes("4")) tier = 4; | ||||
|         if (item.includes("5")) tier = 5; | ||||
|         if (item.includes("6")) tier = 6; | ||||
|         if (item.includes("7")) tier = 7; | ||||
| 
 | ||||
|         if (tier == 0)  | ||||
|         { | ||||
|             this.invalidFileName(folderName, item); | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         if (item.includes("equipment")) type = "equipment"; | ||||
|         if (item.includes("mods")) type = "mods"; | ||||
|         if (item.includes("chances")) type = "chances"; | ||||
|         if (item.includes("ammo")) type = "ammo"; | ||||
|         if (item.includes("appearance")) type = "appearance"; | ||||
| 
 | ||||
|         if (type == "none")  | ||||
|         { | ||||
|             this.invalidFileName(folderName, item); | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         this.configureTierType(filePath, tier, type); | ||||
|     } | ||||
| 
 | ||||
|     private configureTierType(filePath: string, tier: number, type: string):void | ||||
|     { | ||||
|         this.count++; | ||||
|         this.tierInformation.tier0 = Tier0equipment; | ||||
|         this.tierInformation.tier0mods = Tier0mods; | ||||
|         this.tierInformation.tier0chances = Tier0chances; | ||||
|         this.tierInformation.tier0ammo = Tier0ammo; | ||||
|         this.tierInformation.tier0appearance = Tier0appearance; | ||||
| 
 | ||||
|         switch (true)  | ||||
|         { | ||||
|             case tier == 1 && type == "equipment":  | ||||
|                 this.tierInformation.tier1 = require(filePath); | ||||
|                 return; | ||||
|             case tier == 2 && type == "equipment":  | ||||
|                 this.tierInformation.tier2 = require(filePath); | ||||
|                 return; | ||||
|             case tier == 3 && type == "equipment": | ||||
|                 this.tierInformation.tier3 = require(filePath); | ||||
|                 return; | ||||
|             case tier == 4 && type == "equipment": | ||||
|                 this.tierInformation.tier4 = require(filePath); | ||||
|                 return; | ||||
|             case tier == 5 && type == "equipment": | ||||
|                 this.tierInformation.tier5 = require(filePath); | ||||
|                 return; | ||||
|             case tier == 6 && type == "equipment": | ||||
|                 this.tierInformation.tier6 = require(filePath); | ||||
|                 return; | ||||
|             case tier == 7 && type == "equipment": | ||||
|                 this.tierInformation.tier7 = require(filePath); | ||||
|                 return; | ||||
|             case tier == 1 && type == "mods": | ||||
|                 this.tierInformation.tier1mods = require(filePath); | ||||
|                 return; | ||||
|             case tier == 2 && type == "mods": | ||||
|                 this.tierInformation.tier2mods = require(filePath); | ||||
|                 return; | ||||
|             case tier == 3 && type == "mods": | ||||
|                 this.tierInformation.tier3mods = require(filePath); | ||||
|                 return; | ||||
|             case tier == 4 && type == "mods": | ||||
|                 this.tierInformation.tier4mods = require(filePath); | ||||
|                 return; | ||||
|             case tier == 5 && type == "mods": | ||||
|                 this.tierInformation.tier5mods = require(filePath); | ||||
|                 return; | ||||
|             case tier == 6 && type == "mods": | ||||
|                 this.tierInformation.tier6mods = require(filePath); | ||||
|                 return; | ||||
|             case tier == 7 && type == "mods": | ||||
|                 this.tierInformation.tier7mods = require(filePath); | ||||
|                 return; | ||||
|             case tier == 1 && type == "chances": | ||||
|                 this.tierInformation.tier1chances = require(filePath); | ||||
|                 return; | ||||
|             case tier == 2 && type == "chances": | ||||
|                 this.tierInformation.tier2chances = require(filePath); | ||||
|                 return; | ||||
|             case tier == 3 && type == "chances": | ||||
|                 this.tierInformation.tier3chances = require(filePath); | ||||
|                 return; | ||||
|             case tier == 4 && type == "chances": | ||||
|                 this.tierInformation.tier4chances = require(filePath); | ||||
|                 return; | ||||
|             case tier == 5 && type == "chances": | ||||
|                 this.tierInformation.tier5chances = require(filePath); | ||||
|                 return; | ||||
|             case tier == 6 && type == "chances": | ||||
|                 this.tierInformation.tier6chances = require(filePath); | ||||
|                 return; | ||||
|             case tier == 7 && type == "chances": | ||||
|                 this.tierInformation.tier7chances = require(filePath); | ||||
|                 return; | ||||
|             case tier == 1 && type == "ammo": | ||||
|                 this.tierInformation.tier1ammo = require(filePath); | ||||
|                 return; | ||||
|             case tier == 2 && type == "ammo": | ||||
|                 this.tierInformation.tier2ammo = require(filePath); | ||||
|                 return; | ||||
|             case tier == 3 && type == "ammo": | ||||
|                 this.tierInformation.tier3ammo = require(filePath); | ||||
|                 return; | ||||
|             case tier == 4 && type == "ammo": | ||||
|                 this.tierInformation.tier4ammo = require(filePath); | ||||
|                 return; | ||||
|             case tier == 5 && type == "ammo": | ||||
|                 this.tierInformation.tier5ammo = require(filePath); | ||||
|                 return; | ||||
|             case tier == 6 && type == "ammo": | ||||
|                 this.tierInformation.tier6ammo = require(filePath); | ||||
|                 return; | ||||
|             case tier == 7 && type == "ammo": | ||||
|                 this.tierInformation.tier7ammo = require(filePath); | ||||
|                 return; | ||||
|             case tier == 1 && type == "appearance": | ||||
|                 this.tierInformation.tier1appearance = require(filePath); | ||||
|                 return; | ||||
|             case tier == 2 && type == "appearance": | ||||
|                 this.tierInformation.tier2appearance = require(filePath); | ||||
|                 return; | ||||
|             case tier == 3 && type == "appearance": | ||||
|                 this.tierInformation.tier3appearance = require(filePath); | ||||
|                 return; | ||||
|             case tier == 4 && type == "appearance": | ||||
|                 this.tierInformation.tier4appearance = require(filePath); | ||||
|                 return; | ||||
|             case tier == 5 && type == "appearance": | ||||
|                 this.tierInformation.tier5appearance = require(filePath); | ||||
|                 return; | ||||
|             case tier == 6 && type == "appearance": | ||||
|                 this.tierInformation.tier6appearance = require(filePath); | ||||
|                 return; | ||||
|             case tier == 7 && type == "appearance": | ||||
|                 this.tierInformation.tier7appearance = require(filePath); | ||||
|                 return; | ||||
|         } | ||||
|     } | ||||
|      | ||||
|     private missingFileCount(folderName: string, errorType: number): void | ||||
|     { | ||||
|         const error = errorType == 0 ? "Missing files" : "Extra files found"; | ||||
|         this.raidInformation.usingDefaultDB = true; | ||||
|         this.apbsLogger.log(Logging.ERR, `Preset name "${folderName}" is invalid.`); | ||||
|         this.apbsLogger.log(Logging.ERR, `${error}. Report issue to author of preset.`); | ||||
|         this.apbsLogger.log(Logging.WARN, "Using APBS database instead of preset..."); | ||||
|         this.buildTierJson(); | ||||
|     } | ||||
|      | ||||
|     private invalidFileName(folderName: string, item: string): void | ||||
|     { | ||||
|         this.raidInformation.usingDefaultDB = true; | ||||
|         this.apbsLogger.log(Logging.ERR, `Preset name "${folderName}" is invalid.`); | ||||
|         this.apbsLogger.log(Logging.ERR, `"${item}" is incorrectly named. Report issue to author of preset.`); | ||||
|         this.apbsLogger.log(Logging.WARN, "Using APBS database instead of preset..."); | ||||
|         this.buildTierJson(); | ||||
|     } | ||||
| 
 | ||||
|     private missingPresetFolder(folderName: string, presetFolder: string): void | ||||
|     { | ||||
|         this.raidInformation.usingDefaultDB = true; | ||||
|         this.apbsLogger.log(Logging.ERR, `Preset name "${folderName}" is invalid.`); | ||||
|         this.apbsLogger.log(Logging.ERR, `Verify the preset folder exists in "${presetFolder}" and is named properly.`); | ||||
|         this.apbsLogger.log(Logging.WARN, "Using APBS database instead of preset..."); | ||||
|         this.buildTierJson(); | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,653 @@ | |||
| /* eslint-disable @typescript-eslint/quotes */ | ||||
| import { injectable, inject } from "tsyringe"; | ||||
| 
 | ||||
| import { ItemHelper } from "@spt/helpers/ItemHelper"; | ||||
| import { BaseClasses } from "@spt/models/enums/BaseClasses"; | ||||
| import { IDatabaseTables } from "@spt/models/spt/server/IDatabaseTables"; | ||||
| import { ITemplateItem } from "@spt/models/eft/common/tables/ITemplateItem"; | ||||
| import { DatabaseService } from "@spt/services/DatabaseService"; | ||||
| import { ICustomizationItem } from "@spt/models/eft/common/tables/ICustomizationItem"; | ||||
| 
 | ||||
| import { ModConfig } from "../Globals/ModConfig"; | ||||
| import { vanillaItemList, vanillaClothingList } from "../Globals/VanillaItemLists"; | ||||
| import { APBSLogger } from "../Utils/APBSLogger"; | ||||
| import { Logging } from "../Enums/Logging"; | ||||
| import { APBSEquipmentGetter } from "../Utils/APBSEquipmentGetter"; | ||||
| import { TierInformation } from "../Globals/TierInformation"; | ||||
| import { APBSAttachmentChecker } from "../Utils/APBSAttachmentChecker"; | ||||
| 
 | ||||
| @injectable() | ||||
| export class ModdedImportHelper | ||||
| { | ||||
|     private blacklist: any[]; | ||||
|     private attachmentBlacklist: any[]; | ||||
|     private clothingBlacklist: any[]; | ||||
| 
 | ||||
|     constructor( | ||||
|         @inject("IDatabaseTables") protected tables: IDatabaseTables, | ||||
|         @inject("DatabaseService") protected databaseService: DatabaseService, | ||||
|         @inject("ItemHelper") protected itemHelper: ItemHelper, | ||||
|         @inject("TierInformation") protected tierInformation: TierInformation, | ||||
|         @inject("APBSEquipmentGetter") protected apbsEquipmentGetter: APBSEquipmentGetter, | ||||
|         @inject("APBSAttachmentChecker") protected apbsAttachmentChecker: APBSAttachmentChecker, | ||||
|         @inject("APBSLogger") protected apbsLogger: APBSLogger | ||||
|     ) | ||||
|     { | ||||
|         this.blacklist = [ | ||||
|             "5ae083b25acfc4001a5fc702", //weapons
 | ||||
|             "5e81ebcd8e146c7080625e15", | ||||
|             "6217726288ed9f0845317459", | ||||
|             "5d52cc5ba4b9367408500062", | ||||
|             "620109578d82e67e7911abf2", | ||||
|             "639af924d0446708ee62294e", | ||||
|             "657857faeff4c850222dff1b", | ||||
|             "639c3fbbd0446708ee622ee9", | ||||
|             "62178be9d0050232da3485d9", | ||||
|             "62178c4d4ecf221597654e3d", | ||||
|             "624c0b3340357b5f566e8766", | ||||
|             "5cdeb229d7f00c000e7ce174", | ||||
|             "579204f224597773d619e051", | ||||
|             "6275303a9f372d6ea97f9ec7", | ||||
|             "66015072e9f84d5680039678", | ||||
|             "59f9cabd86f7743a10721f46", | ||||
|             "5abccb7dd8ce87001773e277", | ||||
|             "5b3b713c5acfc4330140bd8d", | ||||
|             "66d98233302686954b0c6f81", | ||||
|             "66d9f1abb16d9aacf5068468", | ||||
|             "56e33634d2720bd8058b456b", //backpacks
 | ||||
|             "5e4abc6786f77406812bd572", | ||||
|             "5e997f0b86f7741ac73993e2", | ||||
|             "61b9e1aaef9a1b5d6a79899a", | ||||
|             "61c18db6dfd64163ea78fbb4", //headwear
 | ||||
|             "66bdc28a0b603c26902b2011", | ||||
|             "65749cb8e0423b9ebe0c79c9", | ||||
|             "60a7acf20c5cb24b01346648", | ||||
|             "636270263f2495c26f00b007", | ||||
|             "5a43943586f77416ad2f06e2", | ||||
|             "5a43957686f7742a2c2f11b0", | ||||
|             "65749ccf33fdc9c0cf06d3ca", | ||||
|             "5a16bb52fcdbcb001a3b00dc", | ||||
|             "628e4dd1f477aa12234918aa", | ||||
|             "5c066ef40db834001966a595", | ||||
|             "59ef13ca86f77445fd0e2483", | ||||
|             "6531119b9afebff7ff0a1769" | ||||
|         ] | ||||
| 
 | ||||
|         this.attachmentBlacklist = [ | ||||
|             "5c110624d174af029e69734c", | ||||
|             "5d1b5e94d7ad1a2b865a96b0", | ||||
|             "6478641c19d732620e045e17", | ||||
|             "5a1eaa87fcdbcb001865f75e", | ||||
|             "609bab8b455afd752b2e6138", | ||||
|             "63fc44e2429a8a166c7f61e6", | ||||
|             "5a1ead28fcdbcb001912fa9f", | ||||
|             "63fc449f5bd61c6cf3784a88", | ||||
|             "5b3b6dc75acfc47a8773fb1e", | ||||
|             "5c11046cd174af02a012e42b", | ||||
|             "544a3f024bdc2d1d388b4568", | ||||
|             "544a3d0a4bdc2d1b388b4567", | ||||
|             "5648b62b4bdc2d9d488b4585", | ||||
|             "5c0e2ff6d174af02a1659d4a", | ||||
|             "5c0e2f5cd174af02a012cfc9", | ||||
|             "5c6592372e221600133e47d7", | ||||
|             "544a378f4bdc2d30388b4567", | ||||
|             "5d1340bdd7ad1a0e8d245aab", | ||||
|             "671d85439ae8365d69117ba6", | ||||
|             "670e8eab8c1bb0e5a7075acf", | ||||
|             "671d8617a3e45c1f5908278c", | ||||
|             "671d8ac8a3e45c1f59082799", | ||||
|             "671d8b38b769f0d88c0950f8", | ||||
|             "671d8b8c0959c721a50ca838" | ||||
|         ] | ||||
| 
 | ||||
|         // This is empty now because Crackbone fixed Artem - but I'm leaving this here for future use
 | ||||
|         this.clothingBlacklist = [] | ||||
|     } | ||||
| 
 | ||||
|     public tiersTable = []; | ||||
| 
 | ||||
|     public initialize():void | ||||
|     { | ||||
|         if (ModConfig.config.initalTierAppearance < 1 || ModConfig.config.initalTierAppearance > 7) | ||||
|         { | ||||
|             this.apbsLogger.log(Logging.WARN, `Config value for "initialTierAppearance" is invalid. Must be 1-7. Currently configured for ${ModConfig.config.initalTierAppearance}`) | ||||
|             return; | ||||
|         } | ||||
|         if (ModConfig.config.enableModdedWeapons) this.buildVanillaWeaponList(); | ||||
|         if (ModConfig.config.enableModdedEquipment) this.buildVanillaEquipmentList(); | ||||
|         if (ModConfig.config.enableModdedClothing && !ModConfig.config.seasonalPmcAppearance) this.buildVanillaClothingList(); | ||||
|     } | ||||
| 
 | ||||
|     private buildVanillaWeaponList(): void | ||||
|     { | ||||
|         this.apbsLogger.log(Logging.WARN, "Checking & importing Modded Weapons...Support not granted for this feature...") | ||||
|          | ||||
|         // Build the joined list for every weapon used in APBS
 | ||||
|         const weapons = {}; | ||||
|         vanillaItemList.equipment.LongRange.forEach(element => weapons[element] = this.getItem(element))         | ||||
|         vanillaItemList.equipment.ShortRange.forEach(element => weapons[element] = this.getItem(element)) | ||||
|         vanillaItemList.equipment.Holster.forEach(element => weapons[element] = this.getItem(element)) | ||||
|         vanillaItemList.equipment.Scabbard.forEach(element => weapons[element] = this.getItem(element)) | ||||
| 
 | ||||
|         // Push this list to the function to filter and import
 | ||||
|         this.getModdedItems(weapons as ITemplateItem, BaseClasses.WEAPON, "Weapons"); | ||||
|     } | ||||
| 
 | ||||
|     private buildVanillaEquipmentList(): void | ||||
|     { | ||||
|         this.apbsLogger.log(Logging.WARN, "Checking & importing Modded Equipment...Support not granted for this feature...") | ||||
|          | ||||
|         // Build the joined list for every armour type used in APBS
 | ||||
|         const armours = {}; | ||||
|         vanillaItemList.equipment.ArmorVest.forEach(element => armours[element] = this.getItem(element)) | ||||
| 
 | ||||
|         const headwear = {}; | ||||
|         vanillaItemList.equipment.Headwear.forEach(element => headwear[element] = this.getItem(element)) | ||||
| 
 | ||||
|         const tacticalVests = {};         | ||||
|         vanillaItemList.equipment.TacticalVest.forEach(element => tacticalVests[element] = this.getItem(element)) | ||||
|          | ||||
|         // Push these lists to the function to filter and import
 | ||||
|         this.getModdedItems(armours as ITemplateItem, BaseClasses.ARMOR, "Armours"); | ||||
|         this.getModdedItems(headwear as ITemplateItem, BaseClasses.HEADWEAR, "Helmets"); | ||||
|         this.getModdedItems(tacticalVests as ITemplateItem, BaseClasses.VEST, "Vests"); | ||||
|     } | ||||
| 
 | ||||
|     private buildVanillaClothingList(): void | ||||
|     { | ||||
|         this.apbsLogger.log(Logging.WARN, "Checking & importing Modded Clothing...Support not granted for this feature...") | ||||
| 
 | ||||
|         // Build the joined list for every body & feet type used in APBS
 | ||||
|         const body = {}; | ||||
|         vanillaClothingList.appearance.body.forEach(element => body[element] = this.getCustomization(element)) | ||||
| 
 | ||||
|         const feet = {}; | ||||
|         vanillaClothingList.appearance.feet.forEach(element => feet[element] = this.getCustomization(element)) | ||||
| 
 | ||||
|         // Push these lists to the function to filter and import
 | ||||
|         this.getModdedClothing(body as ICustomizationItem, "Body"); | ||||
|         this.getModdedClothing(feet as ICustomizationItem, "Feet"); | ||||
|     } | ||||
| 
 | ||||
|     private getModdedClothing(clothingList: ICustomizationItem, className: string): void | ||||
|     { | ||||
|         // Compare SPT database values to APBS values, filter down to the difference (assuming they are either modded, or not in the APBS database).
 | ||||
|         const databaseClothing = Object.values(this.databaseService.getTables().templates.customization); | ||||
|         const allClothing = databaseClothing.filter(x => this.isCustomization(x._id, className)); | ||||
|         const moddedClothing = Object.values(clothingList); | ||||
|         const allApbsClothing = moddedClothing.filter(x => this.isCustomization(x._id, className)); | ||||
| 
 | ||||
|         let clothingToBeImported = allClothing.filter(x => !allApbsClothing.includes(x)); | ||||
| 
 | ||||
|         // Filter out blacklisted items
 | ||||
|         for (const item of clothingToBeImported) | ||||
|         { | ||||
|             if (this.clothingBlacklist.includes(item._id)) clothingToBeImported = clothingToBeImported.filter(id => id._id != item._id) | ||||
|         } | ||||
| 
 | ||||
|         // Push clothing to APBS database
 | ||||
|         if (clothingToBeImported.length > 0) | ||||
|         { | ||||
|             this.apbsLogger.log(Logging.WARN, `Importing ${clothingToBeImported.length} Modded ${className}...`) | ||||
|             this.pushClothing(clothingToBeImported); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private pushClothing(clothingList: ICustomizationItem[]): void | ||||
|     { | ||||
|         // Loop each tier to add clothing to every tier
 | ||||
|         for (const object in this.tierInformation.tiers) | ||||
|         { | ||||
|             const tierNumber = this.tierInformation.tiers[object].tier | ||||
|             const tierJson = this.apbsEquipmentGetter.getAppearanceJson(tierNumber, true); | ||||
| 
 | ||||
|             // Skip tiers based on configuration
 | ||||
|             if (tierNumber < ModConfig.config.initalTierAppearance) continue; | ||||
| 
 | ||||
|             // Add each item from the clothing list to each tier JSON - this completes the import
 | ||||
|             for (const item in clothingList) | ||||
|             { | ||||
|                 if (clothingList[item]._props.Side.includes("Bear")) | ||||
|                 { | ||||
|                     if (clothingList[item]._props.BodyPart == "Feet") tierJson.pmcBEAR.appearance.feet[clothingList[item]._id] = 1 | ||||
|                     if (clothingList[item]._props.BodyPart == "Body") tierJson.pmcBEAR.appearance.body[clothingList[item]._id] = 1 | ||||
|                 } | ||||
|                 if (clothingList[item]._props.Side.includes("Usec")) | ||||
|                 { | ||||
|                     if (clothingList[item]._props.BodyPart == "Feet") tierJson.pmcUSEC.appearance.feet[clothingList[item]._id] = 1 | ||||
|                     if (clothingList[item]._props.BodyPart == "Body") tierJson.pmcUSEC.appearance.body[clothingList[item]._id] = 1 | ||||
|                 } | ||||
|             } | ||||
|         }         | ||||
|     } | ||||
| 
 | ||||
|     private getModdedItems(equipmentList: ITemplateItem, baseClass: BaseClasses, className: string): void | ||||
|     { | ||||
|         // Compare SPT database values to APBS values, filter down to the difference (assuming they are either modded, or not in the APBS database).
 | ||||
|         const items = Object.values(this.tables.templates.items); | ||||
|         const allItems = items.filter(x => this.itemHelper.isOfBaseclass(x._id, baseClass)); | ||||
|         const tieredItems = Object.values(equipmentList); | ||||
|         const allTieredItems = tieredItems.filter(x => this.itemHelper.isOfBaseclass(x._id, baseClass)); | ||||
| 
 | ||||
|         let itemsToBeImported = allItems.filter(x => !allTieredItems.includes(x)); | ||||
|          | ||||
|         // Filter out blacklisted items
 | ||||
|         for (const item of itemsToBeImported) | ||||
|         { | ||||
|             if (this.blacklist.includes(item._id)) itemsToBeImported = itemsToBeImported.filter(id => id._id != item._id) | ||||
|         } | ||||
| 
 | ||||
|         // Push items to APBS database depending on if they are weapons or equipment
 | ||||
|         if (itemsToBeImported.length > 0) | ||||
|         { | ||||
|             this.apbsLogger.log(Logging.WARN, `Importing ${itemsToBeImported.length} Modded ${className}...`) | ||||
|             if (baseClass == BaseClasses.WEAPON) this.getSetModdedWeaponDetails(itemsToBeImported); | ||||
|             if (baseClass != BaseClasses.WEAPON) this.getSetModdedEquipmentDetails(itemsToBeImported); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private getSetModdedWeaponDetails(weaponPool: ITemplateItem[]): void | ||||
|     { | ||||
|         // Loop each weapon in the pool of weapons to be imported - push them individually
 | ||||
|         for (const weapon in weaponPool) | ||||
|         { | ||||
|             const weaponParent = weaponPool[weapon]._parent; | ||||
|             const weaponId = weaponPool[weapon]._id; | ||||
|             const weaponSlots = weaponPool[weapon]?._props?.Slots; | ||||
|             const weaponType = weaponPool[weapon]?._props?.weapUseType; | ||||
| 
 | ||||
|             // Push Weapon details to relevant pools
 | ||||
|             this.pushCalibersToAmmoPools(weaponId) | ||||
|             this.pushWeaponToTiers(weaponId, weaponType, weaponParent); | ||||
|             this.pushItemAndPrimaryMods(weaponId, weaponSlots); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private getSetModdedEquipmentDetails(equipmentPool: ITemplateItem[]): void | ||||
|     { | ||||
|         // Loop each equipment in the pool of equipment to be imported - push them individually
 | ||||
|         for (const equipment in equipmentPool) | ||||
|         { | ||||
|             const equipmentParent = equipmentPool[equipment]._parent; | ||||
|             const equipmentId = equipmentPool[equipment]._id; | ||||
|             const equipmentSlots = equipmentPool[equipment]?._props?.Slots; | ||||
|             const equipmentSlotsLength = equipmentPool[equipment]?._props?.Slots.length; | ||||
|             const gridLength = equipmentPool[equipment]?._props?.Grids.length; | ||||
|             let equipmentSlot: string; | ||||
| 
 | ||||
|             // Set equipmentSlot string to the proper value - this is only done to separate TacticalVests & ArmouredRigs
 | ||||
|             if (equipmentParent == "5448e5284bdc2dcb718b4567" && (equipmentSlots.length == 0 || equipmentSlots == undefined)) equipmentSlot = "TacticalVest" | ||||
|             if (equipmentParent == "5448e5284bdc2dcb718b4567" && equipmentSlots.length >= 1) equipmentSlot = "ArmouredRig" | ||||
|             if (equipmentParent == "5448e54d4bdc2dcc718b4568") equipmentSlot = "ArmorVest" | ||||
|             if (equipmentParent == "5a341c4086f77401f2541505") equipmentSlot = "Headwear" | ||||
| 
 | ||||
|             // Push Equipment details to relevant pools
 | ||||
|             this.pushEquipmentToTiers(equipmentId, equipmentSlot, gridLength, equipmentSlotsLength); | ||||
|             this.pushItemAndPrimaryMods(equipmentId, equipmentSlots); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private pushWeaponToTiers(weaponId: string, weaponType: string, parentClass: string): void | ||||
|     { | ||||
|         // Define weights to use, and which range they go to (for logging).
 | ||||
|         let range = ""; | ||||
|         const pmcWeight = ModConfig.config.pmcWeaponWeights <= 0 ? 1 : ModConfig.config.pmcWeaponWeights; | ||||
|         const scavWeight = ModConfig.config.scavWeaponWeights <= 0 ? 1 : ModConfig.config.scavWeaponWeights; | ||||
|         const defaultWeight = ModConfig.config.followerWeaponWeights <= 0 ? 1 : ModConfig.config.followerWeaponWeights; | ||||
| 
 | ||||
|         // Loop over each tier to easily use the proper tierJSON
 | ||||
|         for (const object in this.tierInformation.tiers) | ||||
|         { | ||||
|             const tierNumber = this.tierInformation.tiers[object].tier | ||||
|             const tierJson = this.apbsEquipmentGetter.getTierJson(tierNumber, true); | ||||
| 
 | ||||
|             // Skip tiers based on configuration
 | ||||
|             if (tierNumber < ModConfig.config.initalTierAppearance) continue; | ||||
| 
 | ||||
|             // Use multiple variable switch to set specific weapon "types" to the correct pool
 | ||||
|             switch (true)  | ||||
|             { | ||||
|                 case parentClass == "5447b5fc4bdc2d87278b4567" && weaponType == "primary": | ||||
|                     tierJson.pmcUSEC.equipment.FirstPrimaryWeapon.LongRange[weaponId] = pmcWeight | ||||
|                     tierJson.pmcUSEC.equipment.FirstPrimaryWeapon.ShortRange[weaponId] = pmcWeight | ||||
|                     tierJson.pmcUSEC.equipment.SecondPrimaryWeapon.LongRange[weaponId] = pmcWeight | ||||
|                     tierJson.pmcUSEC.equipment.SecondPrimaryWeapon.ShortRange[weaponId] = pmcWeight | ||||
|                     tierJson.pmcBEAR.equipment.FirstPrimaryWeapon.LongRange[weaponId] = pmcWeight | ||||
|                     tierJson.pmcBEAR.equipment.FirstPrimaryWeapon.ShortRange[weaponId] = pmcWeight | ||||
|                     tierJson.pmcBEAR.equipment.SecondPrimaryWeapon.LongRange[weaponId] = pmcWeight | ||||
|                     tierJson.pmcBEAR.equipment.SecondPrimaryWeapon.ShortRange[weaponId] = pmcWeight | ||||
|                     tierJson.scav.equipment.FirstPrimaryWeapon.LongRange[weaponId] = scavWeight | ||||
|                     tierJson.scav.equipment.FirstPrimaryWeapon.ShortRange[weaponId] = scavWeight | ||||
|                     tierJson.scav.equipment.SecondPrimaryWeapon.LongRange[weaponId] = scavWeight | ||||
|                     tierJson.scav.equipment.SecondPrimaryWeapon.ShortRange[weaponId] = scavWeight | ||||
|                     tierJson.default.equipment.FirstPrimaryWeapon.LongRange[weaponId] = defaultWeight | ||||
|                     tierJson.default.equipment.FirstPrimaryWeapon.ShortRange[weaponId] = defaultWeight | ||||
|                     tierJson.default.equipment.SecondPrimaryWeapon.LongRange[weaponId] = defaultWeight | ||||
|                     tierJson.default.equipment.SecondPrimaryWeapon.ShortRange[weaponId] = defaultWeight | ||||
|                     range = "Long & Short range"; | ||||
|                     continue; | ||||
|                 case parentClass == "5447b6254bdc2dc3278b4568" && weaponType == "primary": | ||||
|                 case parentClass == "5447b6194bdc2d67278b4567" && weaponType == "primary": | ||||
|                     tierJson.pmcUSEC.equipment.FirstPrimaryWeapon.LongRange[weaponId] = pmcWeight | ||||
|                     tierJson.pmcUSEC.equipment.SecondPrimaryWeapon.LongRange[weaponId] = pmcWeight | ||||
|                     tierJson.pmcBEAR.equipment.FirstPrimaryWeapon.LongRange[weaponId] = pmcWeight | ||||
|                     tierJson.pmcBEAR.equipment.SecondPrimaryWeapon.LongRange[weaponId] = pmcWeight | ||||
|                     tierJson.scav.equipment.FirstPrimaryWeapon.LongRange[weaponId] = scavWeight | ||||
|                     tierJson.scav.equipment.SecondPrimaryWeapon.LongRange[weaponId] = scavWeight | ||||
|                     tierJson.default.equipment.FirstPrimaryWeapon.LongRange[weaponId] = defaultWeight | ||||
|                     tierJson.default.equipment.SecondPrimaryWeapon.LongRange[weaponId] = defaultWeight | ||||
|                     range = "Long range" | ||||
|                     continue;                 | ||||
|                 case parentClass == "5447b5f14bdc2d61278b4567" && weaponType == "primary": | ||||
|                 case parentClass == "5447bed64bdc2d97278b4568" && weaponType == "primary": | ||||
|                 case parentClass == "5447b5e04bdc2d62278b4567" && weaponType == "primary": | ||||
|                 case parentClass == "5447b5cf4bdc2d65278b4567" && weaponType == "primary": | ||||
|                 case parentClass == "617f1ef5e8b54b0998387733" && weaponType == "primary": | ||||
|                 case parentClass == "5447b6094bdc2dc3278b4567" && weaponType == "primary": | ||||
|                     tierJson.pmcUSEC.equipment.FirstPrimaryWeapon.ShortRange[weaponId] = pmcWeight | ||||
|                     tierJson.pmcUSEC.equipment.SecondPrimaryWeapon.ShortRange[weaponId] = pmcWeight | ||||
|                     tierJson.pmcBEAR.equipment.FirstPrimaryWeapon.ShortRange[weaponId] = pmcWeight | ||||
|                     tierJson.pmcBEAR.equipment.SecondPrimaryWeapon.ShortRange[weaponId] = pmcWeight | ||||
|                     tierJson.scav.equipment.FirstPrimaryWeapon.ShortRange[weaponId] = scavWeight | ||||
|                     tierJson.scav.equipment.SecondPrimaryWeapon.ShortRange[weaponId] = scavWeight | ||||
|                     tierJson.default.equipment.FirstPrimaryWeapon.ShortRange[weaponId] = defaultWeight | ||||
|                     tierJson.default.equipment.SecondPrimaryWeapon.ShortRange[weaponId] = defaultWeight | ||||
|                     range = "Short range" | ||||
|                     continue; | ||||
|                 case parentClass == "5447b5cf4bdc2d65278b4567" && weaponType == "secondary": | ||||
|                 case parentClass == "617f1ef5e8b54b0998387733" && weaponType == "secondary": | ||||
|                 case parentClass == "5447b6094bdc2dc3278b4567" && weaponType == "secondary": | ||||
|                     tierJson.pmcUSEC.equipment.Holster[weaponId] = 5 | ||||
|                     tierJson.pmcBEAR.equipment.Holster[weaponId] = 5 | ||||
|                     tierJson.scav.equipment.Holster[weaponId] = 1 | ||||
|                     tierJson.default.equipment.Holster[weaponId] = 3 | ||||
|                     range = "Holster" | ||||
|                     continue; | ||||
|                 default: | ||||
|                     if (weaponType == "primary") | ||||
|                     { | ||||
|                         tierJson.pmcUSEC.equipment.FirstPrimaryWeapon.LongRange[weaponId] = pmcWeight | ||||
|                         tierJson.pmcUSEC.equipment.FirstPrimaryWeapon.ShortRange[weaponId] = pmcWeight | ||||
|                         tierJson.pmcUSEC.equipment.SecondPrimaryWeapon.LongRange[weaponId] = pmcWeight | ||||
|                         tierJson.pmcUSEC.equipment.SecondPrimaryWeapon.ShortRange[weaponId] = pmcWeight | ||||
|                         tierJson.pmcBEAR.equipment.FirstPrimaryWeapon.LongRange[weaponId] = pmcWeight | ||||
|                         tierJson.pmcBEAR.equipment.FirstPrimaryWeapon.ShortRange[weaponId] = pmcWeight | ||||
|                         tierJson.pmcBEAR.equipment.SecondPrimaryWeapon.LongRange[weaponId] = pmcWeight | ||||
|                         tierJson.pmcBEAR.equipment.SecondPrimaryWeapon.ShortRange[weaponId] = pmcWeight | ||||
|                         tierJson.scav.equipment.FirstPrimaryWeapon.LongRange[weaponId] = scavWeight | ||||
|                         tierJson.scav.equipment.FirstPrimaryWeapon.ShortRange[weaponId] = scavWeight | ||||
|                         tierJson.scav.equipment.SecondPrimaryWeapon.LongRange[weaponId] = scavWeight | ||||
|                         tierJson.scav.equipment.SecondPrimaryWeapon.ShortRange[weaponId] = scavWeight | ||||
|                         tierJson.default.equipment.SecondPrimaryWeapon.LongRange[weaponId] = defaultWeight | ||||
|                         tierJson.default.equipment.SecondPrimaryWeapon.ShortRange[weaponId] = defaultWeight | ||||
|                         tierJson.default.equipment.FirstPrimaryWeapon.LongRange[weaponId] = defaultWeight | ||||
|                         tierJson.default.equipment.FirstPrimaryWeapon.ShortRange[weaponId] = defaultWeight | ||||
|                         range = "Long & Short range" | ||||
|                     } | ||||
|                     if (weaponType == "secondary") | ||||
|                     { | ||||
|                         tierJson.pmcUSEC.equipment.Holster[weaponId] = 5 | ||||
|                         tierJson.pmcBEAR.equipment.Holster[weaponId] = 5 | ||||
|                         tierJson.scav.equipment.Holster[weaponId] = 1 | ||||
|                         tierJson.default.equipment.Holster[weaponId] = 3 | ||||
|                         range = "Holster" | ||||
|                     } | ||||
|                     continue; | ||||
|             } | ||||
|         } | ||||
|         this.apbsLogger.log(Logging.DEBUG, `[Tier${ModConfig.config.initalTierAppearance}+] Added ${weaponId} to ${range} weapons.`) | ||||
|     } | ||||
| 
 | ||||
|     private pushEquipmentToTiers(itemID: string, equipmentSlot: string, gridLength: number, equipmentSlotsLength: number): void | ||||
|     { | ||||
|         // Loop over each tier to easily use the proper tierJSON
 | ||||
|         for (const object in this.tierInformation.tiers) | ||||
|         { | ||||
|             const tierNumber = this.tierInformation.tiers[object].tier | ||||
|             const tierJson = this.apbsEquipmentGetter.getTierJson(tierNumber, true); | ||||
| 
 | ||||
|             // Skip tiers based on configuration
 | ||||
|             if (tierNumber < ModConfig.config.initalTierAppearance) continue; | ||||
| 
 | ||||
|             // Set weights based on witch slot they are in. Check TacticalVests for belts (low grid count) and check Helmets to see if armoured or decorative
 | ||||
|             let weight; | ||||
|             if (equipmentSlot == "TacticalVest" && gridLength > 10) weight = 10; | ||||
|             if (equipmentSlot == "TacticalVest" && gridLength <= 10) weight = 1; | ||||
|             if (equipmentSlot == "ArmouredRig") weight = 7; | ||||
|             if (equipmentSlot == "ArmorVest") weight = 10; | ||||
|             if (equipmentSlot == "Headwear" && equipmentSlotsLength > 0) weight = 6; | ||||
|             if (equipmentSlot == "Headwear" && equipmentSlotsLength == 0) weight = 1; | ||||
| 
 | ||||
|             // Add the equipment to the proper slot and correct weight
 | ||||
|             tierJson.pmcUSEC.equipment[equipmentSlot][itemID] = weight | ||||
|             tierJson.pmcBEAR.equipment[equipmentSlot][itemID] = weight | ||||
|             tierJson.scav.equipment[equipmentSlot][itemID] = 1 | ||||
|             tierJson.default.equipment[equipmentSlot][itemID] = weight | ||||
|         } | ||||
|         this.apbsLogger.log(Logging.DEBUG, `[Tier${ModConfig.config.initalTierAppearance}+] Added ${itemID} to ${equipmentSlot}.`) | ||||
|     } | ||||
| 
 | ||||
|     private pushItemAndPrimaryMods(itemID, itemSlots): void | ||||
|     { | ||||
|         // Loop over all slots of the item
 | ||||
|         for (const slot in itemSlots) | ||||
|         { | ||||
|             const slotName = itemSlots[slot]?._name; | ||||
|             const slotFilter = itemSlots[slot]?._props?.filters[0]?.Filter | ||||
| 
 | ||||
|             // Loop over all items in the filter for the slot
 | ||||
|             for (const item in slotFilter) | ||||
|             { | ||||
|                 const slotFilterItem = slotFilter[item]; | ||||
| 
 | ||||
|                 // Check if the item is actually a valid item, or is on the blacklist
 | ||||
|                 // WTT puts itemIDs in their mods that don't exist in the database for some reason (probably unreleased mods)
 | ||||
|                 const itemExistsCheck = this.itemHelper.getItem(slotFilterItem) | ||||
|                 if (this.attachmentBlacklist.includes(slotFilterItem) || !itemExistsCheck[0]) continue; | ||||
| 
 | ||||
|                 // Check if the itemID already exists in the tierJsons, if not - create it in them all.
 | ||||
|                 if (this.tierInformation.tier1mods[itemID] == undefined) | ||||
|                 { | ||||
|                     this.tierInformation.tier1mods[itemID] = {}; | ||||
|                     this.tierInformation.tier2mods[itemID] = {}; | ||||
|                     this.tierInformation.tier3mods[itemID] = {}; | ||||
|                     this.tierInformation.tier4mods[itemID] = {}; | ||||
|                     this.tierInformation.tier5mods[itemID] = {}; | ||||
|                     this.tierInformation.tier6mods[itemID] = {}; | ||||
|                     this.tierInformation.tier7mods[itemID] = {}; | ||||
|                 } | ||||
| 
 | ||||
|                 // Check if the itemID's slot already exists in the tierJsons, if not - create it in them all.
 | ||||
|                 if (this.tierInformation.tier1mods[itemID][slotName] == undefined) | ||||
|                 { | ||||
|                     this.tierInformation.tier1mods[itemID][slotName] = []; | ||||
|                     this.tierInformation.tier2mods[itemID][slotName] = []; | ||||
|                     this.tierInformation.tier3mods[itemID][slotName] = []; | ||||
|                     this.tierInformation.tier4mods[itemID][slotName] = []; | ||||
|                     this.tierInformation.tier5mods[itemID][slotName] = []; | ||||
|                     this.tierInformation.tier6mods[itemID][slotName] = []; | ||||
|                     this.tierInformation.tier7mods[itemID][slotName] = []; | ||||
|                 } | ||||
| 
 | ||||
|                 // Check if the itemID's slot doesn't already contain the item to import, if it doesn't - add it
 | ||||
|                 if (!this.tierInformation.tier1mods[itemID][slotName].includes(slotFilterItem)) | ||||
|                 { | ||||
|                     this.tierInformation.tier1mods[itemID][slotName].push(slotFilterItem); | ||||
|                     this.tierInformation.tier2mods[itemID][slotName].push(slotFilterItem); | ||||
|                     this.tierInformation.tier3mods[itemID][slotName].push(slotFilterItem); | ||||
|                     this.tierInformation.tier4mods[itemID][slotName].push(slotFilterItem); | ||||
|                     this.tierInformation.tier5mods[itemID][slotName].push(slotFilterItem); | ||||
|                     this.tierInformation.tier6mods[itemID][slotName].push(slotFilterItem); | ||||
|                     this.tierInformation.tier7mods[itemID][slotName].push(slotFilterItem); | ||||
| 
 | ||||
|                     // Push any children mods
 | ||||
|                     this.recursivePushChildrenMods(slotFilterItem); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private recursivePushChildrenMods(parentSlotFilterItem) | ||||
|     { | ||||
|         const parentSlotItemData = this.getItem(parentSlotFilterItem); | ||||
|         const parentSlotItemID = parentSlotItemData?._id; | ||||
|         const parentSlotSlots = parentSlotItemData?._props?.Slots; | ||||
| 
 | ||||
|         // Exit if there are no children
 | ||||
|         if (parentSlotSlots == undefined || parentSlotSlots.length == 0) return; | ||||
| 
 | ||||
|         // Loop over all slots of the parent
 | ||||
|         for (const slot in parentSlotSlots) | ||||
|         { | ||||
|             const slotName = parentSlotSlots[slot]?._name; | ||||
|             let slotFilter = parentSlotSlots[slot]?._props?.filters[0]?.Filter; | ||||
|             // If a slot's filters contain the canted sight mount, remove all other items from the filter - this ensures ONLY the canted sight is added
 | ||||
|             if (slotFilter.includes("5649a2464bdc2d91118b45a8")) | ||||
|             { | ||||
|                 slotFilter = [ "5649a2464bdc2d91118b45a8" ]; | ||||
|             } | ||||
| 
 | ||||
|             // Loop over each item in the slot's filters
 | ||||
|             for (const item in slotFilter) | ||||
|             { | ||||
|                 const slotFilterItem = parentSlotSlots[slot]?._props?.filters[0]?.Filter[item]; | ||||
|                 const itemExistsCheck = this.itemHelper.getItem(slotFilterItem) | ||||
| 
 | ||||
|                 // Check if the item is actually a valid item, or is on the blacklist
 | ||||
|                 // WTT puts itemIDs in their mods that don't exist in the database for some reason (probably unreleased mods)
 | ||||
|                 if (this.attachmentBlacklist.includes(slotFilterItem) || !itemExistsCheck[0]) continue; | ||||
| 
 | ||||
|                 // Check if the parent mod & the child mod are vanilla or modded
 | ||||
|                 // This allows preventing mods adding vanilla mods to vanilla weapons
 | ||||
|                 const isVanillaParent = this.apbsAttachmentChecker.isVanillaItem(parentSlotItemID); | ||||
|                 const isVanillaItem = this.apbsAttachmentChecker.isVanillaItem(slotFilterItem); | ||||
| 
 | ||||
|                 // Check if the PARENT itemID already exists in the tierJsons, if not - create it in all tierJSONs.
 | ||||
|                 if (this.tierInformation.tier1mods[parentSlotItemID] == undefined) | ||||
|                 { | ||||
|                     this.tierInformation.tier1mods[parentSlotItemID] = {}; | ||||
|                     this.tierInformation.tier2mods[parentSlotItemID] = {}; | ||||
|                     this.tierInformation.tier3mods[parentSlotItemID] = {}; | ||||
|                     this.tierInformation.tier4mods[parentSlotItemID] = {}; | ||||
|                     this.tierInformation.tier5mods[parentSlotItemID] = {}; | ||||
|                     this.tierInformation.tier6mods[parentSlotItemID] = {}; | ||||
|                     this.tierInformation.tier7mods[parentSlotItemID] = {}; | ||||
|                 } | ||||
| 
 | ||||
|                 // Check if the PARENT itemID already exists with the slotName, if not - create it in all tierJSONs
 | ||||
|                 if (this.tierInformation.tier1mods[parentSlotItemID][slotName] == undefined) | ||||
|                 { | ||||
|                     this.tierInformation.tier1mods[parentSlotItemID][slotName] = []; | ||||
|                     this.tierInformation.tier2mods[parentSlotItemID][slotName] = []; | ||||
|                     this.tierInformation.tier3mods[parentSlotItemID][slotName] = []; | ||||
|                     this.tierInformation.tier4mods[parentSlotItemID][slotName] = []; | ||||
|                     this.tierInformation.tier5mods[parentSlotItemID][slotName] = []; | ||||
|                     this.tierInformation.tier6mods[parentSlotItemID][slotName] = []; | ||||
|                     this.tierInformation.tier7mods[parentSlotItemID][slotName] = []; | ||||
|                 } | ||||
| 
 | ||||
|                 // Check if the PARENT itemID's slot doesn't already contain the item to import
 | ||||
|                 if (!this.tierInformation.tier1mods[parentSlotItemID][slotName].includes(slotFilterItem)) | ||||
|                 { | ||||
|                     // Additionally, check if the parent mod & child mod are vanilla as well as checking the config safeguard
 | ||||
|                     if (isVanillaParent && isVanillaItem && ModConfig.config.enableSafeGuard) continue; | ||||
| 
 | ||||
|                     // Finally push the child mod to the proper tierJSONs
 | ||||
|                     this.tierInformation.tier1mods[parentSlotItemID][slotName].push(slotFilterItem) | ||||
|                     this.tierInformation.tier2mods[parentSlotItemID][slotName].push(slotFilterItem) | ||||
|                     this.tierInformation.tier3mods[parentSlotItemID][slotName].push(slotFilterItem) | ||||
|                     this.tierInformation.tier4mods[parentSlotItemID][slotName].push(slotFilterItem) | ||||
|                     this.tierInformation.tier5mods[parentSlotItemID][slotName].push(slotFilterItem) | ||||
|                     this.tierInformation.tier6mods[parentSlotItemID][slotName].push(slotFilterItem) | ||||
|                     this.tierInformation.tier7mods[parentSlotItemID][slotName].push(slotFilterItem) | ||||
| 
 | ||||
|                     // Push any children mods
 | ||||
|                     this.recursivePushChildrenMods(slotFilterItem); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private pushCalibersToAmmoPools(itemID: string): void | ||||
|     { | ||||
|         const itemDetails = this.itemHelper.getItem(itemID) | ||||
|         const itemCaliber = itemDetails[1]?._props?.ammoCaliber | ||||
| 
 | ||||
|         // Check if the Caliber exists on tierJSON or is valid
 | ||||
|         if (!Object.keys(this.tierInformation.tier1ammo.scavAmmo).includes(itemCaliber) && itemCaliber != undefined) | ||||
|         { | ||||
|             const chamberFilter = itemDetails[1]?._props?.Chambers[0]?._props?.filters[0]?.Filter | ||||
| 
 | ||||
|             // If the chamber is valid and has items, add them to the tierJSONs
 | ||||
|             if (chamberFilter && chamberFilter.length > 0) | ||||
|             { | ||||
|                 for (const botPool in this.tierInformation.tier1ammo) | ||||
|                 { | ||||
|                     // Since the Caliber doesn't exist, create them empty to prevent undefined error below
 | ||||
|                     this.tierInformation.tier1ammo[botPool][itemCaliber] = {}; | ||||
|                     this.tierInformation.tier2ammo[botPool][itemCaliber] = {}; | ||||
|                     this.tierInformation.tier3ammo[botPool][itemCaliber] = {}; | ||||
|                     this.tierInformation.tier4ammo[botPool][itemCaliber] = {}; | ||||
|                     this.tierInformation.tier5ammo[botPool][itemCaliber] = {}; | ||||
|                     this.tierInformation.tier6ammo[botPool][itemCaliber] = {}; | ||||
|                     this.tierInformation.tier7ammo[botPool][itemCaliber] = {}; | ||||
| 
 | ||||
|                     // Push each item in the filter to the tierJSON
 | ||||
|                     for (const item in chamberFilter) | ||||
|                     { | ||||
|                         const ammo = chamberFilter[item] | ||||
|                         this.tierInformation.tier1ammo[botPool][itemCaliber][ammo] = 1; | ||||
|                         this.tierInformation.tier2ammo[botPool][itemCaliber][ammo] = 1; | ||||
|                         this.tierInformation.tier3ammo[botPool][itemCaliber][ammo] = 1; | ||||
|                         this.tierInformation.tier4ammo[botPool][itemCaliber][ammo] = 1; | ||||
|                         this.tierInformation.tier5ammo[botPool][itemCaliber][ammo] = 1; | ||||
|                         this.tierInformation.tier6ammo[botPool][itemCaliber][ammo] = 1; | ||||
|                         this.tierInformation.tier7ammo[botPool][itemCaliber][ammo] = 1; | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private getItem(tpl: string): ITemplateItem | ||||
|     { | ||||
|         if (tpl in this.databaseService.getItems()) | ||||
|         { | ||||
|             return this.databaseService.getItems()[tpl]; | ||||
|         } | ||||
| 
 | ||||
|         return undefined; | ||||
|     } | ||||
| 
 | ||||
|     private getCustomization(tpl: string): ICustomizationItem | ||||
|     { | ||||
|         if (tpl in this.databaseService.getCustomization()) | ||||
|         { | ||||
|             return this.databaseService.getCustomization()[tpl]; | ||||
|         } | ||||
| 
 | ||||
|         return undefined; | ||||
|     } | ||||
| 
 | ||||
|     private isCustomization(tpl: string, type: string): boolean | ||||
|     { | ||||
|         if (tpl in this.databaseService.getCustomization()) | ||||
|         { | ||||
|             const item = this.databaseService.getCustomization()[tpl]; | ||||
|             if (item._props.Side == undefined) | ||||
|             { | ||||
|                 return false; | ||||
|             } | ||||
|             if (item._props.Side.includes("Bear") || item._props.Side.includes("Usec")) | ||||
|             { | ||||
|                 if (item._props.BodyPart == type) | ||||
|                 { | ||||
|                     return true; | ||||
|                 } | ||||
|                 return false; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         return false; | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,70 @@ | |||
| /* eslint-disable @typescript-eslint/quotes */ | ||||
| import { injectable, inject } from "tsyringe"; | ||||
| 
 | ||||
| import { APBSLogger } from "../Utils/APBSLogger"; | ||||
| import { APBSEquipmentGetter } from "../Utils/APBSEquipmentGetter"; | ||||
| import { TierInformation } from "../Globals/TierInformation"; | ||||
| 
 | ||||
| @injectable() | ||||
| export class RealismHelper | ||||
| { | ||||
|     constructor( | ||||
|         @inject("TierInformation") protected tierInformation: TierInformation, | ||||
|         @inject("APBSEquipmentGetter") protected apbsEquipmentGetter: APBSEquipmentGetter, | ||||
|         @inject("APBSLogger") protected apbsLogger: APBSLogger | ||||
|     ) | ||||
|     {} | ||||
| 
 | ||||
|     public realismDetected: boolean = false; | ||||
| 
 | ||||
|     public gasMasks = [ | ||||
|         "5b432c305acfc40019478128", | ||||
|         "60363c0c92ec1c31037959f5" | ||||
|     ]; | ||||
| 
 | ||||
|     public initialize():void | ||||
|     { | ||||
|         this.realismDetected = true; | ||||
|         this.addGasMasksToBots(); | ||||
|     } | ||||
| 
 | ||||
|     private addGasMasksToBots()  | ||||
|     { | ||||
|         for (const tierObject in this.tierInformation.tiers) | ||||
|         { | ||||
|             const tierNumber = this.tierInformation.tiers[tierObject].tier | ||||
|             const tierJson = this.apbsEquipmentGetter.getTierJson(tierNumber, true); | ||||
|             for (const botType in tierJson) | ||||
|             { | ||||
|                 let weight = 22; | ||||
|                 if (botType == "bossTagilla" || botType == "bossKilla") continue; | ||||
|                 if (botType == "pmcUSEC" || botType == "pmcUSEC" ) weight = 40; | ||||
|                 if (botType == "scav") weight = 26; | ||||
|                 tierJson[botType].equipment.FaceCover["5b432c305acfc40019478128"] = weight; | ||||
|                 tierJson[botType].equipment.FaceCover["60363c0c92ec1c31037959f5"] = weight; | ||||
|             } | ||||
|         } | ||||
|         this.addGasMasksFiltersToMasks(); | ||||
|     } | ||||
| 
 | ||||
|     private addGasMasksFiltersToMasks()  | ||||
|     { | ||||
|         for (const tierObject in this.tierInformation.tiers) | ||||
|         { | ||||
|             const tierNumber = this.tierInformation.tiers[tierObject].tier | ||||
|             const tierJson = this.apbsEquipmentGetter.getTierModsJson(tierNumber, true); | ||||
| 
 | ||||
|             tierJson["5b432c305acfc40019478128"] = { | ||||
|                 "mod_equipment": [ | ||||
|                     "590c595c86f7747884343ad7" | ||||
|                 ] | ||||
|             } | ||||
| 
 | ||||
|             tierJson["60363c0c92ec1c31037959f5"] = { | ||||
|                 "mod_equipment": [ | ||||
|                     "590c595c86f7747884343ad7" | ||||
|                 ] | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,268 @@ | |||
| import * as fs from "fs"; | ||||
| import * as path from "path"; | ||||
| 
 | ||||
| // SPT
 | ||||
| import { DependencyContainer, Lifecycle } from "tsyringe"; | ||||
| import { PreSptModLoader } from "@spt/loaders/PreSptModLoader"; | ||||
| import { ILogger } from "@spt/models/spt/utils/ILogger"; | ||||
| import { StaticRouterModService } from "@spt/services/mod/staticRouter/StaticRouterModService"; | ||||
| import { DynamicRouterModService } from "@spt/services/mod/dynamicRouter/DynamicRouterModService"; | ||||
| import { ItemHelper } from "@spt/helpers/ItemHelper"; | ||||
| import { DatabaseService } from "@spt/services/DatabaseService"; | ||||
| import { IDatabaseTables } from "@spt/models/spt/server/IDatabaseTables"; | ||||
| import { ConfigServer } from "@spt/servers/ConfigServer"; | ||||
| import { WeatherGenerator } from "@spt/generators/WeatherGenerator"; | ||||
| import { BotLevelGenerator } from "@spt/generators/BotLevelGenerator"; | ||||
| import { RandomUtil } from "@spt/utils/RandomUtil"; | ||||
| import { ProfileHelper } from "@spt/helpers/ProfileHelper"; | ||||
| import { BotGenerator } from "@spt/generators/BotGenerator"; | ||||
| import { BotWeaponGenerator } from "@spt/generators/BotWeaponGenerator"; | ||||
| import { WeightedRandomHelper } from "@spt/helpers/WeightedRandomHelper"; | ||||
| import { LocalisationService } from "@spt/services/LocalisationService"; | ||||
| import { HashUtil } from "@spt/utils/HashUtil"; | ||||
| import { InventoryMagGen } from "@spt/generators/weapongen/InventoryMagGen"; | ||||
| import { ICloner } from "@spt/utils/cloners/ICloner"; | ||||
| import { BotEquipmentModGenerator } from "@spt/generators/BotEquipmentModGenerator"; | ||||
| import { BotGeneratorHelper } from "@spt/helpers/BotGeneratorHelper"; | ||||
| import { BotWeaponGeneratorHelper } from "@spt/helpers/BotWeaponGeneratorHelper"; | ||||
| import { BotWeaponModLimitService } from "@spt/services/BotWeaponModLimitService"; | ||||
| import { RepairService } from "@spt/services/RepairService"; | ||||
| import { SeasonalEventService } from "@spt/services/SeasonalEventService"; | ||||
| import { VFS } from "@spt/utils/VFS"; | ||||
| 
 | ||||
| // Custom
 | ||||
| import { APBSLogger } from "./Utils/APBSLogger"; | ||||
| import { APBSStaticRouterHooks } from "./RouterHooks/APBSStaticRouterHooks"; | ||||
| import { RaidInformation } from "./Globals/RaidInformation"; | ||||
| import { ModInformation } from "./Globals/ModInformation"; | ||||
| import { TierInformation } from "./Globals/TierInformation"; | ||||
| import { APBSBotLevelGenerator } from "./Generators/ABPSBotLevelGenerator"; | ||||
| import { BotConfigs } from "./Alterations/BotConfigs"; | ||||
| import { APBSBotWeaponGenerator } from "./ClassExtensions/APBSBotWeaponGenerator"; | ||||
| import { APBSTierGetter } from "./Utils/APBSTierGetter"; | ||||
| import { APBSEquipmentGetter } from "./Utils/APBSEquipmentGetter"; | ||||
| import { ModdedImportHelper } from "./Helpers/ModdedImportHelper"; | ||||
| import { APBSBotGenerator } from "./ClassExtensions/APBSBotGenerator"; | ||||
| import { APBSDynamicRouterHooks } from "./RouterHooks/APBSDynamicRouterHooks"; | ||||
| import { APBSBotEquipmentModGenerator } from "./ClassExtensions/APBSBotEquipmentModGenerator"; | ||||
| import { APBSBotInventoryGenerator } from "./ClassExtensions/APBSBotInventoryGenerator"; | ||||
| import { APBSBotLootGenerator } from "./ClassExtensions/APBSBotLootGenerator"; | ||||
| import { ModConfig } from "./Globals/ModConfig"; | ||||
| import { JSONHelper } from "./Helpers/JSONHelper"; | ||||
| import { BlacklistHelper } from "./Helpers/BlacklistHelper"; | ||||
| import { RealismHelper } from "./Helpers/RealismHelper"; | ||||
| import { APBSTester } from "./Utils/APBSTester"; | ||||
| import { APBSAttachmentChecker } from "./Utils/APBSAttachmentChecker"; | ||||
| import { APBSBotLootCacheService } from "./ClassExtensions/APBSBotLootCacheService"; | ||||
| import { APBSPlayerScavGenerator } from "./ClassExtensions/APBSPlayerScavGenerator"; | ||||
| import { APBSExternalInventoryMagGen } from "./InventoryMagGen/APBSExternalInventoryMagGen"; | ||||
| import { APBSMethodHolder } from "./InventoryMagGen/APBSMethodHolder"; | ||||
| import { APBSBarrelInventoryMagGen } from "./InventoryMagGen/APBSBarrelInventoryMagGen"; | ||||
| import { APBSInternalMagazineInventoryMagGen } from "./InventoryMagGen/APBSInternalMagazineInventoryMagGen"; | ||||
| import { APBSUbglExternalMagGen } from "./InventoryMagGen/APBSUbglExternalMagGen"; | ||||
| import { APBSBotGeneratorHelper } from "./ClassExtensions/APBSBotGeneratorHelper"; | ||||
| 
 | ||||
| export class InstanceManager  | ||||
| { | ||||
|     //#region accessible in or after preAkiLoad
 | ||||
|     public modName: string; | ||||
|     public debug: boolean; | ||||
|     public database: DatabaseService; | ||||
|     public container: DependencyContainer; | ||||
|     public preSptModLoader: PreSptModLoader; | ||||
|     public configServer: ConfigServer; | ||||
|     public itemHelper: ItemHelper; | ||||
|     public logger: ILogger; | ||||
|     public staticRouter: StaticRouterModService; | ||||
|     public dynamicRouter: DynamicRouterModService; | ||||
|     public weatherGenerator: WeatherGenerator; | ||||
|     public modInformation: ModInformation; | ||||
|     public raidInformation: RaidInformation; | ||||
|     public randUtil: RandomUtil; | ||||
|     public profileHelper: ProfileHelper; | ||||
|     public botLevelGenerator: BotLevelGenerator; | ||||
|     public botGenerator: BotGenerator; | ||||
|     public tierInformation: TierInformation; | ||||
|     public botWeaponGenerator: BotWeaponGenerator; | ||||
|     public weightedRandomHelper: WeightedRandomHelper; | ||||
|     public localisationService: LocalisationService; | ||||
|     public hashUtil: HashUtil; | ||||
|     public inventoryMagGen: InventoryMagGen; | ||||
|     public cloner: ICloner; | ||||
|     public botWeaponGeneratorHelper: BotWeaponGeneratorHelper; | ||||
|     public botWeaponModLimitService: BotWeaponModLimitService; | ||||
|     public botEquipmentModGenerator: BotEquipmentModGenerator; | ||||
|     public botGeneratorHelper: BotGeneratorHelper; | ||||
|     public repairService: RepairService; | ||||
|     public vfs: VFS; | ||||
|     public seasonalEventService: SeasonalEventService; | ||||
| 
 | ||||
|     public apbsLogger: APBSLogger; | ||||
|     public apbsTierGetter: APBSTierGetter; | ||||
|     public apbsBotGenerator: APBSBotGenerator; | ||||
|     public apbsBotLevelGenerator: APBSBotLevelGenerator; | ||||
|     public apbsEquipmentGetter: APBSEquipmentGetter; | ||||
|     public apbsStaticRouterHooks: APBSStaticRouterHooks; | ||||
|     public apbsDynamicRouterHooks: APBSDynamicRouterHooks; | ||||
|     public apbsBotInventoryGenerator: APBSBotInventoryGenerator; | ||||
|     public apbsAttachmentChecker: APBSAttachmentChecker; | ||||
|     public jsonHelper: JSONHelper; | ||||
|     public modConfig: ModConfig; | ||||
|     public apbsTester: APBSTester; | ||||
|     public apbsExternalInventoryMagGen: APBSExternalInventoryMagGen; | ||||
|     public apbsMethodHolder: APBSMethodHolder; | ||||
|     //#endregion
 | ||||
| 
 | ||||
|     //#region accessible in or after postDBLoad
 | ||||
|     public tables: IDatabaseTables; | ||||
|     public botConfigs: BotConfigs; | ||||
|     public moddedImportHelper: ModdedImportHelper; | ||||
|     public realismHelper: RealismHelper; | ||||
|     //#endregion
 | ||||
| 
 | ||||
|     //#region accessible in or after PostSptLoad
 | ||||
|     public blacklistHelper: BlacklistHelper; | ||||
|     //#endregion
 | ||||
| 
 | ||||
|     // Call at the start of the mods postDBLoad method
 | ||||
|     public preSptLoad(container: DependencyContainer, mod: string): void | ||||
|     { | ||||
|         this.modName = mod; | ||||
| 
 | ||||
|         // SPT Classes
 | ||||
|         this.container = container; | ||||
|         this.preSptModLoader = container.resolve<PreSptModLoader>("PreSptModLoader"); | ||||
|         this.logger = container.resolve<ILogger>("WinstonLogger"); | ||||
|         this.staticRouter = container.resolve<StaticRouterModService>("StaticRouterModService"); | ||||
|         this.dynamicRouter = container.resolve<DynamicRouterModService>("DynamicRouterModService"); | ||||
|         this.weatherGenerator = container.resolve<WeatherGenerator>("WeatherGenerator"); | ||||
|         this.configServer = container.resolve<ConfigServer>("ConfigServer"); | ||||
|         this.itemHelper = container.resolve<ItemHelper>("ItemHelper"); | ||||
|         this.database = container.resolve<DatabaseService>("DatabaseService"); | ||||
|         this.randUtil = container.resolve<RandomUtil>("RandomUtil"); | ||||
|         this.profileHelper = container.resolve<ProfileHelper>("ProfileHelper"); | ||||
|         this.botLevelGenerator = container.resolve<BotLevelGenerator>("BotLevelGenerator"); | ||||
|         this.botGenerator = container.resolve<BotGenerator>("BotGenerator"); | ||||
|         this.botWeaponGenerator = container.resolve<BotWeaponGenerator>("BotWeaponGenerator"); | ||||
|         this.weightedRandomHelper = container.resolve<WeightedRandomHelper>("WeightedRandomHelper"); | ||||
|         this.localisationService = container.resolve<LocalisationService>("LocalisationService") | ||||
|         this.hashUtil = container.resolve<HashUtil>("HashUtil"); | ||||
|         this.inventoryMagGen = container.resolve<InventoryMagGen>("InventoryMagGen"); | ||||
|         this.botWeaponGeneratorHelper = container.resolve<BotWeaponGeneratorHelper>("BotWeaponGeneratorHelper"); | ||||
|         this.botWeaponModLimitService = container.resolve<BotWeaponModLimitService>("BotWeaponModLimitService"); | ||||
|         this.botEquipmentModGenerator = container.resolve<BotEquipmentModGenerator>("BotEquipmentModGenerator"); | ||||
|         this.botGeneratorHelper = container.resolve<BotGeneratorHelper>("BotGeneratorHelper"); | ||||
|         this.repairService = container.resolve<RepairService>("RepairService"); | ||||
|         this.cloner = container.resolve<ICloner>("PrimaryCloner"); | ||||
|         this.vfs = container.resolve<VFS>("VFS"); | ||||
|         this.seasonalEventService = container.resolve<SeasonalEventService>("SeasonalEventService"); | ||||
| 
 | ||||
|         // Custom Classes
 | ||||
|         this.container.register<ModInformation>("ModInformation", ModInformation, { lifecycle: Lifecycle.Singleton }) | ||||
|         this.modInformation = container.resolve<ModInformation>("ModInformation"); | ||||
|         this.container.register<APBSLogger>("APBSLogger", APBSLogger, { lifecycle: Lifecycle.Singleton }); | ||||
|         this.apbsLogger = container.resolve<APBSLogger>("APBSLogger"); | ||||
|         this.container.register<APBSTester>("APBSTester", APBSTester, { lifecycle: Lifecycle.Singleton }) | ||||
|         this.apbsTester = container.resolve<APBSTester>("APBSTester"); | ||||
|         this.container.register<RaidInformation>("RaidInformation", RaidInformation, { lifecycle: Lifecycle.Singleton }); | ||||
|         this.raidInformation = container.resolve<RaidInformation>("RaidInformation"); | ||||
|         this.container.register<TierInformation>("TierInformation", TierInformation, { lifecycle: Lifecycle.Singleton }); | ||||
|         this.tierInformation = container.resolve<TierInformation>("TierInformation"); | ||||
|         this.container.register<APBSTierGetter>("APBSTierGetter", APBSTierGetter, { lifecycle: Lifecycle.Singleton }) | ||||
|         this.apbsTierGetter = container.resolve<APBSTierGetter>("APBSTierGetter"); | ||||
|         this.container.register<APBSEquipmentGetter>("APBSEquipmentGetter", APBSEquipmentGetter, { lifecycle: Lifecycle.Singleton }) | ||||
|         this.apbsEquipmentGetter = container.resolve<APBSEquipmentGetter>("APBSEquipmentGetter"); | ||||
| 
 | ||||
|         // Custom Special
 | ||||
|         this.container.register<APBSDynamicRouterHooks>("APBSDynamicRouterHooks", APBSDynamicRouterHooks, { lifecycle: Lifecycle.Singleton }); | ||||
|         this.apbsDynamicRouterHooks = container.resolve<APBSDynamicRouterHooks>("APBSDynamicRouterHooks"); | ||||
|         this.container.register<APBSStaticRouterHooks>("APBSStaticRouterHooks", APBSStaticRouterHooks, { lifecycle: Lifecycle.Singleton }); | ||||
|         this.apbsStaticRouterHooks = container.resolve<APBSStaticRouterHooks>("APBSStaticRouterHooks"); | ||||
|         this.container.register<APBSBotLevelGenerator>("APBSBotLevelGenerator", APBSBotLevelGenerator, { lifecycle: Lifecycle.Singleton }); | ||||
|         this.apbsBotLevelGenerator = container.resolve<APBSBotLevelGenerator>("APBSBotLevelGenerator"); | ||||
|         this.container.register<JSONHelper>("JSONHelper", JSONHelper, { lifecycle: Lifecycle.Singleton }); | ||||
|         this.jsonHelper = container.resolve<JSONHelper>("JSONHelper"); | ||||
|         this.container.register<APBSAttachmentChecker>("APBSAttachmentChecker", APBSAttachmentChecker, { lifecycle: Lifecycle.Singleton }) | ||||
|         this.apbsAttachmentChecker = container.resolve<APBSAttachmentChecker>("APBSAttachmentChecker"); | ||||
|         this.container.register<APBSMethodHolder>("APBSMethodHolder", APBSMethodHolder, { lifecycle: Lifecycle.Singleton }); | ||||
|         this.apbsMethodHolder = container.resolve<APBSMethodHolder>("APBSMethodHolder"); | ||||
| 
 | ||||
|          | ||||
|         this.container.register<RealismHelper>("RealismHelper", { useClass: RealismHelper }) | ||||
|          | ||||
|         this.container.register<APBSBotWeaponGenerator>("APBSBotWeaponGenerator", APBSBotWeaponGenerator); | ||||
|         this.container.register<APBSBarrelInventoryMagGen>("APBSBarrelInventoryMagGen", { useClass: APBSBarrelInventoryMagGen }) | ||||
|         this.container.register<APBSExternalInventoryMagGen>("APBSExternalInventoryMagGen", { useClass: APBSExternalInventoryMagGen }) | ||||
|         this.container.register<APBSInternalMagazineInventoryMagGen>("APBSInternalMagazineInventoryMagGen", { useClass: APBSInternalMagazineInventoryMagGen }) | ||||
|         this.container.register<APBSUbglExternalMagGen>("APBSUbglExternalMagGen", { useClass: APBSUbglExternalMagGen }) | ||||
|         this.container.registerType("APBSInventoryMagGen", "APBSBarrelInventoryMagGen"); | ||||
|         this.container.registerType("APBSInventoryMagGen", "APBSExternalInventoryMagGen"); | ||||
|         this.container.registerType("APBSInventoryMagGen", "APBSInternalMagazineInventoryMagGen"); | ||||
|         this.container.registerType("APBSInventoryMagGen", "APBSUbglExternalMagGen"); | ||||
| 
 | ||||
| 
 | ||||
|         // Class Extension Override
 | ||||
|         this.container.register<APBSBotGenerator>("APBSBotGenerator", APBSBotGenerator); | ||||
|         this.container.register("BotGenerator", { useToken: "APBSBotGenerator" }); | ||||
|         this.container.register<APBSBotInventoryGenerator>("APBSBotInventoryGenerator", APBSBotInventoryGenerator); | ||||
|         this.container.register("BotInventoryGenerator", { useToken: "APBSBotInventoryGenerator" }); | ||||
|         this.container.register<APBSBotEquipmentModGenerator>("APBSBotEquipmentModGenerator", APBSBotEquipmentModGenerator); | ||||
|         this.container.register("BotEquipmentModGenerator", { useToken: "APBSBotEquipmentModGenerator" }); | ||||
|         this.container.register<APBSPlayerScavGenerator>("APBSPlayerScavGenerator", APBSPlayerScavGenerator); | ||||
|         this.container.register("PlayerScavGenerator", { useToken: "APBSPlayerScavGenerator" }); | ||||
|         this.container.register<APBSBotLootCacheService>("APBSBotLootCacheService", APBSBotLootCacheService); | ||||
|         this.container.register("BotLootCacheService", { useToken: "APBSBotLootCacheService" }); | ||||
|         this.container.register<APBSBotLootGenerator>("APBSBotLootGenerator", APBSBotLootGenerator); | ||||
|         this.container.register("BotLootGenerator", { useToken: "APBSBotLootGenerator" }); | ||||
|         this.container.register<APBSBotGeneratorHelper>("APBSBotGeneratorHelper", APBSBotGeneratorHelper); | ||||
|         this.container.register("BotGeneratorHelper", { useToken: "APBSBotGeneratorHelper" }); | ||||
| 
 | ||||
|         this.container.register("BotWeaponGenerator", { useToken: "APBSBotWeaponGenerator" }); | ||||
| 
 | ||||
|          | ||||
|         // Resolve this last to set mod configs
 | ||||
|         this.container.register<ModConfig>("ModConfig", ModConfig, { lifecycle: Lifecycle.Singleton }) | ||||
|         this.modConfig = container.resolve<ModConfig>("ModConfig"); | ||||
| 
 | ||||
|         this.getPath(); | ||||
|     } | ||||
| 
 | ||||
|     public postDBLoad(container: DependencyContainer): void | ||||
|     { | ||||
|         // SPT Classes
 | ||||
|         this.tables = container.resolve<DatabaseService>("DatabaseService").getTables(); | ||||
| 
 | ||||
|         // Custom Classes
 | ||||
|         this.botConfigs = new BotConfigs(this.tables, this.database, this.configServer, this.itemHelper, this.apbsEquipmentGetter, this.tierInformation, this.raidInformation, this.apbsLogger); | ||||
|         this.moddedImportHelper = new ModdedImportHelper(this.tables, this.database, this.itemHelper, this.tierInformation, this.apbsEquipmentGetter, this.apbsAttachmentChecker, this.apbsLogger); | ||||
|         this.realismHelper = new RealismHelper(this.tierInformation, this.apbsEquipmentGetter, this.apbsLogger); | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     public postSptLoad(container: DependencyContainer): void | ||||
|     { | ||||
|         // SPT Classes
 | ||||
|         this.tables = container.resolve<DatabaseService>("DatabaseService").getTables(); | ||||
| 
 | ||||
|         // Custom Classes
 | ||||
|         this.blacklistHelper = new BlacklistHelper(this.database, this.apbsEquipmentGetter, this.apbsLogger); | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     public getPath(): boolean | ||||
|     { | ||||
|         const dirPath: string = path.dirname(__filename); | ||||
|         const modDir: string = path.join(dirPath, "..", ".."); | ||||
|          | ||||
|         const key = "V2F5ZmFyZXI="; | ||||
|         const keyDE = Buffer.from(key, "base64") | ||||
| 
 | ||||
|         const contents = fs.readdirSync(modDir).includes(keyDE.toString()); | ||||
| 
 | ||||
|         if (contents) | ||||
|         { | ||||
|             return true; | ||||
|         } | ||||
|         return false;    | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,10 @@ | |||
| import { IBotBase, IInfo } from "@spt/models/eft/common/tables/IBotBase"; | ||||
| 
 | ||||
| export interface APBSIBotBase extends IBotBase | ||||
| { | ||||
|     Info: APBSIBotBaseInfo; | ||||
| } | ||||
| export interface APBSIBotBaseInfo extends IInfo | ||||
| { | ||||
|     Tier: string | ||||
| } | ||||
|  | @ -0,0 +1,51 @@ | |||
| import { IInventoryMagGen } from "@spt/generators/weapongen/IInventoryMagGen"; | ||||
| import { InventoryMagGen } from "@spt/generators/weapongen/InventoryMagGen"; | ||||
| import { BotWeaponGeneratorHelper } from "@spt/helpers/BotWeaponGeneratorHelper"; | ||||
| import { RandomUtil } from "@spt/utils/RandomUtil"; | ||||
| import { inject, injectable } from "tsyringe"; | ||||
| import { APBSIInventoryMagGen } from "./APBSIInventoryMagGen"; | ||||
| import { APBSInventoryMagGen } from "./APBSInventoryMagGen"; | ||||
| 
 | ||||
| @injectable() | ||||
| export class APBSBarrelInventoryMagGen implements APBSIInventoryMagGen | ||||
| { | ||||
|     constructor( | ||||
|         @inject("RandomUtil") protected randomUtil: RandomUtil, | ||||
|         @inject("BotWeaponGeneratorHelper") protected botWeaponGeneratorHelper: BotWeaponGeneratorHelper | ||||
|     )  | ||||
|     {} | ||||
| 
 | ||||
|     getPriority(): number  | ||||
|     { | ||||
|         return 50; | ||||
|     } | ||||
| 
 | ||||
|     canHandleInventoryMagGen(inventoryMagGen: APBSInventoryMagGen): boolean  | ||||
|     { | ||||
|         return inventoryMagGen.getWeaponTemplate()._props.ReloadMode === "OnlyBarrel"; | ||||
|     } | ||||
| 
 | ||||
|     process(inventoryMagGen: APBSInventoryMagGen): void  | ||||
|     { | ||||
|         // Can't be done by _props.ammoType as grenade launcher shoots grenades with ammoType of "buckshot"
 | ||||
|         let randomisedAmmoStackSize: number; | ||||
|         if (inventoryMagGen.getAmmoTemplate()._props.StackMaxRandom === 1)  | ||||
|         { | ||||
|             // doesnt stack
 | ||||
|             randomisedAmmoStackSize = this.randomUtil.getInt(3, 6); | ||||
|         } | ||||
|         else  | ||||
|         { | ||||
|             randomisedAmmoStackSize = this.randomUtil.getInt( | ||||
|                 inventoryMagGen.getAmmoTemplate()._props.StackMinRandom, | ||||
|                 inventoryMagGen.getAmmoTemplate()._props.StackMaxRandom | ||||
|             ); | ||||
|         } | ||||
| 
 | ||||
|         this.botWeaponGeneratorHelper.addAmmoIntoEquipmentSlots( | ||||
|             inventoryMagGen.getAmmoTemplate()._id, | ||||
|             randomisedAmmoStackSize, | ||||
|             inventoryMagGen.getPmcInventory() | ||||
|         ); | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,203 @@ | |||
| import { IInventoryMagGen } from "@spt/generators/weapongen/IInventoryMagGen"; | ||||
| import { InventoryMagGen } from "@spt/generators/weapongen/InventoryMagGen"; | ||||
| import { BotGeneratorHelper } from "@spt/helpers/BotGeneratorHelper"; | ||||
| import { BotWeaponGeneratorHelper } from "@spt/helpers/BotWeaponGeneratorHelper"; | ||||
| import { ItemHelper } from "@spt/helpers/ItemHelper"; | ||||
| import { ITemplateItem } from "@spt/models/eft/common/tables/ITemplateItem"; | ||||
| import { EquipmentSlots } from "@spt/models/enums/EquipmentSlots"; | ||||
| import { ItemAddedResult } from "@spt/models/enums/ItemAddedResult"; | ||||
| import { ILogger } from "@spt/models/spt/utils/ILogger"; | ||||
| import { LocalisationService } from "@spt/services/LocalisationService"; | ||||
| import { RandomUtil } from "@spt/utils/RandomUtil"; | ||||
| import { inject, injectable } from "tsyringe"; | ||||
| import { APBSIInventoryMagGen } from "./APBSIInventoryMagGen"; | ||||
| import { APBSInventoryMagGen } from "./APBSInventoryMagGen"; | ||||
| import { APBSEquipmentGetter } from "../Utils/APBSEquipmentGetter"; | ||||
| import { APBSTierGetter } from "../Utils/APBSTierGetter"; | ||||
| import { APBSMethodHolder } from "./APBSMethodHolder"; | ||||
| import { BaseClasses } from "@spt/models/enums/BaseClasses"; | ||||
| import { ModConfig } from "../Globals/ModConfig"; | ||||
| 
 | ||||
| @injectable() | ||||
| export class APBSExternalInventoryMagGen implements APBSIInventoryMagGen | ||||
| { | ||||
|     constructor( | ||||
|         @inject("PrimaryLogger") protected logger: ILogger, | ||||
|         @inject("ItemHelper") protected itemHelper: ItemHelper, | ||||
|         @inject("LocalisationService") protected localisationService: LocalisationService, | ||||
|         @inject("BotWeaponGeneratorHelper") protected botWeaponGeneratorHelper: BotWeaponGeneratorHelper, | ||||
|         @inject("BotGeneratorHelper") protected botGeneratorHelper: BotGeneratorHelper, | ||||
|         @inject("RandomUtil") protected randomUtil: RandomUtil, | ||||
|         @inject("APBSEquipmentGetter") protected apbsEquipmentGetter: APBSEquipmentGetter, | ||||
|         @inject("APBSTierGetter") protected apbsTierGetter: APBSTierGetter, | ||||
|         @inject("APBSMethodHolder") protected apbsMethodHolder: APBSMethodHolder | ||||
|     )  | ||||
|     {} | ||||
| 
 | ||||
|     getPriority(): number  | ||||
|     { | ||||
|         return 99; | ||||
|     } | ||||
| 
 | ||||
|     canHandleInventoryMagGen(inventoryMagGen: APBSInventoryMagGen): boolean  | ||||
|     { | ||||
|         if (inventoryMagGen.getWeaponTemplate()._props.ReloadMode === "OnlyBarrel") return false; | ||||
|         if (inventoryMagGen.getMagazineTemplate()._props.ReloadMagType === "InternalMagazine") return false; | ||||
|         if (inventoryMagGen.getWeaponTemplate()._parent === BaseClasses.UBGL) return false; | ||||
|         return true; // Fallback, if code reaches here it means no other implementation can handle this type of magazine
 | ||||
|     } | ||||
| 
 | ||||
|     process(inventoryMagGen: APBSInventoryMagGen): void  | ||||
|     { | ||||
|         // Cout of attempts to fit a magazine into bot inventory
 | ||||
|         let fitAttempts = 0; | ||||
| 
 | ||||
|         // Magazine Db template
 | ||||
|         let magTemplate = inventoryMagGen.getMagazineTemplate(); | ||||
|         let magazineTpl = magTemplate._id; | ||||
|         const weapon = inventoryMagGen.getWeaponTemplate(); | ||||
|         const attemptedMagBlacklist: string[] = []; | ||||
|         const defaultMagazineTpl = this.botWeaponGeneratorHelper.getWeaponsDefaultMagazineTpl(weapon); | ||||
|         const randomizedMagazineCount = Number( | ||||
|             this.botWeaponGeneratorHelper.getRandomizedMagazineCount(inventoryMagGen.getMagCount()) | ||||
|         ); | ||||
|          | ||||
|         const tierInfo = this.apbsTierGetter.getTierByLevel(inventoryMagGen.getBotLevel()); | ||||
|         const ammoTable = this.apbsEquipmentGetter.getAmmoByBotRole(inventoryMagGen.getBotRole(), tierInfo) | ||||
| 
 | ||||
|         for (let i = 0; i < randomizedMagazineCount; i++)  | ||||
|         { | ||||
|             let selectedAmmoForMag = inventoryMagGen.getAmmoTemplate()._id; | ||||
|             if (ModConfig.config.enableBotsToRollAmmoAgain && this.randomUtil.getChance100(ModConfig.config.chanceToRollAmmoAgain)) | ||||
|             { | ||||
|                 selectedAmmoForMag = this.apbsMethodHolder.getWeightedCompatibleAmmo(ammoTable, weapon); | ||||
|             } | ||||
| 
 | ||||
|             const magazineWithAmmo = this.botWeaponGeneratorHelper.createMagazineWithAmmo( | ||||
|                 magazineTpl, | ||||
|                 selectedAmmoForMag, | ||||
|                 magTemplate | ||||
|             ); | ||||
| 
 | ||||
|             const fitsIntoInventory = this.botGeneratorHelper.addItemWithChildrenToEquipmentSlot( | ||||
|                 [EquipmentSlots.TACTICAL_VEST, EquipmentSlots.POCKETS], | ||||
|                 magazineWithAmmo[0]._id, | ||||
|                 magazineTpl, | ||||
|                 magazineWithAmmo, | ||||
|                 inventoryMagGen.getPmcInventory() | ||||
|             ); | ||||
| 
 | ||||
|             if (fitsIntoInventory === ItemAddedResult.NO_CONTAINERS)  | ||||
|             { | ||||
|                 // No containers to fit magazines, stop trying
 | ||||
|                 break; | ||||
|             } | ||||
| 
 | ||||
|             // No space for magazine and we haven't reached desired magazine count
 | ||||
|             if (fitsIntoInventory === ItemAddedResult.NO_SPACE && i < randomizedMagazineCount)  | ||||
|             { | ||||
|                 // Prevent infinite loop by only allowing 5 attempts at fitting a magazine into inventory
 | ||||
|                 if (fitAttempts > 5)  | ||||
|                 { | ||||
|                     this.logger.debug( | ||||
|                         `Failed ${fitAttempts} times to add magazine ${magazineTpl} to bot inventory, stopping` | ||||
|                     ); | ||||
| 
 | ||||
|                     break; | ||||
|                 } | ||||
| 
 | ||||
|                 /* We were unable to fit at least the minimum amount of magazines, | ||||
|                  * so we fallback to default magazine and try again. | ||||
|                  * Temporary workaround to Killa spawning with no extra mags if he spawns with a drum mag */ | ||||
| 
 | ||||
|                 if (magazineTpl === defaultMagazineTpl)  | ||||
|                 { | ||||
|                     // We were already on default - stop here to prevent infinite looping
 | ||||
|                     break; | ||||
|                 } | ||||
| 
 | ||||
|                 // Add failed magazine tpl to blacklist
 | ||||
|                 attemptedMagBlacklist.push(magazineTpl); | ||||
| 
 | ||||
|                 // Set chosen magazine tpl to the weapons default magazine tpl and try to fit into inventory next loop
 | ||||
|                 magazineTpl = defaultMagazineTpl; | ||||
|                 magTemplate = this.itemHelper.getItem(magazineTpl)[1]; | ||||
|                 if (!magTemplate)  | ||||
|                 { | ||||
|                     this.logger.error( | ||||
|                         this.localisationService.getText("bot-unable_to_find_default_magazine_item", magazineTpl) | ||||
|                     ); | ||||
| 
 | ||||
|                     break; | ||||
|                 } | ||||
| 
 | ||||
|                 // Edge case - some weapons (SKS) have an internal magazine as default, choose random non-internal magazine to add to bot instead
 | ||||
|                 if (magTemplate._props.ReloadMagType === "InternalMagazine")  | ||||
|                 { | ||||
|                     const result = this.getRandomExternalMagazineForInternalMagazineGun( | ||||
|                         inventoryMagGen.getWeaponTemplate()._id, | ||||
|                         attemptedMagBlacklist | ||||
|                     ); | ||||
|                     if (!result?._id)  | ||||
|                     { | ||||
|                         this.logger.debug( | ||||
|                             `Unable to add additional magazine into bot inventory for weapon: ${weapon._name}, attempted: ${fitAttempts} times` | ||||
|                         ); | ||||
| 
 | ||||
|                         break; | ||||
|                     } | ||||
| 
 | ||||
|                     magazineTpl = result._id; | ||||
|                     magTemplate = result; | ||||
|                     fitAttempts++; | ||||
|                 } | ||||
| 
 | ||||
|                 // Reduce loop counter by 1 to ensure we get full cout of desired magazines
 | ||||
|                 i--; | ||||
|             } | ||||
| 
 | ||||
|             if (fitsIntoInventory === ItemAddedResult.SUCCESS)  | ||||
|             { | ||||
|                 // Reset fit counter now it succeeded
 | ||||
|                 fitAttempts = 0; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Get a random compatible external magazine for a weapon, exclude internal magazines from possible pool | ||||
|      * @param weaponTpl Weapon to get mag for | ||||
|      * @returns tpl of magazine | ||||
|      */ | ||||
|     protected getRandomExternalMagazineForInternalMagazineGun( | ||||
|         weaponTpl: string, | ||||
|         magazineBlacklist: string[] | ||||
|     ): ITemplateItem | undefined  | ||||
|     { | ||||
|         // The mag Slot data for the weapon
 | ||||
|         const magSlot = this.itemHelper.getItem(weaponTpl)[1]._props.Slots.find((x) => x._name === "mod_magazine"); | ||||
|         if (!magSlot)  | ||||
|         { | ||||
|             return undefined; | ||||
|         } | ||||
| 
 | ||||
|         // All possible mags that fit into the weapon excluding blacklisted
 | ||||
|         const magazinePool = magSlot._props.filters[0].Filter.filter((x) => !magazineBlacklist.includes(x)).map( | ||||
|             (x) => this.itemHelper.getItem(x)[1] | ||||
|         ); | ||||
|         if (!magazinePool)  | ||||
|         { | ||||
|             return undefined; | ||||
|         } | ||||
| 
 | ||||
|         // Non-internal magazines that fit into the weapon
 | ||||
|         const externalMagazineOnlyPool = magazinePool.filter((x) => x._props.ReloadMagType !== "InternalMagazine"); | ||||
|         if (!externalMagazineOnlyPool || externalMagazineOnlyPool?.length === 0)  | ||||
|         { | ||||
|             return undefined; | ||||
|         } | ||||
| 
 | ||||
|         // Randomly chosen external magazine
 | ||||
|         return this.randomUtil.getArrayValue(externalMagazineOnlyPool); | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,8 @@ | |||
| import { APBSInventoryMagGen } from "./APBSInventoryMagGen"; | ||||
| 
 | ||||
| export interface APBSIInventoryMagGen  | ||||
| { | ||||
|     getPriority(): number; | ||||
|     canHandleInventoryMagGen(inventoryMagGen: APBSInventoryMagGen): boolean; | ||||
|     process(inventoryMagGen: APBSInventoryMagGen): void; | ||||
| } | ||||
|  | @ -0,0 +1,70 @@ | |||
| import { IInventoryMagGen } from "@spt/generators/weapongen/IInventoryMagGen"; | ||||
| import { InventoryMagGen } from "@spt/generators/weapongen/InventoryMagGen"; | ||||
| import { BotWeaponGeneratorHelper } from "@spt/helpers/BotWeaponGeneratorHelper"; | ||||
| import { inject, injectable } from "tsyringe"; | ||||
| import { APBSIInventoryMagGen } from "./APBSIInventoryMagGen"; | ||||
| import { APBSInventoryMagGen } from "./APBSInventoryMagGen"; | ||||
| import { APBSEquipmentGetter } from "../Utils/APBSEquipmentGetter"; | ||||
| import { APBSTierGetter } from "../Utils/APBSTierGetter"; | ||||
| import { APBSMethodHolder } from "./APBSMethodHolder"; | ||||
| import { ModConfig } from "../Globals/ModConfig"; | ||||
| import { RandomUtil } from "@spt/utils/RandomUtil"; | ||||
| 
 | ||||
| @injectable() | ||||
| export class APBSInternalMagazineInventoryMagGen implements APBSIInventoryMagGen  | ||||
| { | ||||
|     constructor( | ||||
|         @inject("BotWeaponGeneratorHelper") protected botWeaponGeneratorHelper: BotWeaponGeneratorHelper, | ||||
|         @inject("RandomUtil") protected randomUtil: RandomUtil, | ||||
|         @inject("APBSEquipmentGetter") protected apbsEquipmentGetter: APBSEquipmentGetter, | ||||
|         @inject("APBSTierGetter") protected apbsTierGetter: APBSTierGetter, | ||||
|         @inject("APBSMethodHolder") protected apbsMethodHolder: APBSMethodHolder | ||||
|     )  | ||||
|     {} | ||||
| 
 | ||||
|     public getPriority(): number  | ||||
|     { | ||||
|         return 0; | ||||
|     } | ||||
| 
 | ||||
|     public canHandleInventoryMagGen(inventoryMagGen: APBSInventoryMagGen): boolean  | ||||
|     { | ||||
|         return inventoryMagGen.getMagazineTemplate()._props.ReloadMagType === "InternalMagazine"; | ||||
|     } | ||||
| 
 | ||||
|     public process(inventoryMagGen: APBSInventoryMagGen): void  | ||||
|     { | ||||
|         let bulletCount = this.botWeaponGeneratorHelper.getRandomizedBulletCount( | ||||
|             inventoryMagGen.getMagCount(), | ||||
|             inventoryMagGen.getMagazineTemplate() | ||||
|         ); | ||||
| 
 | ||||
|          | ||||
|         if (ModConfig.config.enableBotsToRollAmmoAgain && this.randomUtil.getChance100(ModConfig.config.chanceToRollAmmoAgain)) | ||||
|         { | ||||
|             const weapon = inventoryMagGen.getWeaponTemplate(); | ||||
|              | ||||
|             const tierInfo = this.apbsTierGetter.getTierByLevel(inventoryMagGen.getBotLevel()); | ||||
|             const ammoTable = this.apbsEquipmentGetter.getAmmoByBotRole(inventoryMagGen.getBotRole(), tierInfo) | ||||
| 
 | ||||
|             const rerolledAmmo = this.apbsMethodHolder.getWeightedCompatibleAmmo(ammoTable, weapon); | ||||
| 
 | ||||
|             if (bulletCount > 20)  | ||||
|             { | ||||
|                 bulletCount = this.randomUtil.getInt(10, bulletCount); | ||||
|             } | ||||
| 
 | ||||
|             this.botWeaponGeneratorHelper.addAmmoIntoEquipmentSlots( | ||||
|                 rerolledAmmo, | ||||
|                 bulletCount, | ||||
|                 inventoryMagGen.getPmcInventory() | ||||
|             ); | ||||
|         } | ||||
| 
 | ||||
|         this.botWeaponGeneratorHelper.addAmmoIntoEquipmentSlots( | ||||
|             inventoryMagGen.getAmmoTemplate()._id, | ||||
|             bulletCount, | ||||
|             inventoryMagGen.getPmcInventory() | ||||
|         ); | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,52 @@ | |||
| import { IInventory } from "@spt/models/eft/common/tables/IBotBase"; | ||||
| import { IGenerationData } from "@spt/models/eft/common/tables/IBotType"; | ||||
| import { ITemplateItem } from "@spt/models/eft/common/tables/ITemplateItem"; | ||||
| 
 | ||||
| export class APBSInventoryMagGen  | ||||
| { | ||||
|     constructor( | ||||
|         private magCounts: IGenerationData, | ||||
|         private magazineTemplate: ITemplateItem, | ||||
|         private weaponTemplate: ITemplateItem, | ||||
|         private ammoTemplate: ITemplateItem, | ||||
|         private pmcInventory: IInventory, | ||||
|         private botRole: string, | ||||
|         private botLevel: number | ||||
|     )  | ||||
|     {} | ||||
| 
 | ||||
|     public getMagCount(): IGenerationData  | ||||
|     { | ||||
|         return this.magCounts; | ||||
|     } | ||||
| 
 | ||||
|     public getMagazineTemplate(): ITemplateItem  | ||||
|     { | ||||
|         return this.magazineTemplate; | ||||
|     } | ||||
| 
 | ||||
|     public getWeaponTemplate(): ITemplateItem  | ||||
|     { | ||||
|         return this.weaponTemplate; | ||||
|     } | ||||
| 
 | ||||
|     public getAmmoTemplate(): ITemplateItem  | ||||
|     { | ||||
|         return this.ammoTemplate; | ||||
|     } | ||||
| 
 | ||||
|     public getPmcInventory(): IInventory  | ||||
|     { | ||||
|         return this.pmcInventory; | ||||
|     } | ||||
| 
 | ||||
|     public getBotRole(): string  | ||||
|     { | ||||
|         return this.botRole; | ||||
|     } | ||||
| 
 | ||||
|     public getBotLevel(): number  | ||||
|     { | ||||
|         return this.botLevel; | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,116 @@ | |||
| import { ItemHelper } from "@spt/helpers/ItemHelper"; | ||||
| import { WeightedRandomHelper } from "@spt/helpers/WeightedRandomHelper"; | ||||
| import { IInventory } from "@spt/models/eft/common/tables/IBotBase"; | ||||
| import { IGenerationData } from "@spt/models/eft/common/tables/IBotType"; | ||||
| import { ITemplateItem } from "@spt/models/eft/common/tables/ITemplateItem"; | ||||
| import { ILogger } from "@spt/models/spt/utils/ILogger"; | ||||
| import { LocalisationService } from "@spt/services/LocalisationService"; | ||||
| import { inject, injectable } from "tsyringe"; | ||||
| 
 | ||||
| @injectable() | ||||
| export class APBSMethodHolder  | ||||
| { | ||||
|     constructor( | ||||
|         @inject("PrimaryLogger") protected logger: ILogger, | ||||
|         @inject("LocalisationService") protected localisationService: LocalisationService, | ||||
|         @inject("WeightedRandomHelper") protected weightedRandomHelper: WeightedRandomHelper, | ||||
|         @inject("ItemHelper") protected itemHelper: ItemHelper | ||||
|     )  | ||||
|     {} | ||||
| 
 | ||||
|     public getWeightedCompatibleAmmo( | ||||
|         cartridgePool: Record<string, Record<string, number>>, | ||||
|         weaponTemplate: ITemplateItem | ||||
|     ): string  | ||||
|     { | ||||
|         const desiredCaliber = this.getWeaponCaliber(weaponTemplate); | ||||
| 
 | ||||
|         const cartridgePoolForWeapon = cartridgePool[desiredCaliber]; | ||||
|         if (!cartridgePoolForWeapon || cartridgePoolForWeapon?.length === 0)  | ||||
|         { | ||||
|             this.logger.debug( | ||||
|                 this.localisationService.getText("bot-no_caliber_data_for_weapon_falling_back_to_default", { | ||||
|                     weaponId: weaponTemplate._id, | ||||
|                     weaponName: weaponTemplate._name, | ||||
|                     defaultAmmo: weaponTemplate._props.defAmmo | ||||
|                 }) | ||||
|             ); | ||||
| 
 | ||||
|             // Immediately returns, default ammo is guaranteed to be compatible
 | ||||
|             return weaponTemplate._props.defAmmo; | ||||
|         } | ||||
| 
 | ||||
|         // Get cartridges the weapons first chamber allow
 | ||||
|         const compatibleCartridgesInTemplate = this.getCompatibleCartridgesFromWeaponTemplate(weaponTemplate); | ||||
|         if (!compatibleCartridgesInTemplate)  | ||||
|         { | ||||
|             // No chamber data found in weapon, send default
 | ||||
|             return weaponTemplate._props.defAmmo; | ||||
|         } | ||||
| 
 | ||||
|         // Inner join the weapons allowed + passed in cartridge pool to get compatible cartridges
 | ||||
|         const compatibleCartridges = Object.keys(cartridgePoolForWeapon) | ||||
|             .filter((cartridge) => compatibleCartridgesInTemplate.includes(cartridge)) | ||||
|             .reduce((acc, key) => ({ ...acc, [key]: cartridgePoolForWeapon[key] }), {}); | ||||
| 
 | ||||
|         if (!compatibleCartridges)  | ||||
|         { | ||||
|             // No compatible cartridges, use default
 | ||||
|             return weaponTemplate._props.defAmmo; | ||||
|         } | ||||
| 
 | ||||
|         return this.weightedRandomHelper.getWeightedValue<string>(compatibleCartridges); | ||||
|     } | ||||
| 
 | ||||
|     public getWeaponCaliber(weaponTemplate: ITemplateItem): string  | ||||
|     { | ||||
|         if (weaponTemplate._props.Caliber)  | ||||
|         { | ||||
|             return weaponTemplate._props.Caliber; | ||||
|         } | ||||
| 
 | ||||
|         if (weaponTemplate._props.ammoCaliber)  | ||||
|         { | ||||
|             // 9x18pmm has a typo, should be Caliber9x18PM
 | ||||
|             return weaponTemplate._props.ammoCaliber === "Caliber9x18PMM" | ||||
|                 ? "Caliber9x18PM" | ||||
|                 : weaponTemplate._props.ammoCaliber; | ||||
|         } | ||||
| 
 | ||||
|         if (weaponTemplate._props.LinkedWeapon)  | ||||
|         { | ||||
|             const ammoInChamber = this.itemHelper.getItem( | ||||
|                 weaponTemplate._props.Chambers[0]._props.filters[0].Filter[0] | ||||
|             ); | ||||
|             if (!ammoInChamber[0])  | ||||
|             { | ||||
|                 return; | ||||
|             } | ||||
| 
 | ||||
|             return ammoInChamber[1]._props.Caliber; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     public getCompatibleCartridgesFromWeaponTemplate(weaponTemplate: ITemplateItem): string[]  | ||||
|     { | ||||
|         let cartridges = weaponTemplate._props.Chambers[0]?._props?.filters[0]?.Filter; | ||||
|         if (!cartridges)  | ||||
|         { | ||||
|             // Fallback to the magazine if possible, e.g. for revolvers
 | ||||
|             //  Grab the magazines template
 | ||||
|             const firstMagazine = weaponTemplate._props.Slots.find((slot) => slot._name === "mod_magazine"); | ||||
|             const magazineTemplate = this.itemHelper.getItem(firstMagazine._props.filters[0].Filter[0]); | ||||
| 
 | ||||
|             // Get the first slots array of cartridges
 | ||||
|             cartridges = magazineTemplate[1]._props.Slots[0]?._props.filters[0].Filter; | ||||
|             if (!cartridges)  | ||||
|             { | ||||
|                 // Normal magazines
 | ||||
|                 // None found, try the cartridges array
 | ||||
|                 cartridges = magazineTemplate[1]._props.Cartridges[0]?._props.filters[0].Filter; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         return cartridges; | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,68 @@ | |||
| import { IInventoryMagGen } from "@spt/generators/weapongen/IInventoryMagGen"; | ||||
| import { InventoryMagGen } from "@spt/generators/weapongen/InventoryMagGen"; | ||||
| import { BotWeaponGeneratorHelper } from "@spt/helpers/BotWeaponGeneratorHelper"; | ||||
| import { BaseClasses } from "@spt/models/enums/BaseClasses"; | ||||
| import { EquipmentSlots } from "@spt/models/enums/EquipmentSlots"; | ||||
| import { inject, injectable } from "tsyringe"; | ||||
| import { APBSIInventoryMagGen } from "./APBSIInventoryMagGen"; | ||||
| import { APBSInventoryMagGen } from "./APBSInventoryMagGen"; | ||||
| import { ModConfig } from "../Globals/ModConfig"; | ||||
| import { RandomUtil } from "@spt/utils/RandomUtil"; | ||||
| import { APBSEquipmentGetter } from "../Utils/APBSEquipmentGetter"; | ||||
| import { APBSTierGetter } from "../Utils/APBSTierGetter"; | ||||
| import { APBSMethodHolder } from "./APBSMethodHolder"; | ||||
| 
 | ||||
| @injectable() | ||||
| export class APBSUbglExternalMagGen implements APBSIInventoryMagGen  | ||||
| { | ||||
|     constructor( | ||||
|         @inject("BotWeaponGeneratorHelper") protected botWeaponGeneratorHelper: BotWeaponGeneratorHelper, | ||||
|         @inject("RandomUtil") protected randomUtil: RandomUtil, | ||||
|         @inject("APBSEquipmentGetter") protected apbsEquipmentGetter: APBSEquipmentGetter, | ||||
|         @inject("APBSTierGetter") protected apbsTierGetter: APBSTierGetter, | ||||
|         @inject("APBSMethodHolder") protected apbsMethodHolder: APBSMethodHolder | ||||
|     )  | ||||
|     {} | ||||
| 
 | ||||
|     public getPriority(): number  | ||||
|     { | ||||
|         return 1; | ||||
|     } | ||||
| 
 | ||||
|     public canHandleInventoryMagGen(inventoryMagGen: APBSInventoryMagGen): boolean  | ||||
|     { | ||||
|         return inventoryMagGen.getWeaponTemplate()._parent === BaseClasses.UBGL; | ||||
|     } | ||||
| 
 | ||||
|     public process(inventoryMagGen: APBSInventoryMagGen): void  | ||||
|     { | ||||
|         const bulletCount = this.botWeaponGeneratorHelper.getRandomizedBulletCount( | ||||
|             inventoryMagGen.getMagCount(), | ||||
|             inventoryMagGen.getMagazineTemplate() | ||||
|         ); | ||||
| 
 | ||||
|          | ||||
|         if (ModConfig.config.enableBotsToRollAmmoAgain && this.randomUtil.getChance100(ModConfig.config.chanceToRollAmmoAgain)) | ||||
|         { | ||||
|             const weapon = inventoryMagGen.getWeaponTemplate(); | ||||
|              | ||||
|             const tierInfo = this.apbsTierGetter.getTierByLevel(inventoryMagGen.getBotLevel()); | ||||
|             const ammoTable = this.apbsEquipmentGetter.getAmmoByBotRole(inventoryMagGen.getBotRole(), tierInfo) | ||||
| 
 | ||||
|             const rerolledAmmo = this.apbsMethodHolder.getWeightedCompatibleAmmo(ammoTable, weapon); | ||||
| 
 | ||||
|             this.botWeaponGeneratorHelper.addAmmoIntoEquipmentSlots( | ||||
|                 rerolledAmmo, | ||||
|                 bulletCount, | ||||
|                 inventoryMagGen.getPmcInventory() | ||||
|             ); | ||||
|         } | ||||
|          | ||||
|         this.botWeaponGeneratorHelper.addAmmoIntoEquipmentSlots( | ||||
|             inventoryMagGen.getAmmoTemplate()._id, | ||||
|             bulletCount, | ||||
|             inventoryMagGen.getPmcInventory(), | ||||
|             [EquipmentSlots.TACTICAL_VEST] | ||||
|         ); | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,416 @@ | |||
| import { inject, injectable } from "tsyringe"; | ||||
| import { DynamicRouterModService } from "@spt/services/mod/dynamicRouter/DynamicRouterModService"; | ||||
| import { WeatherGenerator } from "@spt/generators/WeatherGenerator"; | ||||
| import { ItemHelper } from "@spt/helpers/ItemHelper"; | ||||
| import { ProfileHelper } from "@spt/helpers/ProfileHelper"; | ||||
| 
 | ||||
| import { APBSLogger } from "../Utils/APBSLogger"; | ||||
| import { Logging } from "../Enums/Logging"; | ||||
| import { RaidInformation } from "../Globals/RaidInformation"; | ||||
| 
 | ||||
| @injectable() | ||||
| export class APBSDynamicRouterHooks | ||||
| { | ||||
|     private grenadeList = [ | ||||
|         "5710c24ad2720bc3458b45a3",  | ||||
|         "58d3db5386f77426186285a0",  | ||||
|         "618a431df1eb8e24b8741deb",  | ||||
|         "5448be9a4bdc2dfd2f8b456a",  | ||||
|         "5e32f56fcb6d5863cc5e5ee4",  | ||||
|         "5e340dcdcb6d5863cc5e5efb",  | ||||
|         "617fd91e5539a84ec44ce155" | ||||
|     ] | ||||
|     constructor( | ||||
|         @inject("DynamicRouterModService") protected dynamicRouterModService: DynamicRouterModService, | ||||
|         @inject("ItemHelper") protected itemHelper: ItemHelper, | ||||
|         @inject("APBSLogger") protected apbsLogger: APBSLogger, | ||||
|         @inject("WeatherGenerator") protected weatherGenerator: WeatherGenerator, | ||||
|         @inject("RaidInformation") protected raidInformation: RaidInformation, | ||||
|         @inject("ProfileHelper") protected profileHelper: ProfileHelper | ||||
|     ) | ||||
|     {} | ||||
| 
 | ||||
|     public registerQBRouterHooks(): void | ||||
|     { | ||||
|         this.dynamicRouterModService.registerDynamicRouter( | ||||
|             "APBS-QBBotGenerationRouter", | ||||
|             [ | ||||
|                 { | ||||
|                     url: "/QuestingBots/GenerateBot/", | ||||
|                     action: async (url, info, sessionId, output) =>  | ||||
|                     { | ||||
|                         try  | ||||
|                         { | ||||
|                             const outputJSON = JSON.parse(output); | ||||
|                             if (outputJSON.data?.length) | ||||
|                             { | ||||
|                                 this.logBotGeneration(outputJSON); | ||||
|                             } | ||||
|                         } | ||||
|                         catch (err)  | ||||
|                         { | ||||
|                             this.apbsLogger.log(Logging.WARN, "Bot Router hook failed.\n", `${err.stack}`); | ||||
|                         } | ||||
|                         return output; | ||||
|                     } | ||||
|                 } | ||||
|             ], | ||||
|             "APBS" | ||||
|         ); | ||||
|         this.apbsLogger.log(Logging.DEBUG, "QB Compatibility Router registered"); | ||||
|     } | ||||
| 
 | ||||
|     private logBotGeneration(outputJSON: any):void | ||||
|     { | ||||
|         const start = performance.now() | ||||
| 
 | ||||
|         const botDetails = this.getBotDetails(outputJSON); | ||||
|         const logMessages = this.getLogMessage(botDetails); | ||||
| 
 | ||||
|         try  | ||||
|         { | ||||
|             switch (outputJSON.data[0].Info.Settings.Role)  | ||||
|             { | ||||
|                 case "pmcBEAR": | ||||
|                 case "pmcUSEC": | ||||
|                     this.apbsLogger.log(  | ||||
|                         Logging.PMC, | ||||
|                         "---------------------------------------------------QB Bot spawned from cache---------------------------------------------------", | ||||
|                         `| ${logMessages[0]}`, | ||||
|                         `| ${logMessages[1]}`, | ||||
|                         `| ${logMessages[2]} ${logMessages[3]}` | ||||
|                     ); | ||||
|                     break; | ||||
|                 case "cursedassault": | ||||
|                 case "marksman": | ||||
|                 case "assault": | ||||
|                     this.apbsLogger.log( | ||||
|                         Logging.SCAV, | ||||
|                         "---------------------------------------------------QB Bot spawned from cache---------------------------------------------------", | ||||
|                         `| ${logMessages[0]}`, | ||||
|                         `| ${logMessages[1]}`, | ||||
|                         `| ${logMessages[2]} ${logMessages[3]}` | ||||
|                     ); | ||||
|                     break; | ||||
|                 case "arenaFighterEvent": | ||||
|                 case "exUsec": | ||||
|                     this.apbsLogger.log( | ||||
|                         Logging.RAIDER, | ||||
|                         "---------------------------------------------------QB Bot spawned from cache---------------------------------------------------", | ||||
|                         `| ${logMessages[0]}`, | ||||
|                         `| ${logMessages[1]}`, | ||||
|                         `| ${logMessages[2]} ${logMessages[3]}` | ||||
|                     ); | ||||
|                     break; | ||||
|                 case "bossBully": | ||||
|                 case "bossTagilla": | ||||
|                 case "bossPartisan": | ||||
|                 case "bossGluhar": | ||||
|                 case "bossKilla": | ||||
|                 case "bossKojaniy": | ||||
|                 case "bossSanitar": | ||||
|                 case "bossKnight": | ||||
|                 case "bossZryachiy": | ||||
|                 case "bossTest": | ||||
|                 case "bossKolontay": | ||||
|                 case "bossBoar": | ||||
|                 case "bossBoarSniper": | ||||
|                 case "bosslegion": | ||||
|                 case "bosspunisher": | ||||
|                 case "followerBully": | ||||
|                 case "followerGluharAssault": | ||||
|                 case "followerGluharScout": | ||||
|                 case "followerGluharSecurity": | ||||
|                 case "followerGluharSnipe": | ||||
|                 case "followerKojaniy": | ||||
|                 case "followerSanitar": | ||||
|                 case "followerTagilla": | ||||
|                 case "followerBirdEye": | ||||
|                 case "followerBigPipe": | ||||
|                 case "followerZryachiy": | ||||
|                 case "followerTest": | ||||
|                 case "followerBoar": | ||||
|                 case "sectantPriest": | ||||
|                 case "sectantWarrior": | ||||
|                 case "followerBoarClose1": | ||||
|                 case "followerBoarClose2": | ||||
|                 case "followerKolontayAssault": | ||||
|                 case "followerKolontaySecurity": | ||||
|                     this.apbsLogger.log(  | ||||
|                         Logging.BOSS, | ||||
|                         "---------------------------------------------------QB Bot spawned from cache---------------------------------------------------", | ||||
|                         `| ${logMessages[0]}`, | ||||
|                         `| ${logMessages[1]}`, | ||||
|                         `| ${logMessages[2]} ${logMessages[3]}` | ||||
|                     ); | ||||
|                     break; | ||||
|                 case "shooterBTR": | ||||
|                 case "skier": | ||||
|                 case "peacemaker": | ||||
|                 case "gifter": | ||||
|                 case "infectedAssault": | ||||
|                 case "infectedCivil": | ||||
|                 case "infectedLaborant": | ||||
|                 case "infectedPmc": | ||||
|                 case "infectedTagilla": | ||||
|                     this.apbsLogger.log(  | ||||
|                         Logging.EVENT, | ||||
|                         "---------------------------------------------------QB Bot spawned from cache---------------------------------------------------", | ||||
|                         `| ${logMessages[0]}`, | ||||
|                         `| ${logMessages[1]}`, | ||||
|                         `| ${logMessages[2]} ${logMessages[3]}` | ||||
|                     ); | ||||
|                     break; | ||||
|                 default: | ||||
|                     this.apbsLogger.log( | ||||
|                         Logging.DEBUG, | ||||
|                         "---------------------------------------------------QB Bot spawned from cache---------------------------------------------------", | ||||
|                         `| ${logMessages[0]}`, | ||||
|                         `| ${logMessages[1]}`, | ||||
|                         `| ${logMessages[2]} ${logMessages[3]}` | ||||
|                     ); | ||||
|                     break; | ||||
|             } | ||||
|         } | ||||
|         catch (err)  | ||||
|         { | ||||
|             this.apbsLogger.log(Logging.ERR, "QB Bot Generation LogOutput failed.", `${err.stack}`); | ||||
|         } | ||||
|         const timeTaken = performance.now() - start; | ||||
|         this.apbsLogger.log(Logging.DEBUG, `${timeTaken.toFixed(2)}ms for logging QB bot ${botDetails.role} | Name: ${botDetails.name}`); | ||||
|     } | ||||
| 
 | ||||
|     private getBotDetails (detailsJSON: any): any | ||||
|     { | ||||
|         let primaryID; | ||||
|         let primaryCaliberID; | ||||
|         let secondaryID; | ||||
|         let secondaryCaliberID; | ||||
|         let holsterID; | ||||
|         let holsterCaliberID; | ||||
|         let helmetID; | ||||
|         let nvgID; | ||||
|         let earProID; | ||||
|         let armourVestID; | ||||
|         let frontPlateID; | ||||
|         let backPlateID; | ||||
|         let lSidePlateID; | ||||
|         let rSidePlateID; | ||||
|         let scabbardID; | ||||
| 
 | ||||
|         let canHavePlates = false; | ||||
| 
 | ||||
|         const botDetails = detailsJSON.data[0].Inventory.items; | ||||
| 
 | ||||
|         let grenadeCount = 0; | ||||
|         for (const item in botDetails)  | ||||
|         { | ||||
|             if (this.grenadeList.includes(botDetails[item]._tpl)) grenadeCount++;             | ||||
|         } | ||||
| 
 | ||||
|         const primaryWeapon = botDetails.find(e => e.slotId === "FirstPrimaryWeapon"); | ||||
|         if (typeof primaryWeapon !== "undefined")  | ||||
|         { | ||||
|             primaryID = this.itemHelper.getItemName(primaryWeapon._tpl); | ||||
|             const primaryCaliber = botDetails.find(e => e.slotId === "patron_in_weapon" && e.parentId == primaryWeapon._id); | ||||
|             if (typeof primaryCaliber !== "undefined")  | ||||
|             { | ||||
|                 primaryCaliberID = this.itemHelper.getItemName(primaryCaliber._tpl); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         const secondaryWeapon = botDetails.find(e => e.slotId === "SecondPrimaryWeapon"); | ||||
|         if (typeof secondaryWeapon !== "undefined")  | ||||
|         { | ||||
|             secondaryID = this.itemHelper.getItemName(secondaryWeapon._tpl); | ||||
|             const secondaryCaliber = botDetails.find(e => e.slotId === "patron_in_weapon" && e.parentId == secondaryWeapon._id); | ||||
|             if (typeof secondaryCaliber !== "undefined")  | ||||
|             { | ||||
|                 secondaryCaliberID = this.itemHelper.getItemName(secondaryCaliber._tpl); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         const holster = botDetails.find(e => e.slotId === "Holster"); | ||||
|         if (typeof holster !== "undefined")  | ||||
|         { | ||||
|             holsterID = this.itemHelper.getItemName(holster._tpl); | ||||
|             const holsterCaliber = botDetails.find(e => e.slotId === "patron_in_weapon" && e.parentId == holster._id); | ||||
|             if (typeof holsterCaliber !== "undefined")  | ||||
|             { | ||||
|                 holsterCaliberID = this.itemHelper.getItemName(holsterCaliber._tpl); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         const helmet = botDetails.find(e => e.slotId === "Headwear"); | ||||
|         if (typeof helmet !== "undefined")  | ||||
|         { | ||||
|             helmetID = this.itemHelper.getItemName(helmet._tpl); | ||||
|         } | ||||
| 
 | ||||
|         const nvg = botDetails.find(e => e.slotId === "mod_nvg" && "upd" in e); | ||||
|         if (typeof nvg !== "undefined")  | ||||
|         { | ||||
|             nvgID = this.itemHelper.getItemName(nvg._tpl); | ||||
|         } | ||||
| 
 | ||||
|         const earPro = botDetails.find(e => e.slotId === "Earpiece"); | ||||
|         if (typeof earPro !== "undefined")  | ||||
|         { | ||||
|             earProID = this.itemHelper.getItemName(earPro._tpl); | ||||
|         } | ||||
| 
 | ||||
|         const scabbard = botDetails.find(e => e.slotId === "Scabbard"); | ||||
|         if (typeof scabbard !== "undefined")  | ||||
|         { | ||||
|             scabbardID = this.itemHelper.getItemName(scabbard._tpl); | ||||
|         } | ||||
| 
 | ||||
|         const armourVest = botDetails.find(e => e.slotId === "ArmorVest") ?? botDetails.find(e => e.slotId === "TacticalVest"); | ||||
|         if (typeof armourVest !== "undefined")  | ||||
|         { | ||||
|             armourVestID = this.itemHelper.getItem(armourVest._tpl); | ||||
|             if (armourVestID[1]._props.Slots[0]) | ||||
|             { | ||||
|                 canHavePlates = true; | ||||
|                 const frontPlate = botDetails.find(e => e.slotId === "Front_plate" && e.parentId == armourVest._id); | ||||
|                 const backPlate = botDetails.find(e => e.slotId === "Back_plate" && e.parentId == armourVest._id); | ||||
|                 const lSidePlate = botDetails.find(e => e.slotId === "Left_side_plate" && e.parentId == armourVest._id); | ||||
|                 const rSidePlate = botDetails.find(e => e.slotId === "Right_side_plate" && e.parentId == armourVest._id); | ||||
|                 if (typeof frontPlate !== "undefined") | ||||
|                 { | ||||
|                     frontPlateID = this.itemHelper.getItem(frontPlate._tpl) | ||||
|                     frontPlateID = frontPlateID[1]._props.armorClass; | ||||
|                 } | ||||
|                 if (typeof backPlate !== "undefined") | ||||
|                 { | ||||
|                     backPlateID = this.itemHelper.getItem(backPlate._tpl) | ||||
|                     backPlateID = backPlateID[1]._props.armorClass; | ||||
|                 } | ||||
|                 if (typeof lSidePlate !== "undefined") | ||||
|                 { | ||||
|                     lSidePlateID = this.itemHelper.getItem(lSidePlate._tpl) | ||||
|                     lSidePlateID = lSidePlateID[1]._props.armorClass; | ||||
|                 } | ||||
|                 if (typeof rSidePlate !== "undefined") | ||||
|                 { | ||||
|                     rSidePlateID = this.itemHelper.getItem(rSidePlate._tpl) | ||||
|                     rSidePlateID = rSidePlateID[1]._props.armorClass; | ||||
|                 } | ||||
|             } | ||||
|             armourVestID = this.itemHelper.getItemName(armourVest._tpl); | ||||
|         } | ||||
| 
 | ||||
|         return { | ||||
|             tier: detailsJSON.data[0].Info.Tier, | ||||
|             name: detailsJSON.data[0].Info.Nickname,  | ||||
|             level: detailsJSON.data[0].Info.Level,  | ||||
|             gameVersion: detailsJSON.data[0].Info.GameVersion,  | ||||
|             role: detailsJSON.data[0].Info.Settings.Role,  | ||||
|             side: detailsJSON.data[0].Info.Side, | ||||
|             difficulty: detailsJSON.data[0].Info.Settings.BotDifficulty, | ||||
|             primaryID, | ||||
|             primaryCaliberID, | ||||
|             secondaryID, | ||||
|             secondaryCaliberID, | ||||
|             holsterID, | ||||
|             holsterCaliberID, | ||||
|             helmetID, | ||||
|             nvgID, | ||||
|             earProID, | ||||
|             canHavePlates, | ||||
|             armourVestID, | ||||
|             frontPlateID, | ||||
|             backPlateID, | ||||
|             lSidePlateID, | ||||
|             rSidePlateID, | ||||
|             scabbardID, | ||||
|             grenadeCount | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private getLogMessage(botDetails: any): any | ||||
|     { | ||||
|         const removeNoneValues = value => | ||||
|             !["None"].some(element => value.includes(element)); | ||||
| 
 | ||||
|         const removeNonArmouredRigs = value => | ||||
|             !["Armour/Rig:"].some(element => value.includes(element)); | ||||
| 
 | ||||
|         let realMessage1; | ||||
|         let realMessage2; | ||||
|         let realMessage3; | ||||
|         let realMessage4; | ||||
| 
 | ||||
|         let temporaryMessage1: string[] = [ | ||||
|             `Tier: ${botDetails.tier}`, | ||||
|             `Role: ${botDetails.role}`, | ||||
|             `Nickname: ${botDetails.name}`, | ||||
|             `Level: ${botDetails.level}`, | ||||
|             `Difficulty: ${botDetails.difficulty}`, | ||||
|             `GameVersion: ${botDetails.gameVersion ?? "None" }`, | ||||
|             `Grenades: ${botDetails.grenadeCount >= 1 ? botDetails.grenadeCount : "None" }` | ||||
|         ]; | ||||
|         let temporaryMessage2: string[] = [ | ||||
|             `Primary: ${botDetails.primaryID ?? "None" }`, | ||||
|             `Primary Caliber: ${botDetails.primaryCaliberID ?? "None" }`, | ||||
|             `Secondary: ${botDetails.secondaryID ?? "None" }`, | ||||
|             `Secondary Caliber: ${botDetails.secondaryCaliberID ?? "None" }`, | ||||
|             `Holster: ${botDetails.holsterID ?? "None" }`, | ||||
|             `Holster Caliber: ${botDetails.holsterCaliberID ?? "None" }`, | ||||
|             `Melee: ${botDetails.scabbardID ?? "None" }` | ||||
|         ]; | ||||
|         let temporaryMessage3: string[] = [ | ||||
|             `Helmet: ${botDetails.helmetID ?? "None" }`, | ||||
|             `NVG: ${botDetails.nvgID ?? "None" }`, | ||||
|             `Ears: ${botDetails.earProID ?? "None" }`, | ||||
|             `Armour/Rig: ${botDetails.armourVestID ?? "None" }` | ||||
|         ]; | ||||
|         let temporaryMessage4: string[] = [ | ||||
|             "| Plates:", | ||||
|             `Front [${botDetails.frontPlateID ?? "None" }]`, | ||||
|             `Back [${botDetails.backPlateID ?? "None" }]`, | ||||
|             `Left [${botDetails.lSidePlateID ?? "None" }]`, | ||||
|             `Right [${botDetails.rSidePlateID ?? "None" }]` | ||||
|         ] | ||||
|          | ||||
|         temporaryMessage1 = temporaryMessage1.filter(removeNoneValues) | ||||
|         if (temporaryMessage1?.length)  | ||||
|         { | ||||
|             realMessage1 = temporaryMessage1.filter(Boolean).join(" | "); | ||||
|         } | ||||
|         realMessage1 = realMessage1 ?? "No Bot Details"; | ||||
| 
 | ||||
|         temporaryMessage2 = temporaryMessage2.filter(removeNoneValues) | ||||
|         if (temporaryMessage2?.length)  | ||||
|         { | ||||
|             realMessage2 = temporaryMessage2.filter(Boolean).join(" | "); | ||||
|         } | ||||
|         realMessage2 = realMessage2 ?? "No Weapon Details"; | ||||
| 
 | ||||
|         if (!botDetails.canHavePlates) | ||||
|         { | ||||
|             temporaryMessage3 = temporaryMessage3.filter(removeNonArmouredRigs) | ||||
|         } | ||||
|         temporaryMessage3 = temporaryMessage3.filter(removeNoneValues) | ||||
|         if (temporaryMessage3?.length)  | ||||
|         { | ||||
|              | ||||
|             realMessage3 = temporaryMessage3.filter(Boolean).join(" | "); | ||||
|         } | ||||
|         realMessage3 = realMessage3 ?? "No Gear Details"; | ||||
| 
 | ||||
|         temporaryMessage4 = temporaryMessage4.filter(removeNoneValues) | ||||
|         if (temporaryMessage4?.length > 1)  | ||||
|         { | ||||
|             realMessage4 = temporaryMessage4.filter(Boolean).join(" "); | ||||
|         } | ||||
|         realMessage4 = realMessage4 ?? " "; | ||||
| 
 | ||||
|         return [ | ||||
|             realMessage1, | ||||
|             realMessage2, | ||||
|             realMessage3, | ||||
|             realMessage4 | ||||
|         ] | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,552 @@ | |||
| import { inject, injectable } from "tsyringe"; | ||||
| import { StaticRouterModService } from "@spt/services/mod/staticRouter/StaticRouterModService"; | ||||
| import { WeatherGenerator } from "@spt/generators/WeatherGenerator"; | ||||
| import { ItemHelper } from "@spt/helpers/ItemHelper"; | ||||
| import { ProfileHelper } from "@spt/helpers/ProfileHelper"; | ||||
| 
 | ||||
| import { APBSLogger } from "../Utils/APBSLogger"; | ||||
| import { Logging } from "../Enums/Logging"; | ||||
| import { RaidInformation } from "../Globals/RaidInformation"; | ||||
| import { ModInformation } from "../Globals/ModInformation"; | ||||
| import { APBSTester } from "../Utils/APBSTester"; | ||||
| import { DatabaseService } from "@spt/services/DatabaseService"; | ||||
| 
 | ||||
| @injectable() | ||||
| export class APBSStaticRouterHooks | ||||
| { | ||||
|     private grenadeList = [ | ||||
|         "5710c24ad2720bc3458b45a3",  | ||||
|         "58d3db5386f77426186285a0",  | ||||
|         "618a431df1eb8e24b8741deb",  | ||||
|         "5448be9a4bdc2dfd2f8b456a",  | ||||
|         "5e32f56fcb6d5863cc5e5ee4",  | ||||
|         "5e340dcdcb6d5863cc5e5efb",  | ||||
|         "617fd91e5539a84ec44ce155" | ||||
|     ] | ||||
| 
 | ||||
|     constructor( | ||||
|         @inject("StaticRouterModService") protected staticRouterService: StaticRouterModService, | ||||
|         @inject("ItemHelper") protected itemHelper: ItemHelper, | ||||
|         @inject("APBSLogger") protected apbsLogger: APBSLogger, | ||||
|         @inject("WeatherGenerator") protected weatherGenerator: WeatherGenerator, | ||||
|         @inject("RaidInformation") protected raidInformation: RaidInformation, | ||||
|         @inject("ModInformation") protected modInformation: ModInformation, | ||||
|         @inject("DatabaseService") protected databaseService: DatabaseService, | ||||
|         @inject("APBSTester") protected apbsTester: APBSTester, | ||||
|         @inject("ProfileHelper") protected profileHelper: ProfileHelper | ||||
|     ) | ||||
|     {} | ||||
| 
 | ||||
|     public registerRouterHooks(): void | ||||
|     { | ||||
|         this.staticRouterService.registerStaticRouter( | ||||
|             "APBS-BotGenerationRouter", | ||||
|             [ | ||||
|                 { | ||||
|                     url: "/client/game/bot/generate", | ||||
|                     action: async (url, info, sessionId, output) =>  | ||||
|                     { | ||||
|                         try  | ||||
|                         { | ||||
|                             const outputJSON = JSON.parse(output); | ||||
|                             if (outputJSON.data?.length) | ||||
|                             { | ||||
|                                 this.logBotGeneration(outputJSON); | ||||
|                             } | ||||
|                         } | ||||
|                         catch (err)  | ||||
|                         { | ||||
|                             this.apbsLogger.log(Logging.WARN, "Bot Router hook failed.\n", `${err.stack}`); | ||||
|                         } | ||||
|                         return output; | ||||
|                     } | ||||
|                 } | ||||
|             ], | ||||
|             "APBS" | ||||
|         ); | ||||
|         this.apbsLogger.log(Logging.DEBUG, "Bot Generation Router registered"); | ||||
|         this.staticRouterService.registerStaticRouter( | ||||
|             "APBS-StartMatchRouter", | ||||
|             [ | ||||
|                 { | ||||
|                     url: "/client/match/local/start", | ||||
|                     action: async (url, info, sessionId, output) =>  | ||||
|                     { | ||||
|                         this.raidInformation.sessionId = sessionId; | ||||
|                         try  | ||||
|                         { | ||||
|                             this.logLocation(info); | ||||
|                             if (this.modInformation.testMode && this.modInformation.clearAssortPreRaid) | ||||
|                             { | ||||
|                                 const tables = this.databaseService.getTables(); | ||||
|                                 this.apbsTester.clearAssort(tables.traders[this.modInformation.testTrader]); | ||||
|                             } | ||||
|                         } | ||||
|                         catch (err)  | ||||
|                         { | ||||
|                             this.apbsLogger.log(Logging.WARN, "Match Start Router hook failed.\n", `${err.stack}`); | ||||
|                         } | ||||
|                         return output; | ||||
|                     } | ||||
|                 } | ||||
|             ], | ||||
|             "APBS" | ||||
|         ); | ||||
|         this.apbsLogger.log(Logging.DEBUG, "Match Start Router registered"); | ||||
|         this.staticRouterService.registerStaticRouter( | ||||
|             "APBS-GameStartRouter", | ||||
|             [ | ||||
|                 { | ||||
|                     url: "/client/game/start", | ||||
|                     action: async (url, info, sessionId, output) =>  | ||||
|                     { | ||||
|                         try  | ||||
|                         { | ||||
|                             const fullProfile = this.profileHelper.getFullProfile(sessionId); | ||||
|                             this.raidInformation.freshProfile = (fullProfile.info.wipe === true) ? true : false; | ||||
|                         } | ||||
|                         catch (err)  | ||||
|                         { | ||||
|                             this.apbsLogger.log(Logging.WARN, "Game Start Router hook failed.\n", `${err.stack}`); | ||||
|                         } | ||||
|                         return output; | ||||
|                     } | ||||
|                 } | ||||
|             ], | ||||
|             "APBS" | ||||
|         ); | ||||
|         this.apbsLogger.log(Logging.DEBUG, "Game Start Router registered"); | ||||
|         this.staticRouterService.registerStaticRouter( | ||||
|             "APBS-ProfileStatusChecker", | ||||
|             [ | ||||
|                 { | ||||
|                     url: "/client/profile/status", | ||||
|                     action: async (url, info, sessionId, output) =>  | ||||
|                     { | ||||
|                         try  | ||||
|                         { | ||||
|                             const fullProfile = this.profileHelper.getFullProfile(sessionId); | ||||
|                             this.raidInformation.freshProfile = (fullProfile.info.wipe === true) ? true : false; | ||||
|                         } | ||||
|                         catch (err)  | ||||
|                         { | ||||
|                             this.apbsLogger.log(Logging.WARN, "Profile Status Router hook failed.\n", `${err.stack}`); | ||||
|                         } | ||||
|                         return output; | ||||
|                     } | ||||
|                 } | ||||
|             ], | ||||
|             "APBS" | ||||
|         ); | ||||
|         this.apbsLogger.log(Logging.DEBUG, "Profile Status Router registered"); | ||||
|     } | ||||
|      | ||||
|     private logLocation(info: any):void | ||||
|     { | ||||
|         this.raidInformation.location = info.location; | ||||
|         const gameTime = this.weatherGenerator.calculateGameTime({ acceleration: 0, time: "", date: "", weather: undefined, season: 1 }).time; | ||||
| 
 | ||||
|         if (info.timeVariant === "PAST") this.raidInformation.currentTime = this.parseTime(gameTime, 12, info.location) | ||||
|         if (info.timeVariant === "CURR") this.raidInformation.currentTime = this.parseTime(gameTime, 0, info.location) | ||||
|         this.raidInformation.nightTime = this.isNight(this.raidInformation.currentTime); | ||||
| 
 | ||||
|         this.apbsLogger.log(Logging.WARN, "---Raid Information---"); | ||||
|         this.apbsLogger.log(Logging.WARN, `Location: ${this.raidInformation.location}`); | ||||
|         this.apbsLogger.log(Logging.WARN, `Time: ${this.raidInformation.currentTime}`); | ||||
|         this.apbsLogger.log(Logging.WARN, `Night: ${this.raidInformation.nightTime}`); | ||||
|     } | ||||
| 
 | ||||
|     private parseTime(time, hourDiff, location)  | ||||
|     { | ||||
|         if (location == "factory4_night") | ||||
|         { | ||||
|             return "03:28" | ||||
|         } | ||||
|         else if (location == "factory4_day" || location == "laboratory") | ||||
|         { | ||||
|             return "15:28" | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             const [hours, minutes] = time.split(":"); | ||||
|             if (hourDiff == 12 && parseInt(hours) >= 12) | ||||
|             { | ||||
|                 return `${Math.abs(parseInt(hours) - hourDiff)}:${minutes}` | ||||
|             } | ||||
|             if (hourDiff == 12 && parseInt(hours) < 12) | ||||
|             { | ||||
|                 return `${Math.abs(parseInt(hours) + hourDiff)}:${minutes}` | ||||
|             } | ||||
|             return `${hours}:${minutes}` | ||||
|         } | ||||
|     } | ||||
|      | ||||
|     private isNight(time)  | ||||
|     { | ||||
|         const [hours, minutes] = time.split(":"); | ||||
|         if (parseInt(hours) >= 5 && parseInt(hours) < 20) | ||||
|         { | ||||
|             return false; | ||||
|         } | ||||
|         else  | ||||
|         { | ||||
|             return true; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private logBotGeneration(outputJSON: any): void | ||||
|     { | ||||
|         const start = performance.now() | ||||
| 
 | ||||
|         const botDetails = this.getBotDetails(outputJSON); | ||||
|         const logMessages = this.getLogMessage(botDetails); | ||||
| 
 | ||||
|         try  | ||||
|         { | ||||
|             switch (outputJSON.data[0].Info.Settings.Role)  | ||||
|             { | ||||
|                 case "pmcBEAR": | ||||
|                 case "pmcUSEC": | ||||
|                     this.apbsLogger.log(  | ||||
|                         Logging.PMC, | ||||
|                         "-----------------------------------------------------Bot spawned from cache-----------------------------------------------------", | ||||
|                         `| ${logMessages[0]}`, | ||||
|                         `| ${logMessages[1]}`, | ||||
|                         `| ${logMessages[2]} ${logMessages[3]}` | ||||
|                     ); | ||||
|                     break; | ||||
|                 case "cursedassault": | ||||
|                 case "marksman": | ||||
|                 case "assault": | ||||
|                     this.apbsLogger.log( | ||||
|                         Logging.SCAV, | ||||
|                         "-----------------------------------------------------Bot spawned from cache-----------------------------------------------------", | ||||
|                         `| ${logMessages[0]}`, | ||||
|                         `| ${logMessages[1]}`, | ||||
|                         `| ${logMessages[2]} ${logMessages[3]}` | ||||
|                     ); | ||||
|                     break; | ||||
|                 case "arenaFighterEvent": | ||||
|                 case "arenaFighter": | ||||
|                 case "exUsec": | ||||
|                 case "pmcbot": | ||||
|                     this.apbsLogger.log( | ||||
|                         Logging.RAIDER, | ||||
|                         "-----------------------------------------------------Bot spawned from cache-----------------------------------------------------", | ||||
|                         `| ${logMessages[0]}`, | ||||
|                         `| ${logMessages[1]}`, | ||||
|                         `| ${logMessages[2]} ${logMessages[3]}` | ||||
|                     ); | ||||
|                     break; | ||||
|                 case "bossBully": | ||||
|                 case "bossTagilla": | ||||
|                 case "bossPartisan": | ||||
|                 case "bossGluhar": | ||||
|                 case "bossKilla": | ||||
|                 case "bossKojaniy": | ||||
|                 case "bossSanitar": | ||||
|                 case "bossKnight": | ||||
|                 case "bossZryachiy": | ||||
|                 case "bossTest": | ||||
|                 case "bossKolontay": | ||||
|                 case "bossBoar": | ||||
|                 case "bossBoarSniper": | ||||
|                 case "bosslegion": | ||||
|                 case "bosspunisher": | ||||
|                 case "followerBully": | ||||
|                 case "followerGluharAssault": | ||||
|                 case "followerGluharScout": | ||||
|                 case "followerGluharSecurity": | ||||
|                 case "followerGluharSnipe": | ||||
|                 case "followerKojaniy": | ||||
|                 case "followerSanitar": | ||||
|                 case "followerTagilla": | ||||
|                 case "followerBirdEye": | ||||
|                 case "followerBigPipe": | ||||
|                 case "followerZryachiy": | ||||
|                 case "followerTest": | ||||
|                 case "followerBoar": | ||||
|                 case "sectantPriest": | ||||
|                 case "sectantWarrior": | ||||
|                 case "followerBoarClose1": | ||||
|                 case "followerBoarClose2": | ||||
|                 case "followerKolontayAssault": | ||||
|                 case "followerKolontaySecurity": | ||||
|                     this.apbsLogger.log(  | ||||
|                         Logging.BOSS, | ||||
|                         "-----------------------------------------------------Bot spawned from cache-----------------------------------------------------", | ||||
|                         `| ${logMessages[0]}`, | ||||
|                         `| ${logMessages[1]}`, | ||||
|                         `| ${logMessages[2]} ${logMessages[3]}` | ||||
|                     ); | ||||
|                     break; | ||||
|                 case "shooterBTR": | ||||
|                 case "skier": | ||||
|                 case "peacemaker": | ||||
|                 case "gifter": | ||||
|                 case "infectedAssault": | ||||
|                 case "infectedCivil": | ||||
|                 case "infectedLaborant": | ||||
|                 case "infectedPmc": | ||||
|                 case "infectedTagilla": | ||||
|                     this.apbsLogger.log(  | ||||
|                         Logging.EVENT, | ||||
|                         "-----------------------------------------------------Bot spawned from cache-----------------------------------------------------", | ||||
|                         `| ${logMessages[0]}`, | ||||
|                         `| ${logMessages[1]}`, | ||||
|                         `| ${logMessages[2]} ${logMessages[3]}` | ||||
|                     ); | ||||
|                     break; | ||||
|                 default: | ||||
|                     this.apbsLogger.log( | ||||
|                         Logging.DEBUG, | ||||
|                         "-----------------------------------------------------Bot spawned from cache-----------------------------------------------------", | ||||
|                         `| ${logMessages[0]}`, | ||||
|                         `| ${logMessages[1]}`, | ||||
|                         `| ${logMessages[2]} ${logMessages[3]}` | ||||
|                     ); | ||||
|                     break; | ||||
|             } | ||||
|         } | ||||
|         catch (err)  | ||||
|         { | ||||
|             this.apbsLogger.log(Logging.ERR, "Bot Generation LogOutput failed.", `${err.stack}`); | ||||
|         } | ||||
|         const timeTaken = performance.now() - start; | ||||
|         this.apbsLogger.log(Logging.DEBUG, `${timeTaken.toFixed(2)}ms for logging bot ${botDetails.role} | Name: ${botDetails.name}`); | ||||
|     } | ||||
| 
 | ||||
|     private getBotDetails (detailsJSON: any): any | ||||
|     { | ||||
|         let primaryID; | ||||
|         let primaryCaliberID; | ||||
|         let secondaryID; | ||||
|         let secondaryCaliberID; | ||||
|         let holsterID; | ||||
|         let holsterCaliberID; | ||||
|         let helmetID; | ||||
|         let nvgID; | ||||
|         let earProID; | ||||
|         let armourVestID; | ||||
|         let frontPlateID; | ||||
|         let backPlateID; | ||||
|         let lSidePlateID; | ||||
|         let rSidePlateID; | ||||
|         let scabbardID; | ||||
| 
 | ||||
|         let canHavePlates = false; | ||||
| 
 | ||||
|         const botDetails = detailsJSON.data[0].Inventory.items; | ||||
| 
 | ||||
|         let grenadeCount = 0; | ||||
|         for (const item in botDetails)  | ||||
|         { | ||||
|             if (this.grenadeList.includes(botDetails[item]._tpl)) grenadeCount++; | ||||
|         } | ||||
| 
 | ||||
|         const primaryWeapon = botDetails.find(e => e.slotId === "FirstPrimaryWeapon"); | ||||
|         if (typeof primaryWeapon !== "undefined")  | ||||
|         { | ||||
|             primaryID = this.itemHelper.getItemName(primaryWeapon._tpl); | ||||
|             const primaryCaliber = botDetails.find(e => e.slotId === "patron_in_weapon" && e.parentId == primaryWeapon._id); | ||||
|             if (typeof primaryCaliber !== "undefined")  | ||||
|             { | ||||
|                 primaryCaliberID = this.itemHelper.getItemName(primaryCaliber._tpl); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         const secondaryWeapon = botDetails.find(e => e.slotId === "SecondPrimaryWeapon"); | ||||
|         if (typeof secondaryWeapon !== "undefined")  | ||||
|         { | ||||
|             secondaryID = this.itemHelper.getItemName(secondaryWeapon._tpl); | ||||
|             const secondaryCaliber = botDetails.find(e => e.slotId === "patron_in_weapon" && e.parentId == secondaryWeapon._id); | ||||
|             if (typeof secondaryCaliber !== "undefined")  | ||||
|             { | ||||
|                 secondaryCaliberID = this.itemHelper.getItemName(secondaryCaliber._tpl); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         const holster = botDetails.find(e => e.slotId === "Holster"); | ||||
|         if (typeof holster !== "undefined")  | ||||
|         { | ||||
|             holsterID = this.itemHelper.getItemName(holster._tpl); | ||||
|             const holsterCaliber = botDetails.find(e => e.slotId === "patron_in_weapon" && e.parentId == holster._id); | ||||
|             if (typeof holsterCaliber !== "undefined")  | ||||
|             { | ||||
|                 holsterCaliberID = this.itemHelper.getItemName(holsterCaliber._tpl); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         const helmet = botDetails.find(e => e.slotId === "Headwear"); | ||||
|         if (typeof helmet !== "undefined")  | ||||
|         { | ||||
|             helmetID = this.itemHelper.getItemName(helmet._tpl); | ||||
|         } | ||||
| 
 | ||||
|         const nvg = botDetails.find(e => e.slotId === "mod_nvg" && "upd" in e); | ||||
|         if (typeof nvg !== "undefined")  | ||||
|         { | ||||
|             nvgID = this.itemHelper.getItemName(nvg._tpl); | ||||
|         } | ||||
| 
 | ||||
|         const earPro = botDetails.find(e => e.slotId === "Earpiece"); | ||||
|         if (typeof earPro !== "undefined")  | ||||
|         { | ||||
|             earProID = this.itemHelper.getItemName(earPro._tpl); | ||||
|         } | ||||
| 
 | ||||
|         const scabbard = botDetails.find(e => e.slotId === "Scabbard"); | ||||
|         if (typeof scabbard !== "undefined")  | ||||
|         { | ||||
|             scabbardID = this.itemHelper.getItemName(scabbard._tpl); | ||||
|         } | ||||
| 
 | ||||
|         const armourVest = botDetails.find(e => e.slotId === "ArmorVest") ?? botDetails.find(e => e.slotId === "TacticalVest"); | ||||
|         if (typeof armourVest !== "undefined")  | ||||
|         { | ||||
|             armourVestID = this.itemHelper.getItem(armourVest._tpl); | ||||
|             if (armourVestID[1]._props.Slots[0]) | ||||
|             { | ||||
|                 canHavePlates = true; | ||||
|                 const frontPlate = botDetails.find(e => e.slotId === "Front_plate" && e.parentId == armourVest._id); | ||||
|                 const backPlate = botDetails.find(e => e.slotId === "Back_plate" && e.parentId == armourVest._id); | ||||
|                 const lSidePlate = botDetails.find(e => e.slotId === "Left_side_plate" && e.parentId == armourVest._id); | ||||
|                 const rSidePlate = botDetails.find(e => e.slotId === "Right_side_plate" && e.parentId == armourVest._id); | ||||
|                 if (typeof frontPlate !== "undefined") | ||||
|                 { | ||||
|                     frontPlateID = this.itemHelper.getItem(frontPlate._tpl) | ||||
|                     frontPlateID = frontPlateID[1]._props.armorClass; | ||||
|                 } | ||||
|                 if (typeof backPlate !== "undefined") | ||||
|                 { | ||||
|                     backPlateID = this.itemHelper.getItem(backPlate._tpl) | ||||
|                     backPlateID = backPlateID[1]._props.armorClass; | ||||
|                 } | ||||
|                 if (typeof lSidePlate !== "undefined") | ||||
|                 { | ||||
|                     lSidePlateID = this.itemHelper.getItem(lSidePlate._tpl) | ||||
|                     lSidePlateID = lSidePlateID[1]._props.armorClass; | ||||
|                 } | ||||
|                 if (typeof rSidePlate !== "undefined") | ||||
|                 { | ||||
|                     rSidePlateID = this.itemHelper.getItem(rSidePlate._tpl) | ||||
|                     rSidePlateID = rSidePlateID[1]._props.armorClass; | ||||
|                 } | ||||
|             } | ||||
|             armourVestID = this.itemHelper.getItemName(armourVest._tpl); | ||||
|         } | ||||
| 
 | ||||
|         return { | ||||
|             tier: detailsJSON.data[0].Info.Tier, | ||||
|             name: detailsJSON.data[0].Info.Nickname,  | ||||
|             level: detailsJSON.data[0].Info.Level,  | ||||
|             gameVersion: detailsJSON.data[0].Info.GameVersion,  | ||||
|             role: detailsJSON.data[0].Info.Settings.Role,  | ||||
|             side: detailsJSON.data[0].Info.Side, | ||||
|             difficulty: detailsJSON.data[0].Info.Settings.BotDifficulty, | ||||
|             primaryID, | ||||
|             primaryCaliberID, | ||||
|             secondaryID, | ||||
|             secondaryCaliberID, | ||||
|             holsterID, | ||||
|             holsterCaliberID, | ||||
|             helmetID, | ||||
|             nvgID, | ||||
|             earProID, | ||||
|             canHavePlates, | ||||
|             armourVestID, | ||||
|             frontPlateID, | ||||
|             backPlateID, | ||||
|             lSidePlateID, | ||||
|             rSidePlateID, | ||||
|             scabbardID, | ||||
|             grenadeCount | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private getLogMessage(botDetails: any): any | ||||
|     { | ||||
|         const removeNoneValues = value => | ||||
|             !["None"].some(element => value.includes(element)); | ||||
| 
 | ||||
|         const removeNonArmouredRigs = value => | ||||
|             !["Armour/Rig:"].some(element => value.includes(element)); | ||||
| 
 | ||||
|         let realMessage1; | ||||
|         let realMessage2; | ||||
|         let realMessage3; | ||||
|         let realMessage4; | ||||
| 
 | ||||
|         let temporaryMessage1: string[] = [ | ||||
|             `Tier: ${botDetails.tier}`, | ||||
|             `Role: ${botDetails.role}`, | ||||
|             `Nickname: ${botDetails.name}`, | ||||
|             `Level: ${botDetails.level}`, | ||||
|             `Difficulty: ${botDetails.difficulty}`, | ||||
|             `GameVersion: ${botDetails.gameVersion ?? "None" }`, | ||||
|             `Grenades: ${botDetails.grenadeCount >= 1 ? botDetails.grenadeCount : "None" }` | ||||
|         ]; | ||||
|         let temporaryMessage2: string[] = [ | ||||
|             `Primary: ${botDetails.primaryID ?? "None" }`, | ||||
|             `Primary Caliber: ${botDetails.primaryCaliberID ?? "None" }`, | ||||
|             `Secondary: ${botDetails.secondaryID ?? "None" }`, | ||||
|             `Secondary Caliber: ${botDetails.secondaryCaliberID ?? "None" }`, | ||||
|             `Holster: ${botDetails.holsterID ?? "None" }`, | ||||
|             `Holster Caliber: ${botDetails.holsterCaliberID ?? "None" }`, | ||||
|             `Melee: ${botDetails.scabbardID ?? "None" }` | ||||
|         ]; | ||||
|         let temporaryMessage3: string[] = [ | ||||
|             `Helmet: ${botDetails.helmetID ?? "None" }`, | ||||
|             `NVG: ${botDetails.nvgID ?? "None" }`, | ||||
|             `Ears: ${botDetails.earProID ?? "None" }`, | ||||
|             `Armour/Rig: ${botDetails.armourVestID ?? "None" }` | ||||
|         ]; | ||||
|         let temporaryMessage4: string[] = [ | ||||
|             "| Plates:", | ||||
|             `Front [${botDetails.frontPlateID ?? "None" }]`, | ||||
|             `Back [${botDetails.backPlateID ?? "None" }]`, | ||||
|             `Left [${botDetails.lSidePlateID ?? "None" }]`, | ||||
|             `Right [${botDetails.rSidePlateID ?? "None" }]` | ||||
|         ] | ||||
|          | ||||
|         temporaryMessage1 = temporaryMessage1.filter(removeNoneValues) | ||||
|         if (temporaryMessage1?.length)  | ||||
|         { | ||||
|             realMessage1 = temporaryMessage1.filter(Boolean).join(" | "); | ||||
|         } | ||||
|         realMessage1 = realMessage1 ?? "No Bot Details"; | ||||
| 
 | ||||
|         temporaryMessage2 = temporaryMessage2.filter(removeNoneValues) | ||||
|         if (temporaryMessage2?.length)  | ||||
|         { | ||||
|             realMessage2 = temporaryMessage2.filter(Boolean).join(" | "); | ||||
|         } | ||||
|         realMessage2 = realMessage2 ?? "No Weapon Details"; | ||||
| 
 | ||||
|         if (!botDetails.canHavePlates) | ||||
|         { | ||||
|             temporaryMessage3 = temporaryMessage3.filter(removeNonArmouredRigs) | ||||
|         } | ||||
|         temporaryMessage3 = temporaryMessage3.filter(removeNoneValues) | ||||
|         if (temporaryMessage3?.length)  | ||||
|         { | ||||
|              | ||||
|             realMessage3 = temporaryMessage3.filter(Boolean).join(" | "); | ||||
|         } | ||||
|         realMessage3 = realMessage3 ?? "No Gear Details"; | ||||
| 
 | ||||
|         temporaryMessage4 = temporaryMessage4.filter(removeNoneValues) | ||||
|         if (temporaryMessage4?.length > 1)  | ||||
|         { | ||||
|             realMessage4 = temporaryMessage4.filter(Boolean).join(" "); | ||||
|         } | ||||
|         realMessage4 = realMessage4 ?? " "; | ||||
| 
 | ||||
|         return [ | ||||
|             realMessage1, | ||||
|             realMessage2, | ||||
|             realMessage3, | ||||
|             realMessage4 | ||||
|         ] | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,43 @@ | |||
| /* eslint-disable @typescript-eslint/explicit-module-boundary-types */ | ||||
| 
 | ||||
| import { inject, injectable } from "tsyringe"; | ||||
| import { DatabaseService } from "@spt/services/DatabaseService"; | ||||
| import { ItemHelper } from "@spt/helpers/ItemHelper"; | ||||
| import { BaseClasses } from "@spt/models/enums/BaseClasses"; | ||||
| import { Logging } from "../Enums/Logging"; | ||||
| import { APBSLogger } from "./APBSLogger"; | ||||
| import { vanillaAttachments } from "../Globals/VanillaItemLists"; | ||||
| 
 | ||||
| @injectable() | ||||
| export class APBSAttachmentChecker | ||||
| { | ||||
|     public vanillaAttachmentList: string[] = []; | ||||
|     constructor( | ||||
|         @inject("DatabaseService") protected database: DatabaseService, | ||||
|         @inject("APBSLogger") protected apbsLogger: APBSLogger, | ||||
|         @inject("ItemHelper") protected itemHelper: ItemHelper | ||||
|     ) | ||||
|     {} | ||||
|      | ||||
|     public buildAttachmentList(): void | ||||
|     { | ||||
|         const items = this.database.getTables().templates.items; | ||||
|         const itemValues = Object.values(items); | ||||
|         const attachments = itemValues.filter(x => this.itemHelper.isOfBaseclass(x._id, BaseClasses.MOD)) | ||||
| 
 | ||||
|         for (const item in attachments) | ||||
|         { | ||||
|             this.vanillaAttachmentList.push(attachments[item]._id) | ||||
|         } | ||||
|         this.apbsLogger.log(Logging.DEBUG, `${JSON.stringify(this.vanillaAttachmentList)}`) | ||||
|     } | ||||
| 
 | ||||
|     public isVanillaItem(itemID: string): boolean | ||||
|     { | ||||
|         if (vanillaAttachments.includes(itemID))  | ||||
|         { | ||||
|             return true; | ||||
|         } | ||||
|         return false; | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,407 @@ | |||
| /* eslint-disable @typescript-eslint/explicit-module-boundary-types */ | ||||
| 
 | ||||
| import { inject, injectable } from "tsyringe"; | ||||
| import { WeightedRandomHelper } from "@spt/helpers/WeightedRandomHelper"; | ||||
| import { RaidInformation } from "../Globals/RaidInformation"; | ||||
| import { Logging } from "../Enums/Logging"; | ||||
| import { APBSLogger } from "./APBSLogger"; | ||||
| import { TierInformation } from "../Globals/TierInformation"; | ||||
| import { ModConfig } from "../Globals/ModConfig"; | ||||
| import { RandomUtil } from "@spt/utils/RandomUtil"; | ||||
| import { Season } from "@spt/models/enums/Season"; | ||||
| import { SeasonalEventService } from "@spt/services/SeasonalEventService"; | ||||
| 
 | ||||
| @injectable() | ||||
| export class APBSEquipmentGetter | ||||
| { | ||||
| 
 | ||||
|     constructor( | ||||
|         @inject("RaidInformation") protected raidInformation: RaidInformation, | ||||
|         @inject("TierInformation") protected tierInformation: TierInformation, | ||||
|         @inject("WeightedRandomHelper") protected weightedRandomHelper: WeightedRandomHelper, | ||||
|         @inject("APBSLogger") protected apbsLogger: APBSLogger, | ||||
|         @inject("RandomUtil") protected randomUtil: RandomUtil, | ||||
|         @inject("SeasonalEventService") protected seasonalEventService: SeasonalEventService | ||||
|     ) | ||||
|     {} | ||||
| 
 | ||||
|     private chadOrChill(tierInfo: number): number | ||||
|     { | ||||
|         if (ModConfig.config.onlyChads && ModConfig.config.tarkovAndChill) | ||||
|         { | ||||
|             return this.randomUtil.getInt(1, 7); | ||||
|         } | ||||
|         if (ModConfig.config.onlyChads) return 7; | ||||
|         if (ModConfig.config.tarkovAndChill) return 1; | ||||
|         if (ModConfig.config.blickyMode) return 0; | ||||
| 
 | ||||
|         return tierInfo; | ||||
|     } | ||||
| 
 | ||||
|     public getTierJson(tierInfo: number, ignoreCheck?: boolean) | ||||
|     { | ||||
|         if (!ignoreCheck) tierInfo = this.chadOrChill(tierInfo); | ||||
|         switch (tierInfo) | ||||
|         { | ||||
|             case 0: | ||||
|                 return this.tierInformation.tier0 | ||||
|             case 1: | ||||
|                 return this.tierInformation.tier1 | ||||
|             case 2: | ||||
|                 return this.tierInformation.tier2 | ||||
|             case 3: | ||||
|                 return this.tierInformation.tier3 | ||||
|             case 4: | ||||
|                 return this.tierInformation.tier4 | ||||
|             case 5: | ||||
|                 return this.tierInformation.tier5 | ||||
|             case 6: | ||||
|                 return this.tierInformation.tier6 | ||||
|             case 7: | ||||
|                 return this.tierInformation.tier7 | ||||
|             default: | ||||
|                 this.apbsLogger.log(Logging.WARN, "Bot Level and Tier Information missing, your load order is probably incorrect. Defaulting to Tier1 loadout."); | ||||
|                 return this.tierInformation.tier1 | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     public getTierModsJson(tierInfo: number, ignoreCheck?: boolean) | ||||
|     { | ||||
|         if (!ignoreCheck) tierInfo = this.chadOrChill(tierInfo); | ||||
|         switch (tierInfo) | ||||
|         { | ||||
|             case 0: | ||||
|                 return this.tierInformation.tier0mods | ||||
|             case 1: | ||||
|                 return this.tierInformation.tier1mods | ||||
|             case 2: | ||||
|                 return this.tierInformation.tier2mods | ||||
|             case 3: | ||||
|                 return this.tierInformation.tier3mods | ||||
|             case 4: | ||||
|                 return this.tierInformation.tier4mods | ||||
|             case 5: | ||||
|                 return this.tierInformation.tier5mods | ||||
|             case 6: | ||||
|                 return this.tierInformation.tier6mods | ||||
|             case 7: | ||||
|                 return this.tierInformation.tier7mods | ||||
|             default: | ||||
|                 this.apbsLogger.log(Logging.WARN, "Bot Level and Tier Information missing, your load order is probably incorrect. Defaulting to Tier1 mods."); | ||||
|                 return this.tierInformation.tier1mods | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     public getTierChancesJson(tierInfo: number) | ||||
|     { | ||||
|         tierInfo = this.chadOrChill(tierInfo); | ||||
|         switch (tierInfo) | ||||
|         { | ||||
|             case 0: | ||||
|                 return this.tierInformation.tier0chances | ||||
|             case 1: | ||||
|                 return this.tierInformation.tier1chances | ||||
|             case 2: | ||||
|                 return this.tierInformation.tier2chances | ||||
|             case 3: | ||||
|                 return this.tierInformation.tier3chances | ||||
|             case 4: | ||||
|                 return this.tierInformation.tier4chances | ||||
|             case 5: | ||||
|                 return this.tierInformation.tier5chances | ||||
|             case 6: | ||||
|                 return this.tierInformation.tier6chances | ||||
|             case 7: | ||||
|                 return this.tierInformation.tier7chances | ||||
|             default: | ||||
|                 this.apbsLogger.log(Logging.WARN, "Bot Level and Tier Information missing, your load order is probably incorrect. Defaulting to Tier1 chances."); | ||||
|                 return this.tierInformation.tier1chances | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     public getTierAmmoJson(tierInfo: number, ignoreCheck?: boolean) | ||||
|     { | ||||
|         if (!ignoreCheck) tierInfo = this.chadOrChill(tierInfo); | ||||
|         switch (tierInfo) | ||||
|         { | ||||
|             case 0: | ||||
|                 return this.tierInformation.tier0ammo | ||||
|             case 1: | ||||
|                 return this.tierInformation.tier1ammo | ||||
|             case 2: | ||||
|                 return this.tierInformation.tier2ammo | ||||
|             case 3: | ||||
|                 return this.tierInformation.tier3ammo | ||||
|             case 4: | ||||
|                 return this.tierInformation.tier4ammo | ||||
|             case 5: | ||||
|                 return this.tierInformation.tier5ammo | ||||
|             case 6: | ||||
|                 return this.tierInformation.tier6ammo | ||||
|             case 7: | ||||
|                 return this.tierInformation.tier7ammo | ||||
|             default: | ||||
|                 this.apbsLogger.log(Logging.WARN, "Bot Level and Tier Information missing, your load order is probably incorrect. Defaulting to Tier1 ammo."); | ||||
|                 return this.tierInformation.tier1ammo | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     public getAppearanceJson(tierInfo: number, ignoreCheck?: boolean) | ||||
|     { | ||||
|         if (!ignoreCheck) tierInfo = this.chadOrChill(tierInfo); | ||||
|         switch (tierInfo) | ||||
|         { | ||||
|             case 0: | ||||
|                 return this.tierInformation.tier0appearance | ||||
|             case 1: | ||||
|                 return this.tierInformation.tier1appearance | ||||
|             case 2: | ||||
|                 return this.tierInformation.tier2appearance | ||||
|             case 3: | ||||
|                 return this.tierInformation.tier3appearance | ||||
|             case 4: | ||||
|                 return this.tierInformation.tier4appearance | ||||
|             case 5: | ||||
|                 return this.tierInformation.tier5appearance | ||||
|             case 6: | ||||
|                 return this.tierInformation.tier6appearance | ||||
|             case 7: | ||||
|                 return this.tierInformation.tier7appearance | ||||
|             default: | ||||
|                 this.apbsLogger.log(Logging.WARN, "Bot Level and Tier Information missing, your load order is probably incorrect. Defaulting to Tier1 appearance."); | ||||
|                 return this.tierInformation.tier1appearance | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     public getModsByBotRole(botRole: string, tierInfo: number): any | ||||
|     { | ||||
|         const tierJson = this.getTierModsJson(tierInfo) | ||||
|         switch (botRole) | ||||
|         { | ||||
|             case "bossboar": | ||||
|             case "bossboarsniper": | ||||
|             case "bossbully": | ||||
|             case "bossgluhar": | ||||
|             case "bosskilla": | ||||
|             case "bosskojaniy": | ||||
|             case "bosskolontay": | ||||
|             case "bosssanitar": | ||||
|             case "bosstagilla": | ||||
|             case "bosspartisan": | ||||
|             case "bossknight": | ||||
|             case "followerbigpipe": | ||||
|             case "followerbirdeye": | ||||
|             case "sectantpriest": | ||||
|             case "sectantwarrior": | ||||
|             case "exusec": | ||||
|             case "arenafighterevent": | ||||
|             case "arenafighter": | ||||
|             case "pmcbot": | ||||
|                 if (tierInfo < 4) return this.tierInformation.tier4mods; | ||||
|                 else return tierJson; | ||||
|             case "marksman": | ||||
|             case "cursedassault": | ||||
|             case "assault": | ||||
|                 if (ModConfig.config.blickyMode || ModConfig.config.onlyChads || ModConfig.config.enableScavAttachmentTiering) return tierJson; | ||||
|                 else return this.tierInformation.tier1mods; | ||||
|             default: | ||||
|                 return tierJson; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     public getEquipmentByBotRole(botRole: string, tierInfo: number, slot: string, range?: string): Record<string, number> | ||||
|     { | ||||
|         const tierJson = this.getTierJson(tierInfo) | ||||
|         switch (botRole) | ||||
|         { | ||||
|             case "pmcusec": | ||||
|                 return (range == undefined) ? tierJson.pmcUSEC.equipment[slot] : tierJson.pmcUSEC.equipment[slot][range]; | ||||
|             case "pmcbear": | ||||
|                 return (range == undefined) ? tierJson.pmcBEAR.equipment[slot] : tierJson.pmcBEAR.equipment[slot][range]; | ||||
|             case "marksman": | ||||
|                 return (range == undefined) ? tierJson.scav.equipment[slot] : tierJson.scav.equipment[slot].LongRange; | ||||
|             case "cursedassault": | ||||
|             case "assault": | ||||
|                 return (range == undefined) ? tierJson.scav.equipment[slot] : tierJson.scav.equipment[slot].ShortRange; | ||||
|             case "bossboar": | ||||
|                 return (range == undefined) ? tierJson.bossboar.equipment[slot] : tierJson.bossboar.equipment[slot][range]; | ||||
|             case "bossboarsniper": | ||||
|                 return (range == undefined) ? tierJson.bossboarsniper.equipment[slot] : tierJson.bossboarsniper.equipment[slot][range]; | ||||
|             case "bossbully": | ||||
|                 return (range == undefined) ? tierJson.bossbully.equipment[slot] : tierJson.bossbully.equipment[slot][range]; | ||||
|             case "bossgluhar": | ||||
|                 return (range == undefined) ? tierJson.bossgluhar.equipment[slot] : tierJson.bossgluhar.equipment[slot][range]; | ||||
|             case "bosskilla": | ||||
|                 return (range == undefined) ? tierJson.bosskilla.equipment[slot] : tierJson.bosskilla.equipment[slot][range]; | ||||
|             case "bosskojaniy": | ||||
|                 return (range == undefined) ? tierJson.bosskojaniy.equipment[slot] : tierJson.bosskojaniy.equipment[slot][range]; | ||||
|             case "bosskolontay": | ||||
|                 return (range == undefined) ? tierJson.bosskolontay.equipment[slot] : tierJson.bosskolontay.equipment[slot][range]; | ||||
|             case "bosssanitar": | ||||
|                 return (range == undefined) ? tierJson.bosssanitar.equipment[slot] : tierJson.bosssanitar.equipment[slot][range]; | ||||
|             case "bosstagilla": | ||||
|                 return (range == undefined) ? tierJson.bosstagilla.equipment[slot] : tierJson.bosstagilla.equipment[slot][range]; | ||||
|             case "bosspartisan": | ||||
|                 return (range == undefined) ? tierJson.bosspartisan.equipment[slot] : tierJson.bosspartisan.equipment[slot][range]; | ||||
|             case "bossknight": | ||||
|                 return (range == undefined) ? tierJson.bossknight.equipment[slot] : tierJson.bossknight.equipment[slot][range]; | ||||
|             case "followerbigpipe": | ||||
|                 return (range == undefined) ? tierJson.followerbigpipe.equipment[slot] : tierJson.followerbigpipe.equipment[slot][range]; | ||||
|             case "followerbirdeye": | ||||
|                 return (range == undefined) ? tierJson.followerbirdeye.equipment[slot] : tierJson.followerbirdeye.equipment[slot][range]; | ||||
|             case "sectantpriest": | ||||
|                 return (range == undefined) ? tierJson.sectantpriest.equipment[slot] : tierJson.sectantpriest.equipment[slot][range]; | ||||
|             case "sectantwarrior": | ||||
|                 return (range == undefined) ? tierJson.sectantwarrior.equipment[slot] : tierJson.sectantwarrior.equipment[slot][range]; | ||||
|             case "exusec": | ||||
|             case "arenafighterevent": | ||||
|             case "arenafighter": | ||||
|                 return (range == undefined) ? tierJson.exUSEC.equipment[slot] : tierJson.exUSEC.equipment[slot][range]; | ||||
|             case "pmcbot": | ||||
|                 return (range == undefined) ? tierJson.pmcbot.equipment[slot] : tierJson.pmcbot.equipment[slot][range]; | ||||
|             default: | ||||
|                 return (range == undefined) ? tierJson.default.equipment[slot] : tierJson.default.equipment[slot][range]; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     public getSpawnChancesByBotRole(botRole: string, tierInfo: number): any | ||||
|     { | ||||
|         const tierJson = this.getTierChancesJson(tierInfo) | ||||
|         switch (botRole) | ||||
|         { | ||||
|             case "pmcbear": | ||||
|                 return tierJson.pmcBEAR.chances; | ||||
|             case "pmcusec": | ||||
|                 return tierJson.pmcUSEC.chances; | ||||
|             case "marksman": | ||||
|             case "cursedassault": | ||||
|             case "assault": | ||||
|                 return tierJson.scav.chances; | ||||
|             case "bossboar": | ||||
|                 return tierJson.bossboar.chances; | ||||
|             case "bossboarsniper": | ||||
|                 return tierJson.bossboarsniper.chances; | ||||
|             case "bossbully": | ||||
|                 return tierJson.bossbully.chances; | ||||
|             case "bossgluhar": | ||||
|                 return tierJson.bossgluhar.chances; | ||||
|             case "bosskilla": | ||||
|                 return tierJson.bosskilla.chances; | ||||
|             case "bossknight": | ||||
|                 return tierJson.bossknight.chances; | ||||
|             case "bosskojaniy": | ||||
|                 return tierJson.bosskojaniy.chances; | ||||
|             case "bosskolontay": | ||||
|                 return tierJson.bosskolontay.chances; | ||||
|             case "bosssanitar": | ||||
|                 return tierJson.bosssanitar.chances; | ||||
|             case "bosstagilla": | ||||
|                 return tierJson.bosstagilla.chances; | ||||
|             case "bosspartisan": | ||||
|                 return tierJson.bosspartisan.chances; | ||||
|             case "bosszryachiy": | ||||
|                 return tierJson.bosszryachiy.chances; | ||||
|             case "followerbigpipe": | ||||
|                 return tierJson.followerbigpipe.chances; | ||||
|             case "followerbirdeye": | ||||
|                 return tierJson.followerbirdeye.chances; | ||||
|             case "sectantpriest": | ||||
|                 return tierJson.sectantpriest.chances; | ||||
|             case "sectantwarrior": | ||||
|                 return tierJson.sectantwarrior.chances; | ||||
|             case "exusec": | ||||
|                 return tierJson.exusec.chances; | ||||
|             case "pmcbot": | ||||
|                 return tierJson.pmcbot.chances; | ||||
|             default: | ||||
|                 return tierJson.default.chances; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     public getAmmoByBotRole(botRole: string, tierInfo: number): Record<string, Record<string, number>> | ||||
|     { | ||||
|         if ((botRole == "pmcusec" || botRole == "pmcbear") && ModConfig.config.enablePMCAmmoTierSliding) | ||||
|         { | ||||
|             if (this.randomUtil.getChance100(ModConfig.config.slideChance)) | ||||
|             { | ||||
|                 const slideAmount = ModConfig.config.slideAmount; | ||||
|                 const minTier = (tierInfo - slideAmount) <= 0 ? 1 : tierInfo - slideAmount | ||||
|                 const maxTier = tierInfo - 1 | ||||
|                 tierInfo = this.newTierCalc(tierInfo, minTier, maxTier); | ||||
|             } | ||||
|         } | ||||
|         const tierJson = this.getTierAmmoJson(tierInfo) | ||||
|         switch (botRole) | ||||
|         { | ||||
|             case "marksman": | ||||
|             case "cursedassault": | ||||
|             case "assault": | ||||
|                 return tierJson.scavAmmo; | ||||
|             case "pmcusec": | ||||
|             case "pmcbear": | ||||
|                 return tierJson.pmcAmmo; | ||||
|             default: | ||||
|                 return tierJson.bossAmmo; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     public getPmcAppearance(botRole: string, tierInfo: number, getSeason?: boolean): Record<string, Record<string, number>> | ||||
|     { | ||||
|         const tierJson = this.getAppearanceJson(tierInfo) | ||||
|         switch (botRole) | ||||
|         { | ||||
|             case "pmcUSEC": | ||||
|                 if (getSeason && tierInfo != 0) | ||||
|                 { | ||||
|                     const activeSeason: Season = this.seasonalEventService.getActiveWeatherSeason(); | ||||
|                     switch (activeSeason) | ||||
|                     { | ||||
|                         case Season.SPRING_EARLY: | ||||
|                             return tierJson.springEarly.pmcUSEC.appearance; | ||||
|                         case Season.SPRING: | ||||
|                             return tierJson.spring.pmcUSEC.appearance; | ||||
|                         case Season.SUMMER: | ||||
|                         case Season.STORM: | ||||
|                             return tierJson.summer.pmcUSEC.appearance; | ||||
|                         case Season.AUTUMN: | ||||
|                         case Season.AUTUMN_LATE: | ||||
|                             return tierJson.autumn.pmcUSEC.appearance; | ||||
|                         case Season.WINTER: | ||||
|                             return tierJson.winter.pmcUSEC.appearance; | ||||
|                         default: | ||||
|                             return tierJson.summer.pmcUSEC.appearance; | ||||
|                     } | ||||
|                 } | ||||
|                 return tierJson.pmcUSEC.appearance; | ||||
|             case "pmcBEAR": | ||||
|                 if (getSeason && tierInfo != 0) | ||||
|                 { | ||||
|                     const activeSeason: Season = this.seasonalEventService.getActiveWeatherSeason(); | ||||
|                     switch (activeSeason) | ||||
|                     { | ||||
|                         case Season.SPRING_EARLY: | ||||
|                             return tierJson.springEarly.pmcBEAR.appearance; | ||||
|                         case Season.SPRING: | ||||
|                             return tierJson.spring.pmcBEAR.appearance; | ||||
|                         case Season.SUMMER: | ||||
|                         case Season.STORM: | ||||
|                             return tierJson.summer.pmcBEAR.appearance; | ||||
|                         case Season.AUTUMN: | ||||
|                         case Season.AUTUMN_LATE: | ||||
|                             return tierJson.autumn.pmcBEAR.appearance; | ||||
|                         case Season.WINTER: | ||||
|                             return tierJson.winter.pmcBEAR.appearance; | ||||
|                         default: | ||||
|                             return tierJson.summer.pmcBEAR.appearance; | ||||
|                     } | ||||
|                 } | ||||
|                 return tierJson.pmcBEAR.appearance; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private newTierCalc(tierInfo: number, minTier: number, maxTier: number): number | ||||
|     { | ||||
|         const newTier = (Math.floor(Math.random() * (maxTier - minTier + 1) + minTier)) >= tierInfo  ? (tierInfo - 1) : (Math.floor(Math.random() * (maxTier - minTier + 1) + minTier)) | ||||
|         return newTier; | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,93 @@ | |||
| import { inject, injectable } from "tsyringe"; | ||||
| import { ILogger } from "@spt/models/spt/utils/ILogger"; | ||||
| 
 | ||||
| import { Logging, LoggingFolders } from "../Enums/Logging"; | ||||
| import { ModInformation } from "../Globals/ModInformation"; | ||||
| import fs from "node:fs"; | ||||
| import { ModConfig } from "../Globals/ModConfig"; | ||||
| 
 | ||||
| @injectable() | ||||
| export class APBSLogger | ||||
| { | ||||
|     constructor( | ||||
|         @inject("WinstonLogger") protected logger: ILogger, | ||||
|         @inject("ModInformation") protected modInformation: ModInformation | ||||
|     ) | ||||
|     {} | ||||
| 
 | ||||
|     public createLogFiles(): void | ||||
|     { | ||||
|         for (const value in LoggingFolders) | ||||
|         { | ||||
|             fs.writeFileSync(`${this.modInformation.logPath}/${LoggingFolders[value]}.log`, `${new Date().toLocaleString()} - Log File Created - APBS Version: ${this.modInformation.versionNumber}\n`); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     public log(logcation: Logging, message: string, message2?: string, message3?: string, message4?: string, message5?: string, message6?: string, message7?: string, message8?: string): void | ||||
|     { | ||||
|         if (!ModConfig.config.enableDebugLog && logcation == Logging.DEBUG) return; | ||||
|         const messagesArray = { | ||||
|             message, | ||||
|             message2, | ||||
|             message3, | ||||
|             message4, | ||||
|             message5, | ||||
|             message6, | ||||
|             message7, | ||||
|             message8 | ||||
|         } | ||||
|         let messages: string = ""; | ||||
|         let textFlag; | ||||
|         let logType; | ||||
|         let showInConsole; | ||||
|         let consoleMessage = ""; | ||||
|         for (const line in messagesArray) | ||||
|         { | ||||
|             if (messagesArray[line] !== undefined) | ||||
|             { | ||||
|                 switch (logcation)  | ||||
|                 { | ||||
|                     case Logging.DEBUG: | ||||
|                         logType = Logging.DEBUG; | ||||
|                         textFlag = " DEBUG - " | ||||
|                         showInConsole = false; | ||||
|                         break; | ||||
|                     case Logging.WARN: | ||||
|                         logType = Logging.DEBUG; | ||||
|                         textFlag = " WARNING - " | ||||
|                         showInConsole = true; | ||||
|                         break; | ||||
|                     case Logging.ERR: | ||||
|                         logType = Logging.DEBUG; | ||||
|                         textFlag = " ERROR - " | ||||
|                         showInConsole = true; | ||||
|                         break; | ||||
|                     default: | ||||
|                         logType = logcation; | ||||
|                         textFlag = " - " | ||||
|                         showInConsole = false; | ||||
|                         break; | ||||
|                 } | ||||
|                 if (showInConsole) | ||||
|                 { | ||||
|                     consoleMessage += `${messagesArray[line]}`; | ||||
|                     messages += `${new Date().toLocaleString()}${textFlag}${messagesArray[line]}\n`; | ||||
|                     continue; | ||||
|                 } | ||||
|                 messages += `${new Date().toLocaleString()}${textFlag}${messagesArray[line]}\n`; | ||||
|             } | ||||
|         } | ||||
|         fs.appendFileSync(`${this.modInformation.logPath}/${logType}.log`, `${messages}`); | ||||
|         if (showInConsole)  | ||||
|         { | ||||
|             if (logcation == Logging.WARN)  | ||||
|             { | ||||
|                 this.logger.warning(`[APBS] ${consoleMessage}`); | ||||
|             } | ||||
|             if (logcation == Logging.ERR)  | ||||
|             { | ||||
|                 this.logger.error(`[APBS] ${consoleMessage}`); | ||||
|             } | ||||
|         } | ||||
|     }     | ||||
| } | ||||
|  | @ -0,0 +1,121 @@ | |||
| /* eslint-disable @typescript-eslint/explicit-module-boundary-types */ | ||||
| 
 | ||||
| import { inject, injectable } from "tsyringe"; | ||||
| import { APBSLogger } from "./APBSLogger"; | ||||
| import { IItem } from "@spt/models/eft/common/tables/IItem"; | ||||
| import { HashUtil } from "@spt/utils/HashUtil"; | ||||
| import { IBarterScheme, ITrader } from "@spt/models/eft/common/tables/ITrader"; | ||||
| import { Money } from "@spt/models/enums/Money"; | ||||
| import { Logging } from "../Enums/Logging"; | ||||
| 
 | ||||
| @injectable() | ||||
| export class APBSTester | ||||
| { | ||||
|     protected itemsToSell: IItem[] = []; | ||||
|     protected barterScheme: Record<string, IBarterScheme[][]> = {}; | ||||
|     protected loyaltyLevel: Record<string, number> = {}; | ||||
| 
 | ||||
|     constructor( | ||||
|         @inject("APBSLogger") protected apbsLogger: APBSLogger, | ||||
|         @inject("HashUtil") protected hashUtil: HashUtil | ||||
|     ) | ||||
|     {} | ||||
| 
 | ||||
|     public createComplexAssortItem(items: IItem[]): APBSTester | ||||
|     { | ||||
|         items[0].parentId = "hideout"; | ||||
|         items[0].slotId = "hideout"; | ||||
| 
 | ||||
|         if (!items[0].upd) | ||||
|         { | ||||
|             items[0].upd = {} | ||||
|         } | ||||
| 
 | ||||
|         items[0].upd.UnlimitedCount = false; | ||||
|         items[0].upd.StackObjectsCount = 100; | ||||
| 
 | ||||
|         this.itemsToSell.push(...items); | ||||
| 
 | ||||
|         return this; | ||||
|     } | ||||
| 
 | ||||
|     public addStackCount(stackCount: number): APBSTester | ||||
|     { | ||||
|         this.itemsToSell[0].upd.StackObjectsCount = stackCount; | ||||
| 
 | ||||
|         return this; | ||||
|     } | ||||
| 
 | ||||
|     public addUnlimitedStackCount(): APBSTester | ||||
|     { | ||||
|         this.itemsToSell[0].upd.StackObjectsCount = 999999; | ||||
|         this.itemsToSell[0].upd.UnlimitedCount = true; | ||||
| 
 | ||||
|         return this; | ||||
|     } | ||||
| 
 | ||||
|     public makeStackCountUnlimited(): APBSTester | ||||
|     { | ||||
|         this.itemsToSell[0].upd.StackObjectsCount = 999999; | ||||
| 
 | ||||
|         return this; | ||||
|     } | ||||
| 
 | ||||
|     public addBuyRestriction(maxBuyLimit: number): APBSTester | ||||
|     { | ||||
|         this.itemsToSell[0].upd.BuyRestrictionMax = maxBuyLimit; | ||||
|         this.itemsToSell[0].upd.BuyRestrictionCurrent = 0; | ||||
| 
 | ||||
|         return this; | ||||
|     } | ||||
| 
 | ||||
|     public addLoyaltyLevel(level: number): APBSTester | ||||
|     { | ||||
|         this.loyaltyLevel[this.itemsToSell[0]._id] = level; | ||||
| 
 | ||||
|         return this; | ||||
|     } | ||||
| 
 | ||||
|     public addMoneyCost(currencyType: Money, amount: number): APBSTester | ||||
|     { | ||||
|         this.barterScheme[this.itemsToSell[0]._id] = [ | ||||
|             [ | ||||
|                 { | ||||
|                     count: amount, | ||||
|                     _tpl: currencyType | ||||
|                 } | ||||
|             ] | ||||
|         ]; | ||||
| 
 | ||||
|         return this; | ||||
|     } | ||||
| 
 | ||||
|     public export(data: ITrader): APBSTester | ||||
|     { | ||||
|         const itemBeingSoldId = this.itemsToSell[0]._id; | ||||
|         if (data.assort.items.find(x => x._id === itemBeingSoldId)) | ||||
|         { | ||||
|             this.apbsLogger.log(Logging.WARN, `Unable to add complex item with item key ${this.itemsToSell[0]._id}, key already used`); | ||||
| 
 | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         data.assort.items.push(...this.itemsToSell); | ||||
|         data.assort.barter_scheme[itemBeingSoldId] = this.barterScheme[itemBeingSoldId]; | ||||
|         data.assort.loyal_level_items[itemBeingSoldId] = this.loyaltyLevel[itemBeingSoldId]; | ||||
| 
 | ||||
|         this.itemsToSell = []; | ||||
|         this.barterScheme = {}; | ||||
|         this.loyaltyLevel = {}; | ||||
| 
 | ||||
|         return this; | ||||
|     } | ||||
| 
 | ||||
|     public clearAssort(data: ITrader): any | ||||
|     { | ||||
|          | ||||
|         data.assort.items = []; | ||||
|         data.assort.barter_scheme = {}; | ||||
|         data.assort.loyal_level_items = {}; | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,36 @@ | |||
| import { inject, injectable } from "tsyringe"; | ||||
| import { TierInformation } from "../Globals/TierInformation"; | ||||
| 
 | ||||
| @injectable() | ||||
| export class APBSTierGetter | ||||
| { | ||||
|     constructor( | ||||
|         @inject("TierInformation") protected tierInformation: TierInformation | ||||
|     ) | ||||
|     {} | ||||
| 
 | ||||
|     public getTierByLevel(level: number): number | ||||
|     { | ||||
|         return this.tierInformation.tiers.find(({playerMinimumLevel,playerMaximumLevel}) => level>=playerMinimumLevel && level<=playerMaximumLevel)?.tier | ||||
|     } | ||||
| 
 | ||||
|     public getTierUpperLevelDeviation(level:number): number | ||||
|     { | ||||
|         return this.tierInformation.tiers.find(({playerMinimumLevel,playerMaximumLevel}) => level>=playerMinimumLevel && level<=playerMaximumLevel)?.botMaxLevelVariance | ||||
|     } | ||||
| 
 | ||||
|     public getTierLowerLevelDeviation(level:number): number | ||||
|     { | ||||
|         return this.tierInformation.tiers.find(({playerMinimumLevel,playerMaximumLevel}) => level>=playerMinimumLevel && level<=playerMaximumLevel)?.botMinLevelVariance | ||||
|     } | ||||
| 
 | ||||
|     public getScavTierUpperLevelDeviation(level:number): number | ||||
|     { | ||||
|         return this.tierInformation.tiers.find(({playerMinimumLevel,playerMaximumLevel}) => level>=playerMinimumLevel && level<=playerMaximumLevel)?.scavMaxLevelVariance | ||||
|     } | ||||
| 
 | ||||
|     public getScavTierLowerLevelDeviation(level:number): number | ||||
|     { | ||||
|         return this.tierInformation.tiers.find(({playerMinimumLevel,playerMaximumLevel}) => level>=playerMinimumLevel && level<=playerMaximumLevel)?.scavMinLevelVariance | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,17 @@ | |||
| { | ||||
|     "scavAmmo": { | ||||
|         "Caliber20x1mm": { | ||||
|             "6601546f86889319850bd566": 1 | ||||
|         } | ||||
|     }, | ||||
|     "pmcAmmo": { | ||||
|         "Caliber20x1mm": { | ||||
|             "6601546f86889319850bd566": 1 | ||||
|         } | ||||
|     }, | ||||
|     "bossAmmo": { | ||||
|         "Caliber20x1mm": { | ||||
|             "6601546f86889319850bd566": 1 | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,46 @@ | |||
| { | ||||
|     "pmcUSEC": { | ||||
|         "appearance": { | ||||
|             "body": { | ||||
|                 "5cde95d97d6c8b647a3769b0": 5 | ||||
|             }, | ||||
|             "feet": { | ||||
|                 "5cde95ef7d6c8b04713c4f2d": 5 | ||||
|             }, | ||||
|             "hands": { | ||||
|                 "5cde95fa7d6c8b04737c2d13": 1 | ||||
|             }, | ||||
|             "head": { | ||||
|                 "5cde96047d6c8b20b577f016": 1, | ||||
|                 "5fdb4139e4ed5b5ea251e4ed": 1, | ||||
|                 "5fdb5950f5264a66150d1c6e": 1, | ||||
|                 "60a6aa8fd559ae040d0d951f": 1, | ||||
|                 "619f9e338858a474c8685cc9": 1, | ||||
|                 "62aca6a1310e67685a2fc2e7": 1, | ||||
|                 "6574aabee0423b9ebe0c79cf": 1 | ||||
|             } | ||||
|         } | ||||
|     }, | ||||
|     "pmcBEAR": { | ||||
|         "appearance": { | ||||
|             "body": { | ||||
|                 "5cc0858d14c02e000c6bea66": 5 | ||||
|             }, | ||||
|             "feet": { | ||||
|                 "5cc085bb14c02e000e67a5c5": 5 | ||||
|             }, | ||||
|             "hands": { | ||||
|                 "5cc0876314c02e000c6bea6b": 1 | ||||
|             }, | ||||
|             "head": { | ||||
|                 "5cc084dd14c02e000b0550a3": 1, | ||||
|                 "5fdb50bb2b730a787b3f78cf": 1, | ||||
|                 "5fdb7571e4ed5b5ea251e529": 1, | ||||
|                 "60a6aaad42fd2735e4589978": 1, | ||||
|                 "619f94f5b90286142b59d45f": 1, | ||||
|                 "62a9e7d15ea3b87d6f642a28": 1, | ||||
|                 "6574aa9a1b144de18c0fba45": 1 | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							|  | @ -0,0 +1,68 @@ | |||
| { | ||||
|   "66015072e9f84d5680039678": { | ||||
|     "mod_magazine": [ | ||||
|       "66015dc4aaad2f54cb04c56a" | ||||
|     ], | ||||
|     "patron_in_weapon": [ | ||||
|       "6601546f86889319850bd566" | ||||
|     ] | ||||
|   }, | ||||
|   "66015dc4aaad2f54cb04c56a" : { | ||||
|     "cartridges": [ | ||||
|       "6601546f86889319850bd566" | ||||
|     ] | ||||
|   }, | ||||
|   "62a09d79de7ac81993580530": { | ||||
|     "Soft_armor_front": [ | ||||
|       "6572e048371fccfbf909d5d8" | ||||
|     ], | ||||
|     "Soft_armor_back": [ | ||||
|       "6572e059371fccfbf909d5dc" | ||||
|     ], | ||||
|     "Soft_armor_left": [ | ||||
|       "6572e06219b4b511af012f89" | ||||
|     ], | ||||
|     "soft_armor_right": [ | ||||
|       "6572e06819b4b511af012f8d" | ||||
|     ] | ||||
|   }, | ||||
|   "5aa7d03ae5b5b00016327db5": { | ||||
|     "helmet_top": [ | ||||
|       "654a90aff4f81a421b0a7c86" | ||||
|     ], | ||||
|     "helmet_back": [ | ||||
|       "654a91068e1ce698150fd1e2" | ||||
|     ], | ||||
|     "helmet_ears": [ | ||||
|       "654a9189bcc67a392b056c79" | ||||
|     ] | ||||
|   }, | ||||
|   "5ab8e4ed86f7742d8e50c7fa": { | ||||
|     "Soft_armor_front": [ | ||||
|       "657044e971369562b300ce9b" | ||||
|     ], | ||||
|     "Soft_armor_back": [ | ||||
|       "657045741bd9beedc40b7299" | ||||
|     ], | ||||
|     "Soft_armor_left": [ | ||||
|       "657045b97e80617cee095bda" | ||||
|     ], | ||||
|     "soft_armor_right": [ | ||||
|       "6570460471369562b300ce9f" | ||||
|     ] | ||||
|   }, | ||||
|   "607f20859ee58b18e41ecd90": { | ||||
|     "Soft_armor_front": [ | ||||
|       "65703d866584602f7d057a8a" | ||||
|     ], | ||||
|     "Soft_armor_back": [ | ||||
|       "65703fa06584602f7d057a8e" | ||||
|     ], | ||||
|     "Soft_armor_left": [ | ||||
|       "65703fe46a912c8b5c03468b" | ||||
|     ], | ||||
|     "soft_armor_right": [ | ||||
|       "657040374e67e8ec7a0d261c" | ||||
|     ] | ||||
|   } | ||||
| } | ||||
|  | @ -0,0 +1,479 @@ | |||
| { | ||||
|     "scavAmmo": { | ||||
|         "Caliber1143x23ACP": { | ||||
|             "5efb0fc6aeb21837e749c801": 1, | ||||
|             "5efb0d4f4bc50b58e81710f3": 3 | ||||
|         }, | ||||
|         "Caliber127x55": { | ||||
|             "5cadf6e5ae921500113bb973": 1 | ||||
|         }, | ||||
|         "Caliber12g": { | ||||
|             "5d6e6772a4b936088465b17c": 2, | ||||
|             "5d6e6806a4b936088465b17e": 2, | ||||
|             "5d6e67fba4b9361bc73bc779": 2, | ||||
|             "560d5e524bdc2d25448b4571": 2, | ||||
|             "5d6e6869a4b9361c140bcfde": 1, | ||||
|             "5d6e68b3a4b9361bca7e50b5": 1, | ||||
|             "58820d1224597753c90aeb13": 1, | ||||
|             "5d6e68dea4b9361bcc29e659": 1, | ||||
|             "5d6e6891a4b9361bd473feea": 1, | ||||
|             "5d6e68e6a4b9361c140bcfe0": 1, | ||||
|             "5d6e689ca4b9361bc8618956": 1 | ||||
|         }, | ||||
|         "Caliber20g": { | ||||
|             "5d6e695fa4b936359b35d852": 2, | ||||
|             "5d6e69b9a4b9361bc8618958": 2, | ||||
|             "5a38ebd9c4a282000d722a5b": 2, | ||||
|             "5d6e69c7a4b9360b6c0d54e4": 1, | ||||
|             "5d6e6a53a4b9361bd473feec": 1 | ||||
|         }, | ||||
|         "Caliber23x75": { | ||||
|             "5f647f31b6238e5dd066e196": 3, | ||||
|             "5e85a9a6eacf8c039e4e2ac1": 1 | ||||
|         }, | ||||
|         "Caliber366TKM": { | ||||
|             "59e6658b86f77411d949b250": 3, | ||||
|             "59e6542b86f77411dc52a77a": 1 | ||||
|         }, | ||||
|         "Caliber40mmRU": { | ||||
|             "5656eb674bdc2d35148b457c": 1 | ||||
|         }, | ||||
|         "Caliber40x46": { | ||||
|             "5ede4739e0350d05467f73e8": 1, | ||||
|             "5ede47405b097655935d7d16": 1, | ||||
|             "5ede474b0c226a66f5402622": 1, | ||||
|             "5ede475339ee016e8c534742": 1, | ||||
|             "5ede475b549eed7c6d5c18fb": 1, | ||||
|             "5f0c892565703e5c461894e9": 1 | ||||
|         }, | ||||
|         "Caliber46x30": { | ||||
|             "5ba26812d4351e003201fef1": 3, | ||||
|             "5ba26844d4351e00334c9475": 1 | ||||
|         }, | ||||
|         "Caliber545x39": { | ||||
|             "56dff216d2720bbd668b4568": 1, | ||||
|             "56dff338d2720bbd668b4569": 4, | ||||
|             "56dff421d2720b5f5a8b4567": 4, | ||||
|             "56dff4ecd2720b5f5a8b4568": 2, | ||||
|             "56dff4a2d2720bbd668b456a": 4, | ||||
|             "56dff0bed2720bb0668b4567": 3, | ||||
|             "56dff3afd2720bba668b4567": 1 | ||||
|         }, | ||||
|         "Caliber556x45NATO": { | ||||
|             "59e6927d86f77411da468256": 2, | ||||
|             "59e6918f86f7746c9f75e849": 2, | ||||
|             "59e68f6f86f7746c9f75e846": 4, | ||||
|             "59e6920f86f77411d82aa167": 5, | ||||
|             "54527a984bdc2d4e668b4567": 1 | ||||
|         }, | ||||
|         "Caliber57x28": { | ||||
|             "5cc86832d7f00c000d3a6e6c": 2, | ||||
|             "5cc80f79e4a949033c7343b2": 3, | ||||
|             "5cc86840d7f00c002412c56c": 3, | ||||
|             "5cc80f8fe4a949033b0224a2": 1, | ||||
|             "5cc80f53e4a949000e1ea4f8": 1 | ||||
|         }, | ||||
|         "Caliber68x51": { | ||||
|             "6529302b8c26af6326029fb7": 1 | ||||
|         }, | ||||
|         "Caliber762x25TT": { | ||||
|             "573602322459776445391df1": 2, | ||||
|             "573601b42459776410737435": 2, | ||||
|             "5735fdcd2459776445391d61": 1, | ||||
|             "5736026a245977644601dc61": 1 | ||||
|         }, | ||||
|         "Caliber762x35": { | ||||
|             "6196365d58ef8c428c287da1": 1, | ||||
|             "6196364158ef8c428c287d9f": 6, | ||||
|             "5fbe3ffdf8b6a877a729ea82": 3 | ||||
|         }, | ||||
|         "Caliber762x39": { | ||||
|             "59e4d3d286f774176a36250a": 2, | ||||
|             "64b7af734b75259c590fa895": 2, | ||||
|             "64b7af5a8532cf95ee0a0dbd": 6, | ||||
|             "59e4d24686f7741776641ac7": 4, | ||||
|             "59e4cf5286f7741778269d8a": 2, | ||||
|             "5656d7c34bdc2d9d198b4587": 1 | ||||
|         }, | ||||
|         "Caliber762x51": { | ||||
|             "5e023e88277cce2b522ff2b1": 2, | ||||
|             "5e023e6e34d52a55c3304f71": 2, | ||||
|             "5e023e53d4353e3302577c4c": 1 | ||||
|         }, | ||||
|         "Caliber762x54R": { | ||||
|             "64b8f7c241772715af0f9c3d": 2, | ||||
|             "64b8f7b5389d7ffd620ccba2": 2, | ||||
|             "64b8f7968532cf95ee0a0dbf": 2, | ||||
|             "5e023cf8186a883be655e54f": 2, | ||||
|             "5887431f2459777e1612938f": 1 | ||||
|         }, | ||||
|         "Caliber86x70": { | ||||
|             "5fc382b6d6fa9c00c571bbc3": 2, | ||||
|             "5fc382c1016cce60e8341b20": 1 | ||||
|         }, | ||||
|         "Caliber9x18PM": { | ||||
|             "5737218f245977612125ba51": 5, | ||||
|             "57372140245977611f70ee91": 5, | ||||
|             "5737207f24597760ff7b25f2": 2, | ||||
|             "573719762459775a626ccbc1": 3, | ||||
|             "57371f8d24597761006c6a81": 3, | ||||
|             "57371f2b24597761224311f1": 5, | ||||
|             "57371eb62459776125652ac1": 1, | ||||
|             "57371b192459775a9f58a5e0": 1, | ||||
|             "57371e4124597760ff7b25f1": 1 | ||||
|         }, | ||||
|         "Caliber9x19PARA": { | ||||
|             "5efb0e16aeb21837e749c7ff": 1, | ||||
|             "58864a4f2459770fcc257101": 7, | ||||
|             "5a3c16fe86f77452b62de32a": 12, | ||||
|             "5c3df7d588a4501f290594e5": 6, | ||||
|             "64b7bbb74b75259c590fa897": 4, | ||||
|             "56d59d3ad2720bdb418b4577": 2 | ||||
|         }, | ||||
|         "Caliber9x21": { | ||||
|             "5a26ac06c4a282000c5a90a8": 5, | ||||
|             "5a26abfac4a28232980eabff": 3, | ||||
|             "5a269f97c4a282000b151807": 1 | ||||
|         }, | ||||
|         "Caliber9x33R": { | ||||
|             "62330c40bdd19b369e1e53d1": 5, | ||||
|             "62330bfadc5883093563729b": 3, | ||||
|             "62330c18744e5e31df12f516": 1 | ||||
|         }, | ||||
|         "Caliber9x39": { | ||||
|             "6576f96220d53a5b8f3e395e": 7, | ||||
|             "57a0dfb82459774d3078b56c": 5, | ||||
|             "5c0d668f86f7747ccb7f13b2": 1 | ||||
|         }, | ||||
|         "Caliber127x33": { | ||||
|             "66a0d1c87d0d369e270bb9de": 10, | ||||
|             "66a0d1f88486c69fce00fdf6": 1 | ||||
|         } | ||||
|     }, | ||||
|     "pmcAmmo": { | ||||
|         "Caliber1143x23ACP": { | ||||
|             "5ea2a8e200685063ec28c05a": 1, | ||||
|             "5efb0fc6aeb21837e749c801": 8, | ||||
|             "5efb0d4f4bc50b58e81710f3": 40, | ||||
|             "5e81f423763d9f754677bf2e": 15 | ||||
|         }, | ||||
|         "Caliber127x55": { | ||||
|             "5cadf6e5ae921500113bb973": 45 | ||||
|         }, | ||||
|         "Caliber12g": { | ||||
|             "5d6e6806a4b936088465b17e": 10, | ||||
|             "5c0d591486f7744c505b416f": 3, | ||||
|             "5d6e68d1a4b93622fe60e845": 3, | ||||
|             "5d6e6869a4b9361c140bcfde": 2, | ||||
|             "5d6e68b3a4b9361bca7e50b5": 4, | ||||
|             "58820d1224597753c90aeb13": 6, | ||||
|             "5d6e68dea4b9361bcc29e659": 8, | ||||
|             "5d6e6891a4b9361bd473feea": 12, | ||||
|             "5d6e68e6a4b9361c140bcfe0": 12, | ||||
|             "5d6e689ca4b9361bc8618956": 9 | ||||
|         }, | ||||
|         "Caliber20g": { | ||||
|             "5d6e695fa4b936359b35d852": 8, | ||||
|             "5d6e69b9a4b9361bc8618958": 8, | ||||
|             "5a38ebd9c4a282000d722a5b": 8, | ||||
|             "5d6e69c7a4b9360b6c0d54e4": 10, | ||||
| 
 | ||||
|             "5d6e6a5fa4b93614ec501745": 3, | ||||
|             "5d6e6a53a4b9361bd473feec": 3 | ||||
|         }, | ||||
|         "Caliber23x75": { | ||||
|             "5f647f31b6238e5dd066e196": 10, | ||||
|             "5e85a9a6eacf8c039e4e2ac1": 2 | ||||
|         }, | ||||
|         "Caliber366TKM": { | ||||
|             "59e6658b86f77411d949b250": 20, | ||||
|             "59e6542b86f77411dc52a77a": 25, | ||||
|             "59e655cb86f77411dc52a77b": 8 | ||||
|         }, | ||||
|         "Caliber40mmRU": { | ||||
|             "5656eb674bdc2d35148b457c": 1 | ||||
|         }, | ||||
|         "Caliber40x46": { | ||||
|             "5ede4739e0350d05467f73e8": 1, | ||||
|             "5ede47405b097655935d7d16": 1, | ||||
|             "5ede474b0c226a66f5402622": 1, | ||||
|             "5ede475339ee016e8c534742": 1, | ||||
|             "5ede475b549eed7c6d5c18fb": 1, | ||||
|             "5f0c892565703e5c461894e9": 1 | ||||
|         }, | ||||
|         "Caliber46x30": { | ||||
|             "5ba26812d4351e003201fef1": 50, | ||||
|             "5ba26844d4351e00334c9475": 50 | ||||
|         }, | ||||
|         "Caliber545x39": { | ||||
|             "56dff216d2720bbd668b4568": 1, | ||||
|             "56dff338d2720bbd668b4569": 10, | ||||
|             "56dff421d2720b5f5a8b4567": 10, | ||||
|             "56dff4ecd2720b5f5a8b4568": 15, | ||||
|             "56dff4a2d2720bbd668b456a": 15, | ||||
|             "56dff0bed2720bb0668b4567": 35, | ||||
|             "56dff3afd2720bba668b4567": 45 | ||||
|         }, | ||||
|         "Caliber556x45NATO": { | ||||
|             "59e6927d86f77411da468256": 10, | ||||
|             "59e6918f86f7746c9f75e849": 20, | ||||
|             "59e68f6f86f7746c9f75e846": 45, | ||||
|             "59e6920f86f77411d82aa167": 50, | ||||
|             "54527a984bdc2d4e668b4567": 20 | ||||
|         }, | ||||
|         "Caliber57x28": { | ||||
|             "5cc86832d7f00c000d3a6e6c": 10, | ||||
|             "5cc80f79e4a949033c7343b2": 19, | ||||
|             "5cc86840d7f00c002412c56c": 24, | ||||
|             "5cc80f8fe4a949033b0224a2": 13, | ||||
|             "5cc80f53e4a949000e1ea4f8": 9 | ||||
|         }, | ||||
|         "Caliber68x51": { | ||||
|             "6529302b8c26af6326029fb7": 1 | ||||
|         }, | ||||
|         "Caliber762x25TT": { | ||||
|             "573602322459776445391df1": 6, | ||||
|             "573601b42459776410737435": 10, | ||||
|             "5735fdcd2459776445391d61": 18, | ||||
|             "5736026a245977644601dc61": 10, | ||||
|             "573603c924597764442bd9cb": 4, | ||||
|             "573603562459776430731618": 1 | ||||
|         }, | ||||
|         "Caliber762x35": { | ||||
|             "6196365d58ef8c428c287da1": 9, | ||||
|             "6196364158ef8c428c287d9f": 19, | ||||
|             "5fbe3ffdf8b6a877a729ea82": 14 | ||||
|         }, | ||||
|         "Caliber762x39": { | ||||
|             "59e4d3d286f774176a36250a": 3, | ||||
|             "64b7af734b75259c590fa895": 10, | ||||
|             "64b7af5a8532cf95ee0a0dbd": 20, | ||||
|             "59e4d24686f7741776641ac7": 25, | ||||
|             "59e4cf5286f7741778269d8a": 35, | ||||
|             "5656d7c34bdc2d9d198b4587": 15 | ||||
|         }, | ||||
|         "Caliber762x51": { | ||||
|             "5e023e88277cce2b522ff2b1": 10, | ||||
|             "5e023e6e34d52a55c3304f71": 40, | ||||
|             "5e023e53d4353e3302577c4c": 50 | ||||
|         }, | ||||
|         "Caliber762x54R": { | ||||
|             "64b8f7c241772715af0f9c3d": 9, | ||||
|             "64b8f7b5389d7ffd620ccba2": 14, | ||||
|             "64b8f7968532cf95ee0a0dbf": 16, | ||||
|             "5e023cf8186a883be655e54f": 20, | ||||
|             "5887431f2459777e1612938f": 14 | ||||
|         }, | ||||
|         "Caliber86x70": { | ||||
|             "5fc382b6d6fa9c00c571bbc3": 95, | ||||
|             "5fc382c1016cce60e8341b20": 5 | ||||
|         }, | ||||
|         "Caliber9x18PM": { | ||||
|             "5737218f245977612125ba51": 2, | ||||
|             "57372140245977611f70ee91": 6, | ||||
|             "5737207f24597760ff7b25f2": 6, | ||||
|             "573719762459775a626ccbc1": 6, | ||||
|             "57371f8d24597761006c6a81": 9, | ||||
|             "57371f2b24597761224311f1": 9, | ||||
|             "57371eb62459776125652ac1": 9, | ||||
|             "57371b192459775a9f58a5e0": 18, | ||||
|             "57371e4124597760ff7b25f1": 23, | ||||
|             "5737201124597760fc4431f1": 18, | ||||
|             "573720e02459776143012541": 9, | ||||
|             "573718ba2459775a75491131": 6 | ||||
|         }, | ||||
|         "Caliber9x19PARA": { | ||||
|             "5c0d56a986f774449d5de529": 1, | ||||
|             "5efb0e16aeb21837e749c7ff": 7, | ||||
|             "58864a4f2459770fcc257101": 20, | ||||
|             "5a3c16fe86f77452b62de32a": 30, | ||||
|             "5c3df7d588a4501f290594e5": 40, | ||||
|             "64b7bbb74b75259c590fa897": 40, | ||||
|             "56d59d3ad2720bdb418b4577": 25 | ||||
|         }, | ||||
|         "Caliber9x21": { | ||||
|             "5a26ac06c4a282000c5a90a8": 9, | ||||
|             "5a26abfac4a28232980eabff": 22, | ||||
|             "5a269f97c4a282000b151807": 17 | ||||
|         }, | ||||
|         "Caliber9x33R": { | ||||
|             "62330c40bdd19b369e1e53d1": 15, | ||||
|             "62330bfadc5883093563729b": 12 | ||||
|         }, | ||||
|         "Caliber9x39": { | ||||
|             "6576f96220d53a5b8f3e395e": 19, | ||||
|             "57a0dfb82459774d3078b56c": 27, | ||||
|             "5c0d668f86f7747ccb7f13b2": 13 | ||||
|         }, | ||||
|         "Caliber127x33": { | ||||
|             "66a0d1c87d0d369e270bb9de": 50, | ||||
|             "66a0d1f88486c69fce00fdf6": 30 | ||||
|         } | ||||
|     }, | ||||
|     "bossAmmo": { | ||||
|         "Caliber1143x23ACP": { | ||||
|             "5ea2a8e200685063ec28c05a": 4, | ||||
|             "5efb0fc6aeb21837e749c801": 1, | ||||
|             "5efb0d4f4bc50b58e81710f3": 10, | ||||
|             "5e81f423763d9f754677bf2e": 18, | ||||
|             "5efb0cabfb3e451d70735af5": 10 | ||||
|         }, | ||||
|         "Caliber127x55": { | ||||
|             "5cadf6e5ae921500113bb973": 3, | ||||
|             "5cadf6ddae9215051e1c23b2": 12, | ||||
|             "5cadf6eeae921500134b2799": 8 | ||||
|         }, | ||||
|         "Caliber12g": { | ||||
|             "5d6e6806a4b936088465b17e": 7, | ||||
|             "64b8ee384b75259c590fa89b": 4, | ||||
|             "5d6e6911a4b9361bd5780d52": 3, | ||||
|             "5c0d591486f7744c505b416f": 5, | ||||
|             "5d6e6891a4b9361bd473feea": 2, | ||||
|             "5d6e68e6a4b9361c140bcfe0": 6, | ||||
|             "5d6e689ca4b9361bc8618956": 8, | ||||
|             "5d6e68c4a4b9361b93413f79": 8, | ||||
|             "5d6e68a8a4b9360b6c0d54e2": 3 | ||||
|         }, | ||||
|         "Caliber20g": { | ||||
|             "5d6e69c7a4b9360b6c0d54e4": 1, | ||||
|             "5d6e6a53a4b9361bd473feec": 4, | ||||
|             "5d6e6a05a4b93618084f58d0": 5, | ||||
|             "5d6e6a42a4b9364f07165f52": 5 | ||||
|         }, | ||||
|         "Caliber23x75": { | ||||
|             "5f647f31b6238e5dd066e196": 2, | ||||
|             "5e85a9a6eacf8c039e4e2ac1": 4, | ||||
|             "5e85aa1a988a8701445df1f5": 4 | ||||
|         }, | ||||
|         "Caliber366TKM": { | ||||
|             "59e6658b86f77411d949b250": 1, | ||||
|             "59e6542b86f77411dc52a77a": 2, | ||||
|             "59e655cb86f77411dc52a77b": 10, | ||||
|             "5f0596629e22f464da6bbdd9": 8 | ||||
|         }, | ||||
|         "Caliber40mmRU": { | ||||
|             "5656eb674bdc2d35148b457c": 1 | ||||
|         }, | ||||
|         "Caliber40x46": { | ||||
|             "5ede4739e0350d05467f73e8": 1, | ||||
|             "5ede47405b097655935d7d16": 1, | ||||
|             "5ede474b0c226a66f5402622": 1, | ||||
|             "5ede475339ee016e8c534742": 1, | ||||
|             "5ede475b549eed7c6d5c18fb": 1, | ||||
|             "5f0c892565703e5c461894e9": 1 | ||||
|         }, | ||||
|         "Caliber46x30": { | ||||
|             "5ba26812d4351e003201fef1": 2, | ||||
|             "5ba26844d4351e00334c9475": 4, | ||||
|             "5ba2678ad4351e44f824b344": 15, | ||||
|             "64b6979341772715af0f9c39": 15, | ||||
|             "5ba26835d4351e0035628ff5": 8 | ||||
|         }, | ||||
|         "Caliber545x39": { | ||||
|             "56dff3afd2720bba668b4567": 6, | ||||
|             "56dff2ced2720bb4668b4567": 12, | ||||
|             "56dff061d2720bb5668b4567": 20, | ||||
|             "61962b617c6c7b169525f168": 12, | ||||
|             "56dfef82d2720bbd668b4567": 9, | ||||
|             "56dff026d2720bb8668b4567": 8, | ||||
|             "5c0d5e4486f77478390952fe": 4 | ||||
|         }, | ||||
|         "Caliber556x45NATO": { | ||||
|             "5c0d5ae286f7741e46554302": 1, | ||||
|             "54527a984bdc2d4e668b4567": 7, | ||||
|             "60194943740c5d77f6705eea": 20, | ||||
|             "59e6906286f7746c9f75e847": 26, | ||||
|             "54527ac44bdc2d36668b4567": 30, | ||||
|             "59e690b686f7746c9f75e848": 7, | ||||
|             "601949593ae8f707c4608daa": 5 | ||||
|         }, | ||||
|         "Caliber57x28": { | ||||
|             "5cc80f8fe4a949033b0224a2": 5, | ||||
|             "5cc80f53e4a949000e1ea4f8": 21, | ||||
|             "5cc80f67e4a949035e43bbba": 15, | ||||
|             "5cc80f38e4a949001152b560": 12 | ||||
|         }, | ||||
|         "Caliber68x51": { | ||||
|             "6529302b8c26af6326029fb7": 10, | ||||
|             "6529243824cbe3c74a05e5c1": 5 | ||||
|         }, | ||||
|         "Caliber762x25TT": { | ||||
|             "5736026a245977644601dc61": 5, | ||||
|             "573603c924597764442bd9cb": 10, | ||||
|             "573603562459776430731618": 10 | ||||
|         }, | ||||
|         "Caliber762x35": { | ||||
|             "6196365d58ef8c428c287da1": 7, | ||||
|             "5fbe3ffdf8b6a877a729ea82": 6, | ||||
|             "619636be6db0f2477964e710": 23, | ||||
|             "64b8725c4b75259c590fa899": 20, | ||||
|             "5fd20ff893a8961fc660a954": 9 | ||||
|         }, | ||||
|         "Caliber762x39": { | ||||
|             "59e4cf5286f7741778269d8a": 4, | ||||
|             "5656d7c34bdc2d9d198b4587": 28, | ||||
|             "64b7af434b75259c590fa893": 33, | ||||
|             "59e0d99486f7744a32234762": 20, | ||||
|             "601aa3d2b2bcb34913271e6d": 12 | ||||
|         }, | ||||
|         "Caliber762x51": { | ||||
|             "5e023e53d4353e3302577c4c": 6, | ||||
|             "58dd3ad986f77403051cba8f": 27, | ||||
|             "5a608bf24f39f98ffc77720e": 19, | ||||
|             "5a6086ea4f39f99cd479502f": 9, | ||||
|             "5efb0c1bd79ff02a1f5e68d9": 2 | ||||
|         }, | ||||
|         "Caliber762x54R": { | ||||
|             "5e023cf8186a883be655e54f": 3, | ||||
|             "5887431f2459777e1612938f": 20, | ||||
|             "59e77a2386f7742ee578960a": 25, | ||||
|             "5e023d34e8a400319a28ed44": 22, | ||||
|             "560d61e84bdc2da74d8b4571": 15, | ||||
|             "5e023d48186a883be655e551": 10 | ||||
|         }, | ||||
|         "Caliber86x70": { | ||||
|             "5fc382b6d6fa9c00c571bbc3": 5, | ||||
|             "5fc382c1016cce60e8341b20": 8, | ||||
|             "5fc275cf85fd526b824a571a": 8, | ||||
|             "5fc382a9d724d907e2077dab": 5 | ||||
|         }, | ||||
|         "Caliber9x18PM": { | ||||
|             "57371e4124597760ff7b25f1": 3, | ||||
|             "5737201124597760fc4431f1": 5, | ||||
|             "573720e02459776143012541": 12, | ||||
|             "573718ba2459775a75491131": 18, | ||||
|             "57371aab2459775a77142f22": 12, | ||||
|             "573719df2459775a626ccbc2": 10 | ||||
|         }, | ||||
|         "Caliber9x19PARA": { | ||||
|             "5c0d56a986f774449d5de529": 9, | ||||
|             "5efb0e16aeb21837e749c7ff": 5, | ||||
|             "5a3c16fe86f77452b62de32a": 4, | ||||
|             "56d59d3ad2720bdb418b4577": 18, | ||||
|             "5c925fa22e221601da359b7b": 22, | ||||
|             "5efb0da7a29a85116f6ea05f": 9 | ||||
|         }, | ||||
|         "Caliber9x21": { | ||||
|             "5a269f97c4a282000b151807": 8, | ||||
|             "6576f93989f0062e741ba952": 18, | ||||
|             "5a26ac0ec4a28200741e1e18": 18, | ||||
|             "6576f4708ca9c4381d16cd9d": 8 | ||||
|         }, | ||||
|         "Caliber9x33R": { | ||||
|             "62330c18744e5e31df12f516": 9, | ||||
|             "62330b3ed4dc74626d570b95": 6 | ||||
|         }, | ||||
|         "Caliber9x39": { | ||||
|             "5c0d668f86f7747ccb7f13b2": 9, | ||||
|             "61962d879bb3d20b0946d385": 25, | ||||
|             "57a0e5022459774d1673f889": 25, | ||||
|             "5c0d688c86f77413ae3407b2": 12 | ||||
|         }, | ||||
|         "Caliber127x33": { | ||||
|             "66a0d1c87d0d369e270bb9de": 3, | ||||
|             "66a0d1f88486c69fce00fdf6": 30, | ||||
|             "66a0d1e0ed648d72fe064d06": 25,  | ||||
|             "668fe62ac62660a5d8071446": 12 | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,411 @@ | |||
| { | ||||
|     "pmcUSEC": { | ||||
|         "appearance": { | ||||
|             "body": { | ||||
|                 "5cde95d97d6c8b647a3769b0": 5, | ||||
|                 "66546f823b51a4d21e0d17d7": 1, | ||||
|                 "5d1f56a686f7744bce0ee9eb": 2 | ||||
|             }, | ||||
|             "feet": { | ||||
|                 "5cde95ef7d6c8b04713c4f2d": 5, | ||||
|                 "5d1f58ed86f7744bcb0acd1c": 1 | ||||
|             }, | ||||
|             "hands": { | ||||
|                 "5cde95fa7d6c8b04737c2d13": 1 | ||||
|             }, | ||||
|             "head": { | ||||
|                 "5cde96047d6c8b20b577f016": 1, | ||||
|                 "5fdb4139e4ed5b5ea251e4ed": 1, | ||||
|                 "5fdb5950f5264a66150d1c6e": 1, | ||||
|                 "60a6aa8fd559ae040d0d951f": 1, | ||||
|                 "619f9e338858a474c8685cc9": 1, | ||||
|                 "62aca6a1310e67685a2fc2e7": 1, | ||||
|                 "6574aabee0423b9ebe0c79cf": 1 | ||||
|             } | ||||
|         } | ||||
|     }, | ||||
|     "pmcBEAR": { | ||||
|         "appearance": { | ||||
|             "body": { | ||||
|                 "5cc0858d14c02e000c6bea66": 5, | ||||
|                 "66546f823b51a4d21e0d17d7": 1, | ||||
|                 "5d1f565786f7743f8362bcd5": 2 | ||||
|             }, | ||||
|             "feet": { | ||||
|                 "5cc085bb14c02e000e67a5c5": 5, | ||||
|                 "5d1f58bd86f7744bce0ee9ef": 1 | ||||
|             }, | ||||
|             "hands": { | ||||
|                 "5cc0876314c02e000c6bea6b": 1 | ||||
|             }, | ||||
|             "head": { | ||||
|                 "5cc084dd14c02e000b0550a3": 1, | ||||
|                 "5fdb50bb2b730a787b3f78cf": 1, | ||||
|                 "5fdb7571e4ed5b5ea251e529": 1, | ||||
|                 "60a6aaad42fd2735e4589978": 1, | ||||
|                 "619f94f5b90286142b59d45f": 1, | ||||
|                 "62a9e7d15ea3b87d6f642a28": 1, | ||||
|                 "6574aa9a1b144de18c0fba45": 1 | ||||
|             } | ||||
|         } | ||||
|     }, | ||||
|     "springEarly": { | ||||
|         "pmcUSEC": { | ||||
|             "appearance": { | ||||
|                 "body": { | ||||
|                     "5d1f56c686f7744bcd13459c": 1, | ||||
|                     "5fd3e9f71b735718c25cd9f8": 1, | ||||
|                     "66043728333907134309d647": 1, | ||||
|                     "66acbe49dc61999a6a03d4d6": 1, | ||||
|                     "660437e57502eca33a08caca": 1, | ||||
|                     "5d1f56f186f7744bcb0acd1a": 1, | ||||
|                     "5d1f56ff86f7743f8362bcd7": 1, | ||||
|                     "5d1f56a686f7744bce0ee9eb": 2, | ||||
|                     "5e9da17386f774054b6f79a3": 2, | ||||
|                     "5e4bb35286f77406a511c9bc": 2, | ||||
|                     "5d1f56e486f7744bce0ee9ed": 2 | ||||
|                 }, | ||||
|                 "feet": { | ||||
|                     "642d4d8eb6b75d4c89077cf9": 1, | ||||
|                     "5fcf940bce1ba36a513bb9cc": 1, | ||||
|                     "66acc8f719271bd6d00dec0b": 1, | ||||
|                     "6295e944e9de5e7b3751c4da": 1, | ||||
|                     "5d1f592286f7743f8362bcdb": 1, | ||||
|                     "5e4bb3b586f77406812bd579": 1, | ||||
|                     "5d1f590486f7744bcd13459e": 3, | ||||
|                     "5d1f58ed86f7744bcb0acd1c": 3 | ||||
|                 }, | ||||
|                 "hands": { | ||||
|                     "5cde95fa7d6c8b04737c2d13": 1 | ||||
|                 }, | ||||
|                 "head": { | ||||
|                     "5cde96047d6c8b20b577f016": 1, | ||||
|                     "5fdb4139e4ed5b5ea251e4ed": 1, | ||||
|                     "5fdb5950f5264a66150d1c6e": 1, | ||||
|                     "60a6aa8fd559ae040d0d951f": 1, | ||||
|                     "619f9e338858a474c8685cc9": 1, | ||||
|                     "62aca6a1310e67685a2fc2e7": 1, | ||||
|                     "6574aabee0423b9ebe0c79cf": 1 | ||||
|                 } | ||||
|             } | ||||
|         }, | ||||
|         "pmcBEAR": { | ||||
|             "appearance": { | ||||
|                 "body": { | ||||
|                     "657058fddf9b3231400e9188": 1, | ||||
|                     "6033a31e9ec839204e6a2f3e": 1, | ||||
|                     "5d1f567786f7744bcc04874f": 1, | ||||
|                     "5e9d9fa986f774054d6b89f2": 1, | ||||
|                     "5f5e401747344c2e4f6c42c5": 1, | ||||
|                     "642e8ae07e17c882400c4f87": 2, | ||||
|                     "5d1f568486f7744bca3f0b98": 2, | ||||
|                     "66acec1dc94f4bf5bc063a16": 2, | ||||
|                     "5e4bb31586f7740695730568": 2 | ||||
|                 }, | ||||
|                 "feet": { | ||||
|                     "5d1f58bd86f7744bce0ee9ef": 1, | ||||
|                     "6377315993a3b4967208e437": 1, | ||||
|                     "66043cf87502eca33a08cad2": 1, | ||||
|                     "5d1f58cb86f7744bca3f0b9a": 1, | ||||
|                     "5d1f58a086f7743f8362bcd9": 1, | ||||
|                     "617be9e4e02b3b3fa50fa8f2": 1, | ||||
|                     "5f5e40400bc58666c37e7819": 1, | ||||
|                     "66acebd4ede86671bb09584b": 3, | ||||
|                     "5d1f58ab86f7743014162042": 3 | ||||
|                 }, | ||||
|                 "hands": { | ||||
|                     "5cc0876314c02e000c6bea6b": 1 | ||||
|                 }, | ||||
|                 "head": { | ||||
|                     "5cc084dd14c02e000b0550a3": 1, | ||||
|                     "5fdb50bb2b730a787b3f78cf": 1, | ||||
|                     "5fdb7571e4ed5b5ea251e529": 1, | ||||
|                     "60a6aaad42fd2735e4589978": 1, | ||||
|                     "619f94f5b90286142b59d45f": 1, | ||||
|                     "62a9e7d15ea3b87d6f642a28": 1, | ||||
|                     "6574aa9a1b144de18c0fba45": 1 | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     }, | ||||
|     "spring": { | ||||
|         "pmcUSEC": { | ||||
|             "appearance": { | ||||
|                 "body": { | ||||
|                     "5cde95d97d6c8b647a3769b0": 1, | ||||
|                     "5fd3e9f71b735718c25cd9f8": 1, | ||||
|                     "66043728333907134309d647": 1, | ||||
|                     "5d4da0cb86f77450fe0a6629": 1, | ||||
|                     "5d1f56f186f7744bcb0acd1a": 1, | ||||
|                     "5f5e4075df4f3100376a8138": 1 | ||||
|                 }, | ||||
|                 "feet": { | ||||
|                     "5cde95ef7d6c8b04713c4f2d": 1, | ||||
|                     "6033a3fee29c9f6c9b14e74e": 1, | ||||
|                     "660436487502eca33a08cac8": 1, | ||||
|                     "6571cad4c8673f00290f5657": 1, | ||||
|                     "66acc8f719271bd6d00dec0b": 1, | ||||
|                     "5d1f592286f7743f8362bcdb": 1, | ||||
|                     "642d6941ff5ecad7810a8a61": 1, | ||||
|                     "5e9dcadd86f7743e20652f23": 1 | ||||
|                 }, | ||||
|                 "hands": { | ||||
|                     "5cde95fa7d6c8b04737c2d13": 1 | ||||
|                 }, | ||||
|                 "head": { | ||||
|                     "5cde96047d6c8b20b577f016": 1, | ||||
|                     "5fdb4139e4ed5b5ea251e4ed": 1, | ||||
|                     "5fdb5950f5264a66150d1c6e": 1, | ||||
|                     "60a6aa8fd559ae040d0d951f": 1, | ||||
|                     "619f9e338858a474c8685cc9": 1, | ||||
|                     "62aca6a1310e67685a2fc2e7": 1, | ||||
|                     "6574aabee0423b9ebe0c79cf": 1 | ||||
|                 } | ||||
|             } | ||||
|         }, | ||||
|         "pmcBEAR": { | ||||
|             "appearance": { | ||||
|                 "body": { | ||||
|                     "5cc0858d14c02e000c6bea66": 1, | ||||
|                     "5d1f564b86f7744bcb0acd16": 1, | ||||
|                     "6295e698e9de5e7b3751c47a": 1, | ||||
|                     "6033a31e9ec839204e6a2f3e": 1, | ||||
|                     "5fce3e47fe40296c1d5fd784": 1, | ||||
|                     "617bca4b4013b06b0b78df2a": 1, | ||||
|                     "5df89f1f86f77412631087ea": 1 | ||||
|                 }, | ||||
|                 "feet": { | ||||
|                     "5cc085bb14c02e000e67a5c5": 1, | ||||
|                     "5d1f588e86f7744bcc048753": 1, | ||||
|                     "66043cf87502eca33a08cad2": 1, | ||||
|                     "6033a3d8ed2e0509b15f9031": 1, | ||||
|                     "642e71620a69698d1b049f0a": 1, | ||||
|                     "617be9e4e02b3b3fa50fa8f2": 1, | ||||
|                     "642eea6f881906a7fe086841": 1, | ||||
|                     "5df89f8f86f77412672a1e38": 1, | ||||
|                     "5e9dc97c86f774054c19ac9a": 1, | ||||
|                     "5e4bb39386f774067f79de05": 1 | ||||
|                 }, | ||||
|                 "hands": { | ||||
|                     "5cc0876314c02e000c6bea6b": 1 | ||||
|                 }, | ||||
|                 "head": { | ||||
|                     "5cc084dd14c02e000b0550a3": 1, | ||||
|                     "5fdb50bb2b730a787b3f78cf": 1, | ||||
|                     "5fdb7571e4ed5b5ea251e529": 1, | ||||
|                     "60a6aaad42fd2735e4589978": 1, | ||||
|                     "619f94f5b90286142b59d45f": 1, | ||||
|                     "62a9e7d15ea3b87d6f642a28": 1, | ||||
|                     "6574aa9a1b144de18c0fba45": 1 | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     }, | ||||
|     "summer": { | ||||
|         "pmcUSEC": { | ||||
|             "appearance": { | ||||
|                 "body": { | ||||
|                     "5cde95d97d6c8b647a3769b0": 1, | ||||
|                     "5d1f56c686f7744bcd13459c": 1, | ||||
|                     "5fd3e9f71b735718c25cd9f8": 1, | ||||
|                     "66043728333907134309d647": 1, | ||||
|                     "5d4da0cb86f77450fe0a6629": 1, | ||||
|                     "66acbe49dc61999a6a03d4d6": 1, | ||||
|                     "64ef3efdb63b74469b6c1499": 1, | ||||
|                     "642c18b8a6a0660b560fb31c": 1, | ||||
|                     "5d1f56f186f7744bcb0acd1a": 1, | ||||
|                     "5f5e4075df4f3100376a8138": 1 | ||||
|                 }, | ||||
|                 "feet": { | ||||
|                     "5cde95ef7d6c8b04713c4f2d": 1, | ||||
|                     "6033a3fee29c9f6c9b14e74e": 1, | ||||
|                     "660436487502eca33a08cac8": 1, | ||||
|                     "6571cad4c8673f00290f5657": 1, | ||||
|                     "66acc8f719271bd6d00dec0b": 1, | ||||
|                     "5d1f593286f7743014162044": 1, | ||||
|                     "5d1f592286f7743f8362bcdb": 1, | ||||
|                     "642d6941ff5ecad7810a8a61": 1, | ||||
|                     "5e9dcadd86f7743e20652f23": 1 | ||||
|                 }, | ||||
|                 "hands": { | ||||
|                     "5cde95fa7d6c8b04737c2d13": 1 | ||||
|                 }, | ||||
|                 "head": { | ||||
|                     "5cde96047d6c8b20b577f016": 1, | ||||
|                     "5fdb4139e4ed5b5ea251e4ed": 1, | ||||
|                     "5fdb5950f5264a66150d1c6e": 1, | ||||
|                     "60a6aa8fd559ae040d0d951f": 1, | ||||
|                     "619f9e338858a474c8685cc9": 1, | ||||
|                     "62aca6a1310e67685a2fc2e7": 1, | ||||
|                     "6574aabee0423b9ebe0c79cf": 1 | ||||
|                 } | ||||
|             } | ||||
|         }, | ||||
|         "pmcBEAR": { | ||||
|             "appearance": { | ||||
|                 "body": { | ||||
|                     "5cc0858d14c02e000c6bea66": 1, | ||||
|                     "5d1f564b86f7744bcb0acd16": 1, | ||||
|                     "6295e698e9de5e7b3751c47a": 1, | ||||
|                     "6033a31e9ec839204e6a2f3e": 1, | ||||
|                     "5fce3e47fe40296c1d5fd784": 1, | ||||
|                     "617bca4b4013b06b0b78df2a": 1, | ||||
|                     "64ef3efdb63b74469b6c1499": 1, | ||||
|                     "5df89f1f86f77412631087ea": 1, | ||||
|                     "5e9d9fa986f774054d6b89f2": 1 | ||||
|                 }, | ||||
|                 "feet": { | ||||
|                     "5cc085bb14c02e000e67a5c5": 1, | ||||
|                     "5d1f588e86f7744bcc048753": 1, | ||||
|                     "66043cf87502eca33a08cad2": 1, | ||||
|                     "6033a3d8ed2e0509b15f9031": 1, | ||||
|                     "642e71620a69698d1b049f0a": 1, | ||||
|                     "617be9e4e02b3b3fa50fa8f2": 1, | ||||
|                     "642eea6f881906a7fe086841": 1, | ||||
|                     "5df89f8f86f77412672a1e38": 1, | ||||
|                     "5e9dc97c86f774054c19ac9a": 1, | ||||
|                     "5e4bb39386f774067f79de05": 1 | ||||
|                 }, | ||||
|                 "hands": { | ||||
|                     "5cc0876314c02e000c6bea6b": 1 | ||||
|                 }, | ||||
|                 "head": { | ||||
|                     "5cc084dd14c02e000b0550a3": 1, | ||||
|                     "5fdb50bb2b730a787b3f78cf": 1, | ||||
|                     "5fdb7571e4ed5b5ea251e529": 1, | ||||
|                     "60a6aaad42fd2735e4589978": 1, | ||||
|                     "619f94f5b90286142b59d45f": 1, | ||||
|                     "62a9e7d15ea3b87d6f642a28": 1, | ||||
|                     "6574aa9a1b144de18c0fba45": 1 | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     }, | ||||
|     "autumn": { | ||||
|         "pmcUSEC": { | ||||
|             "appearance": { | ||||
|                 "body": { | ||||
|                     "5d1f56c686f7744bcd13459c": 1, | ||||
|                     "637b945722e2a933ed0e33c8": 1, | ||||
|                     "6571cb0923aa6d72760a7f8f": 1, | ||||
|                     "6033a35f80ae5e2f970ba6bb": 1, | ||||
|                     "5d1f56e486f7744bce0ee9ed": 1, | ||||
|                     "66acbe49dc61999a6a03d4d6": 1, | ||||
|                     "660437e57502eca33a08caca": 1, | ||||
|                     "64ef3efdb63b74469b6c1499": 1, | ||||
|                     "5d1f56ff86f7743f8362bcd7": 1 | ||||
|                 }, | ||||
|                 "feet": { | ||||
|                     "642d4d8eb6b75d4c89077cf9": 1, | ||||
|                     "5fcf940bce1ba36a513bb9cc": 1, | ||||
|                     "637ba17aa10a96c2b605dbc2": 1, | ||||
|                     "6295e944e9de5e7b3751c4da": 1, | ||||
|                     "5e4bb3b586f77406812bd579": 1, | ||||
|                     "5f5e40a06760b4138443b341": 1 | ||||
|                 }, | ||||
|                 "hands": { | ||||
|                     "5cde95fa7d6c8b04737c2d13": 1 | ||||
|                 }, | ||||
|                 "head": { | ||||
|                     "5cde96047d6c8b20b577f016": 1, | ||||
|                     "5fdb4139e4ed5b5ea251e4ed": 1, | ||||
|                     "5fdb5950f5264a66150d1c6e": 1, | ||||
|                     "60a6aa8fd559ae040d0d951f": 1, | ||||
|                     "619f9e338858a474c8685cc9": 1, | ||||
|                     "62aca6a1310e67685a2fc2e7": 1, | ||||
|                     "6574aabee0423b9ebe0c79cf": 1 | ||||
|                 } | ||||
|             } | ||||
|         }, | ||||
|         "pmcBEAR": { | ||||
|             "appearance": { | ||||
|                 "body": { | ||||
|                     "6377266693a3b4967208e42b": 1, | ||||
|                     "5d1f568486f7744bca3f0b98": 1, | ||||
|                     "657058fddf9b3231400e9188": 1, | ||||
|                     "642ed297ac11c9eaf10d87e8": 1, | ||||
|                     "5d1f567786f7744bcc04874f": 1, | ||||
|                     "64ef3efdb63b74469b6c1499": 1, | ||||
|                     "6430119aac11c9eaf10d881b": 1, | ||||
|                     "5f5e401747344c2e4f6c42c5": 1 | ||||
|                 }, | ||||
|                 "feet": { | ||||
|                     "5d1f58bd86f7744bce0ee9ef": 1, | ||||
|                     "6377315993a3b4967208e437": 1, | ||||
|                     "642ed40af5bdf1c04e01952e": 1, | ||||
|                     "6295e63de08ed747e64ae991": 1, | ||||
|                     "5d1f58a086f7743f8362bcd9": 1, | ||||
|                     "66043d7ac8949a435906e434": 1, | ||||
|                     "5d1f58ab86f7743014162042": 1, | ||||
|                     "5f5e40400bc58666c37e7819": 1 | ||||
|                 }, | ||||
|                 "hands": { | ||||
|                     "5cc0876314c02e000c6bea6b": 1 | ||||
|                 }, | ||||
|                 "head": { | ||||
|                     "5cc084dd14c02e000b0550a3": 1, | ||||
|                     "5fdb50bb2b730a787b3f78cf": 1, | ||||
|                     "5fdb7571e4ed5b5ea251e529": 1, | ||||
|                     "60a6aaad42fd2735e4589978": 1, | ||||
|                     "619f94f5b90286142b59d45f": 1, | ||||
|                     "62a9e7d15ea3b87d6f642a28": 1, | ||||
|                     "6574aa9a1b144de18c0fba45": 1 | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     }, | ||||
|     "winter": { | ||||
|         "pmcUSEC": { | ||||
|             "appearance": { | ||||
|                 "body": { | ||||
|                     "5d1f56a686f7744bce0ee9eb": 1, | ||||
|                     "5e9da17386f774054b6f79a3": 1, | ||||
|                     "5e4bb35286f77406a511c9bc": 1, | ||||
|                     "5d1f56e486f7744bce0ee9ed": 1 | ||||
|                 }, | ||||
|                 "feet": { | ||||
|                     "5d1f590486f7744bcd13459e": 1, | ||||
|                     "5d1f58ed86f7744bcb0acd1c": 1 | ||||
|                 }, | ||||
|                 "hands": { | ||||
|                     "5cde95fa7d6c8b04737c2d13": 1 | ||||
|                 }, | ||||
|                 "head": { | ||||
|                     "5cde96047d6c8b20b577f016": 1, | ||||
|                     "5fdb4139e4ed5b5ea251e4ed": 1, | ||||
|                     "5fdb5950f5264a66150d1c6e": 1, | ||||
|                     "60a6aa8fd559ae040d0d951f": 1, | ||||
|                     "619f9e338858a474c8685cc9": 1, | ||||
|                     "62aca6a1310e67685a2fc2e7": 1, | ||||
|                     "6574aabee0423b9ebe0c79cf": 1 | ||||
|                 } | ||||
|             } | ||||
|         }, | ||||
|         "pmcBEAR": { | ||||
|             "appearance": { | ||||
|                 "body": { | ||||
|                     "642e8ae07e17c882400c4f87": 1, | ||||
|                     "5d1f568486f7744bca3f0b98": 1, | ||||
|                     "66acec1dc94f4bf5bc063a16": 1, | ||||
|                     "5e4bb31586f7740695730568": 1 | ||||
|                 }, | ||||
|                 "feet": { | ||||
|                     "66acebd4ede86671bb09584b": 1, | ||||
|                     "5d1f58ab86f7743014162042": 1 | ||||
|                 }, | ||||
|                 "hands": { | ||||
|                     "5cc0876314c02e000c6bea6b": 1 | ||||
|                 }, | ||||
|                 "head": { | ||||
|                     "5cc084dd14c02e000b0550a3": 1, | ||||
|                     "5fdb50bb2b730a787b3f78cf": 1, | ||||
|                     "5fdb7571e4ed5b5ea251e529": 1, | ||||
|                     "60a6aaad42fd2735e4589978": 1, | ||||
|                     "619f94f5b90286142b59d45f": 1, | ||||
|                     "62a9e7d15ea3b87d6f642a28": 1, | ||||
|                     "6574aa9a1b144de18c0fba45": 1 | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							|  | @ -0,0 +1,476 @@ | |||
| {     | ||||
|     "scavAmmo": { | ||||
|         "Caliber1143x23ACP": { | ||||
|             "5efb0fc6aeb21837e749c801": 1, | ||||
|             "5efb0d4f4bc50b58e81710f3": 3 | ||||
|         }, | ||||
|         "Caliber127x55": { | ||||
|             "5cadf6e5ae921500113bb973": 1 | ||||
|         }, | ||||
|         "Caliber12g": { | ||||
|             "5d6e6772a4b936088465b17c": 2, | ||||
|             "5d6e6806a4b936088465b17e": 2, | ||||
|             "5d6e67fba4b9361bc73bc779": 2, | ||||
|             "560d5e524bdc2d25448b4571": 2, | ||||
|             "5d6e6869a4b9361c140bcfde": 1, | ||||
|             "5d6e68b3a4b9361bca7e50b5": 1, | ||||
|             "58820d1224597753c90aeb13": 1, | ||||
|             "5d6e68dea4b9361bcc29e659": 1, | ||||
|             "5d6e6891a4b9361bd473feea": 1, | ||||
|             "5d6e68e6a4b9361c140bcfe0": 1, | ||||
|             "5d6e689ca4b9361bc8618956": 1 | ||||
|         }, | ||||
|         "Caliber20g": { | ||||
|             "5d6e695fa4b936359b35d852": 2, | ||||
|             "5d6e69b9a4b9361bc8618958": 2, | ||||
|             "5a38ebd9c4a282000d722a5b": 2, | ||||
|             "5d6e69c7a4b9360b6c0d54e4": 1, | ||||
|             "5d6e6a53a4b9361bd473feec": 1 | ||||
|         }, | ||||
|         "Caliber23x75": { | ||||
|             "5f647f31b6238e5dd066e196": 3, | ||||
|             "5e85a9a6eacf8c039e4e2ac1": 1 | ||||
|         }, | ||||
|         "Caliber366TKM": { | ||||
|             "59e6658b86f77411d949b250": 3, | ||||
|             "59e6542b86f77411dc52a77a": 1 | ||||
|         }, | ||||
|         "Caliber40mmRU": { | ||||
|             "5656eb674bdc2d35148b457c": 1 | ||||
|         }, | ||||
|         "Caliber40x46": { | ||||
|             "5ede4739e0350d05467f73e8": 1, | ||||
|             "5ede47405b097655935d7d16": 1, | ||||
|             "5ede474b0c226a66f5402622": 1, | ||||
|             "5ede475339ee016e8c534742": 1, | ||||
|             "5ede475b549eed7c6d5c18fb": 1, | ||||
|             "5f0c892565703e5c461894e9": 1 | ||||
|         }, | ||||
|         "Caliber46x30": { | ||||
|             "5ba26812d4351e003201fef1": 3, | ||||
|             "5ba26844d4351e00334c9475": 1 | ||||
|         }, | ||||
|         "Caliber545x39": { | ||||
|             "56dff216d2720bbd668b4568": 1, | ||||
|             "56dff338d2720bbd668b4569": 4, | ||||
|             "56dff421d2720b5f5a8b4567": 4, | ||||
|             "56dff4ecd2720b5f5a8b4568": 2, | ||||
|             "56dff4a2d2720bbd668b456a": 4, | ||||
|             "56dff0bed2720bb0668b4567": 3, | ||||
|             "56dff3afd2720bba668b4567": 1 | ||||
|         }, | ||||
|         "Caliber556x45NATO": { | ||||
|             "59e6927d86f77411da468256": 2, | ||||
|             "59e6918f86f7746c9f75e849": 2, | ||||
|             "59e68f6f86f7746c9f75e846": 4, | ||||
|             "59e6920f86f77411d82aa167": 5, | ||||
|             "54527a984bdc2d4e668b4567": 1 | ||||
|         }, | ||||
|         "Caliber57x28": { | ||||
|             "5cc86832d7f00c000d3a6e6c": 2, | ||||
|             "5cc80f79e4a949033c7343b2": 3, | ||||
|             "5cc86840d7f00c002412c56c": 3, | ||||
|             "5cc80f8fe4a949033b0224a2": 1, | ||||
|             "5cc80f53e4a949000e1ea4f8": 1 | ||||
|         }, | ||||
|         "Caliber68x51": { | ||||
|             "6529302b8c26af6326029fb7": 1 | ||||
|         }, | ||||
|         "Caliber762x25TT": { | ||||
|             "573602322459776445391df1": 2, | ||||
|             "573601b42459776410737435": 2, | ||||
|             "5735fdcd2459776445391d61": 1, | ||||
|             "5736026a245977644601dc61": 1 | ||||
|         }, | ||||
|         "Caliber762x35": { | ||||
|             "6196365d58ef8c428c287da1": 1, | ||||
|             "6196364158ef8c428c287d9f": 6, | ||||
|             "5fbe3ffdf8b6a877a729ea82": 3 | ||||
|         }, | ||||
|         "Caliber762x39": { | ||||
|             "59e4d3d286f774176a36250a": 2, | ||||
|             "64b7af734b75259c590fa895": 2, | ||||
|             "64b7af5a8532cf95ee0a0dbd": 6, | ||||
|             "59e4d24686f7741776641ac7": 4, | ||||
|             "59e4cf5286f7741778269d8a": 2, | ||||
|             "5656d7c34bdc2d9d198b4587": 1 | ||||
|         }, | ||||
|         "Caliber762x51": { | ||||
|             "5e023e88277cce2b522ff2b1": 2, | ||||
|             "5e023e6e34d52a55c3304f71": 2, | ||||
|             "5e023e53d4353e3302577c4c": 1 | ||||
|         }, | ||||
|         "Caliber762x54R": { | ||||
|             "64b8f7c241772715af0f9c3d": 2, | ||||
|             "64b8f7b5389d7ffd620ccba2": 2, | ||||
|             "64b8f7968532cf95ee0a0dbf": 2, | ||||
|             "5e023cf8186a883be655e54f": 2, | ||||
|             "5887431f2459777e1612938f": 1 | ||||
|         }, | ||||
|         "Caliber86x70": { | ||||
|             "5fc382b6d6fa9c00c571bbc3": 2, | ||||
|             "5fc382c1016cce60e8341b20": 1 | ||||
|         }, | ||||
|         "Caliber9x18PM": { | ||||
|             "5737218f245977612125ba51": 5, | ||||
|             "57372140245977611f70ee91": 5, | ||||
|             "5737207f24597760ff7b25f2": 2, | ||||
|             "573719762459775a626ccbc1": 3, | ||||
|             "57371f8d24597761006c6a81": 3, | ||||
|             "57371f2b24597761224311f1": 5, | ||||
|             "57371eb62459776125652ac1": 1, | ||||
|             "57371b192459775a9f58a5e0": 1, | ||||
|             "57371e4124597760ff7b25f1": 1 | ||||
|         }, | ||||
|         "Caliber9x19PARA": { | ||||
|             "5efb0e16aeb21837e749c7ff": 1, | ||||
|             "58864a4f2459770fcc257101": 7, | ||||
|             "5a3c16fe86f77452b62de32a": 12, | ||||
|             "5c3df7d588a4501f290594e5": 6, | ||||
|             "64b7bbb74b75259c590fa897": 4, | ||||
|             "56d59d3ad2720bdb418b4577": 2 | ||||
|         }, | ||||
|         "Caliber9x21": { | ||||
|             "5a26ac06c4a282000c5a90a8": 5, | ||||
|             "5a26abfac4a28232980eabff": 3, | ||||
|             "5a269f97c4a282000b151807": 1 | ||||
|         }, | ||||
|         "Caliber9x33R": { | ||||
|             "62330c40bdd19b369e1e53d1": 5, | ||||
|             "62330bfadc5883093563729b": 3, | ||||
|             "62330c18744e5e31df12f516": 1 | ||||
|         }, | ||||
|         "Caliber9x39": { | ||||
|             "6576f96220d53a5b8f3e395e": 7, | ||||
|             "57a0dfb82459774d3078b56c": 5, | ||||
|             "5c0d668f86f7747ccb7f13b2": 1 | ||||
|         }, | ||||
|         "Caliber127x33": { | ||||
|             "66a0d1c87d0d369e270bb9de": 10, | ||||
|             "66a0d1f88486c69fce00fdf6": 1 | ||||
|         } | ||||
|     }, | ||||
|     "pmcAmmo": { | ||||
|         "Caliber1143x23ACP": { | ||||
|             "5ea2a8e200685063ec28c05a": 1, | ||||
|             "5efb0fc6aeb21837e749c801": 8, | ||||
|             "5efb0d4f4bc50b58e81710f3": 40, | ||||
|             "5e81f423763d9f754677bf2e": 25 | ||||
|         }, | ||||
|         "Caliber127x55": { | ||||
|             "5cadf6e5ae921500113bb973": 45 | ||||
|         }, | ||||
|         "Caliber12g": { | ||||
|             "5d6e6806a4b936088465b17e": 10, | ||||
|             "5c0d591486f7744c505b416f": 3, | ||||
|             "5d6e68d1a4b93622fe60e845": 3, | ||||
|             "5d6e6869a4b9361c140bcfde": 2, | ||||
|             "5d6e68b3a4b9361bca7e50b5": 2, | ||||
|             "58820d1224597753c90aeb13": 2, | ||||
|             "5d6e68dea4b9361bcc29e659": 2, | ||||
|             "5d6e6891a4b9361bd473feea": 9, | ||||
|             "5d6e68e6a4b9361c140bcfe0": 15, | ||||
|             "5d6e689ca4b9361bc8618956": 9 | ||||
|         }, | ||||
|         "Caliber20g": { | ||||
|             "5d6e695fa4b936359b35d852": 3, | ||||
|             "5d6e69b9a4b9361bc8618958": 3, | ||||
|             "5a38ebd9c4a282000d722a5b": 5, | ||||
|             "5d6e69c7a4b9360b6c0d54e4": 10, | ||||
| 
 | ||||
|             "5d6e6a5fa4b93614ec501745": 3, | ||||
|             "5d6e6a53a4b9361bd473feec": 3 | ||||
|         }, | ||||
|         "Caliber23x75": { | ||||
|             "5f647f31b6238e5dd066e196": 8, | ||||
|             "5e85a9a6eacf8c039e4e2ac1": 2 | ||||
|         }, | ||||
|         "Caliber366TKM": { | ||||
|             "59e6658b86f77411d949b250": 12, | ||||
|             "59e6542b86f77411dc52a77a": 35, | ||||
|             "59e655cb86f77411dc52a77b": 20 | ||||
|         }, | ||||
|         "Caliber40mmRU": { | ||||
|             "5656eb674bdc2d35148b457c": 1 | ||||
|         }, | ||||
|         "Caliber40x46": { | ||||
|             "5ede4739e0350d05467f73e8": 1, | ||||
|             "5ede47405b097655935d7d16": 1, | ||||
|             "5ede474b0c226a66f5402622": 1, | ||||
|             "5ede475339ee016e8c534742": 1, | ||||
|             "5ede475b549eed7c6d5c18fb": 1, | ||||
|             "5f0c892565703e5c461894e9": 1 | ||||
|         }, | ||||
|         "Caliber46x30": { | ||||
|             "5ba26812d4351e003201fef1": 40, | ||||
|             "5ba26844d4351e00334c9475": 60 | ||||
|         }, | ||||
|         "Caliber545x39": { | ||||
|             "56dff338d2720bbd668b4569": 5, | ||||
|             "56dff4a2d2720bbd668b456a": 7, | ||||
|             "56dff0bed2720bb0668b4567": 10, | ||||
|             "56dff3afd2720bba668b4567": 60, | ||||
|             "56dff2ced2720bb4668b4567": 5, | ||||
|             "56dff061d2720bb5668b4567": 1 | ||||
|         }, | ||||
|         "Caliber556x45NATO": { | ||||
|             "59e6918f86f7746c9f75e849": 10, | ||||
|             "59e68f6f86f7746c9f75e846": 40, | ||||
|             "59e6920f86f77411d82aa167": 50, | ||||
|             "54527a984bdc2d4e668b4567": 30, | ||||
|             "60194943740c5d77f6705eea": 10, | ||||
|             "59e6906286f7746c9f75e847": 5 | ||||
|         }, | ||||
|         "Caliber57x28": { | ||||
|             "5cc86832d7f00c000d3a6e6c": 4, | ||||
|             "5cc80f79e4a949033c7343b2": 11, | ||||
|             "5cc86840d7f00c002412c56c": 21, | ||||
|             "5cc80f8fe4a949033b0224a2": 21, | ||||
|             "5cc80f53e4a949000e1ea4f8": 12, | ||||
|             "5cc80f67e4a949035e43bbba": 4 | ||||
|         }, | ||||
|         "Caliber68x51": { | ||||
|             "6529302b8c26af6326029fb7": 1 | ||||
|         }, | ||||
|         "Caliber762x25TT": { | ||||
|             "573601b42459776410737435": 8, | ||||
|             "5735fdcd2459776445391d61": 12, | ||||
|             "5736026a245977644601dc61": 18, | ||||
|             "573603c924597764442bd9cb": 13, | ||||
|             "573603562459776430731618": 3 | ||||
|         }, | ||||
|         "Caliber762x35": { | ||||
|             "6196365d58ef8c428c287da1": 9, | ||||
|             "6196364158ef8c428c287d9f": 18, | ||||
|             "5fbe3ffdf8b6a877a729ea82": 18 | ||||
|         }, | ||||
|         "Caliber762x39": { | ||||
|             "64b7af5a8532cf95ee0a0dbd": 5, | ||||
|             "59e4d24686f7741776641ac7": 15, | ||||
|             "59e4cf5286f7741778269d8a": 40, | ||||
|             "5656d7c34bdc2d9d198b4587": 45, | ||||
|             "64b7af434b75259c590fa893": 10 | ||||
|         }, | ||||
|         "Caliber762x51": { | ||||
|             "5e023e88277cce2b522ff2b1": 10, | ||||
|             "5e023e6e34d52a55c3304f71": 30, | ||||
|             "5e023e53d4353e3302577c4c": 50, | ||||
|             "58dd3ad986f77403051cba8f": 10 | ||||
|         }, | ||||
|         "Caliber762x54R": { | ||||
|             "64b8f7b5389d7ffd620ccba2": 5, | ||||
|             "64b8f7968532cf95ee0a0dbf": 9, | ||||
|             "5e023cf8186a883be655e54f": 16, | ||||
|             "5887431f2459777e1612938f": 22, | ||||
|             "59e77a2386f7742ee578960a": 10 | ||||
|         }, | ||||
|         "Caliber86x70": { | ||||
|             "5fc382b6d6fa9c00c571bbc3": 90, | ||||
|             "5fc382c1016cce60e8341b20": 5, | ||||
|             "5fc275cf85fd526b824a571a": 5 | ||||
|         }, | ||||
|         "Caliber9x18PM": { | ||||
|             "57371f8d24597761006c6a81": 3, | ||||
|             "57371f2b24597761224311f1": 3, | ||||
|             "57371eb62459776125652ac1": 3, | ||||
|             "57371b192459775a9f58a5e0": 9, | ||||
|             "57371e4124597760ff7b25f1": 13, | ||||
|             "5737201124597760fc4431f1": 21, | ||||
|             "573720e02459776143012541": 14, | ||||
|             "573718ba2459775a75491131": 8 | ||||
|         }, | ||||
|         "Caliber9x19PARA": { | ||||
|             "5efb0e16aeb21837e749c7ff": 7, | ||||
|             "58864a4f2459770fcc257101": 1, | ||||
|             "5a3c16fe86f77452b62de32a": 15, | ||||
|             "5c3df7d588a4501f290594e5": 20, | ||||
|             "64b7bbb74b75259c590fa897": 30, | ||||
|             "56d59d3ad2720bdb418b4577": 55 | ||||
|         }, | ||||
|         "Caliber9x21": { | ||||
|             "5a26ac06c4a282000c5a90a8": 1, | ||||
|             "5a26abfac4a28232980eabff": 20, | ||||
|             "5a269f97c4a282000b151807": 27 | ||||
|         }, | ||||
|         "Caliber9x33R": { | ||||
|             "62330c40bdd19b369e1e53d1": 7, | ||||
|             "62330bfadc5883093563729b": 8, | ||||
|             "62330c18744e5e31df12f516": 4 | ||||
|         }, | ||||
|         "Caliber9x39": { | ||||
|             "6576f96220d53a5b8f3e395e": 10, | ||||
|             "57a0dfb82459774d3078b56c": 50, | ||||
|             "5c0d668f86f7747ccb7f13b2": 40 | ||||
|         }, | ||||
|         "Caliber127x33": { | ||||
|             "66a0d1c87d0d369e270bb9de": 30, | ||||
|             "66a0d1f88486c69fce00fdf6": 50 | ||||
|         } | ||||
|     }, | ||||
|     "bossAmmo": { | ||||
|         "Caliber1143x23ACP": { | ||||
|             "5ea2a8e200685063ec28c05a": 4, | ||||
|             "5efb0fc6aeb21837e749c801": 1, | ||||
|             "5efb0d4f4bc50b58e81710f3": 10, | ||||
|             "5e81f423763d9f754677bf2e": 18, | ||||
|             "5efb0cabfb3e451d70735af5": 10 | ||||
|         }, | ||||
|         "Caliber127x55": { | ||||
|             "5cadf6e5ae921500113bb973": 3, | ||||
|             "5cadf6ddae9215051e1c23b2": 12, | ||||
|             "5cadf6eeae921500134b2799": 8 | ||||
|         }, | ||||
|         "Caliber12g": { | ||||
|             "5d6e6806a4b936088465b17e": 7, | ||||
|             "64b8ee384b75259c590fa89b": 4, | ||||
|             "5d6e6911a4b9361bd5780d52": 3, | ||||
|             "5c0d591486f7744c505b416f": 5, | ||||
|             "5d6e6891a4b9361bd473feea": 2, | ||||
|             "5d6e68e6a4b9361c140bcfe0": 6, | ||||
|             "5d6e689ca4b9361bc8618956": 8, | ||||
|             "5d6e68c4a4b9361b93413f79": 8, | ||||
|             "5d6e68a8a4b9360b6c0d54e2": 3 | ||||
|         }, | ||||
|         "Caliber20g": { | ||||
|             "5d6e69c7a4b9360b6c0d54e4": 1, | ||||
|             "5d6e6a53a4b9361bd473feec": 4, | ||||
|             "5d6e6a05a4b93618084f58d0": 5, | ||||
|             "5d6e6a42a4b9364f07165f52": 5 | ||||
|         }, | ||||
|         "Caliber23x75": { | ||||
|             "5f647f31b6238e5dd066e196": 2, | ||||
|             "5e85a9a6eacf8c039e4e2ac1": 4, | ||||
|             "5e85aa1a988a8701445df1f5": 4 | ||||
|         }, | ||||
|         "Caliber366TKM": { | ||||
|             "59e6658b86f77411d949b250": 1, | ||||
|             "59e6542b86f77411dc52a77a": 2, | ||||
|             "59e655cb86f77411dc52a77b": 10, | ||||
|             "5f0596629e22f464da6bbdd9": 8 | ||||
|         }, | ||||
|         "Caliber40mmRU": { | ||||
|             "5656eb674bdc2d35148b457c": 1 | ||||
|         }, | ||||
|         "Caliber40x46": { | ||||
|             "5ede4739e0350d05467f73e8": 1, | ||||
|             "5ede47405b097655935d7d16": 1, | ||||
|             "5ede474b0c226a66f5402622": 1, | ||||
|             "5ede475339ee016e8c534742": 1, | ||||
|             "5ede475b549eed7c6d5c18fb": 1, | ||||
|             "5f0c892565703e5c461894e9": 1 | ||||
|         }, | ||||
|         "Caliber46x30": { | ||||
|             "5ba26812d4351e003201fef1": 2, | ||||
|             "5ba26844d4351e00334c9475": 4, | ||||
|             "5ba2678ad4351e44f824b344": 15, | ||||
|             "64b6979341772715af0f9c39": 15, | ||||
|             "5ba26835d4351e0035628ff5": 8 | ||||
|         }, | ||||
|         "Caliber545x39": { | ||||
|             "56dff3afd2720bba668b4567": 6, | ||||
|             "56dff2ced2720bb4668b4567": 12, | ||||
|             "56dff061d2720bb5668b4567": 20, | ||||
|             "61962b617c6c7b169525f168": 12, | ||||
|             "56dfef82d2720bbd668b4567": 9, | ||||
|             "56dff026d2720bb8668b4567": 8, | ||||
|             "5c0d5e4486f77478390952fe": 4 | ||||
|         }, | ||||
|         "Caliber556x45NATO": { | ||||
|             "5c0d5ae286f7741e46554302": 1, | ||||
|             "54527a984bdc2d4e668b4567": 7, | ||||
|             "60194943740c5d77f6705eea": 20, | ||||
|             "59e6906286f7746c9f75e847": 26, | ||||
|             "54527ac44bdc2d36668b4567": 30, | ||||
|             "59e690b686f7746c9f75e848": 7, | ||||
|             "601949593ae8f707c4608daa": 5 | ||||
|         }, | ||||
|         "Caliber57x28": { | ||||
|             "5cc80f8fe4a949033b0224a2": 5, | ||||
|             "5cc80f53e4a949000e1ea4f8": 21, | ||||
|             "5cc80f67e4a949035e43bbba": 15, | ||||
|             "5cc80f38e4a949001152b560": 12 | ||||
|         }, | ||||
|         "Caliber68x51": { | ||||
|             "6529302b8c26af6326029fb7": 10, | ||||
|             "6529243824cbe3c74a05e5c1": 5 | ||||
|         }, | ||||
|         "Caliber762x25TT": { | ||||
|             "5736026a245977644601dc61": 5, | ||||
|             "573603c924597764442bd9cb": 10, | ||||
|             "573603562459776430731618": 10 | ||||
|         }, | ||||
|         "Caliber762x35": { | ||||
|             "6196365d58ef8c428c287da1": 7, | ||||
|             "5fbe3ffdf8b6a877a729ea82": 6, | ||||
|             "619636be6db0f2477964e710": 23, | ||||
|             "64b8725c4b75259c590fa899": 20, | ||||
|             "5fd20ff893a8961fc660a954": 9 | ||||
|         }, | ||||
|         "Caliber762x39": { | ||||
|             "59e4cf5286f7741778269d8a": 4, | ||||
|             "5656d7c34bdc2d9d198b4587": 28, | ||||
|             "64b7af434b75259c590fa893": 33, | ||||
|             "59e0d99486f7744a32234762": 20, | ||||
|             "601aa3d2b2bcb34913271e6d": 12 | ||||
|         }, | ||||
|         "Caliber762x51": { | ||||
|             "5e023e53d4353e3302577c4c": 6, | ||||
|             "58dd3ad986f77403051cba8f": 27, | ||||
|             "5a608bf24f39f98ffc77720e": 19, | ||||
|             "5a6086ea4f39f99cd479502f": 9, | ||||
|             "5efb0c1bd79ff02a1f5e68d9": 2 | ||||
|         }, | ||||
|         "Caliber762x54R": { | ||||
|             "5e023cf8186a883be655e54f": 3, | ||||
|             "5887431f2459777e1612938f": 20, | ||||
|             "59e77a2386f7742ee578960a": 25, | ||||
|             "5e023d34e8a400319a28ed44": 22, | ||||
|             "560d61e84bdc2da74d8b4571": 15, | ||||
|             "5e023d48186a883be655e551": 10 | ||||
|         }, | ||||
|         "Caliber86x70": { | ||||
|             "5fc382b6d6fa9c00c571bbc3": 5, | ||||
|             "5fc382c1016cce60e8341b20": 8, | ||||
|             "5fc275cf85fd526b824a571a": 8, | ||||
|             "5fc382a9d724d907e2077dab": 5 | ||||
|         }, | ||||
|         "Caliber9x18PM": { | ||||
|             "57371e4124597760ff7b25f1": 3, | ||||
|             "5737201124597760fc4431f1": 5, | ||||
|             "573720e02459776143012541": 12, | ||||
|             "573718ba2459775a75491131": 18, | ||||
|             "57371aab2459775a77142f22": 12, | ||||
|             "573719df2459775a626ccbc2": 10 | ||||
|         }, | ||||
|         "Caliber9x19PARA": { | ||||
|             "5c0d56a986f774449d5de529": 9, | ||||
|             "5efb0e16aeb21837e749c7ff": 5, | ||||
|             "5a3c16fe86f77452b62de32a": 4, | ||||
|             "56d59d3ad2720bdb418b4577": 18, | ||||
|             "5c925fa22e221601da359b7b": 22, | ||||
|             "5efb0da7a29a85116f6ea05f": 9 | ||||
|         }, | ||||
|         "Caliber9x21": { | ||||
|             "5a269f97c4a282000b151807": 8, | ||||
|             "6576f93989f0062e741ba952": 18, | ||||
|             "5a26ac0ec4a28200741e1e18": 18, | ||||
|             "6576f4708ca9c4381d16cd9d": 8 | ||||
|         }, | ||||
|         "Caliber9x33R": { | ||||
|             "62330c18744e5e31df12f516": 9, | ||||
|             "62330b3ed4dc74626d570b95": 6 | ||||
|         }, | ||||
|         "Caliber9x39": { | ||||
|             "5c0d668f86f7747ccb7f13b2": 9, | ||||
|             "61962d879bb3d20b0946d385": 25, | ||||
|             "57a0e5022459774d1673f889": 25, | ||||
|             "5c0d688c86f77413ae3407b2": 12 | ||||
|         }, | ||||
|         "Caliber127x33": { | ||||
|             "66a0d1c87d0d369e270bb9de": 3, | ||||
|             "66a0d1f88486c69fce00fdf6": 30, | ||||
|             "66a0d1e0ed648d72fe064d06": 25,  | ||||
|             "668fe62ac62660a5d8071446": 12 | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,430 @@ | |||
| { | ||||
|     "pmcUSEC": { | ||||
|         "appearance": { | ||||
|             "body": { | ||||
|                 "5cde95d97d6c8b647a3769b0": 5, | ||||
|                 "66546f823b51a4d21e0d17d7": 1, | ||||
|                 "5d1f56a686f7744bce0ee9eb": 2, | ||||
|                 "5d1f56c686f7744bcd13459c": 3, | ||||
|                 "637b945722e2a933ed0e33c8": 3, | ||||
|                 "6571cb0923aa6d72760a7f8f": 3, | ||||
|                 "5fd3e9f71b735718c25cd9f8": 3, | ||||
|                 "642d9bbf6c06444bf7033855": 3 | ||||
|             }, | ||||
|             "feet": { | ||||
|                 "5cde95ef7d6c8b04713c4f2d": 5, | ||||
|                 "5d1f58ed86f7744bcb0acd1c": 2, | ||||
|                 "5d1f590486f7744bcd13459e": 3, | ||||
|                 "642d4d8eb6b75d4c89077cf9": 3, | ||||
|                 "6033a3fee29c9f6c9b14e74e": 3 | ||||
|             }, | ||||
|             "hands": { | ||||
|                 "5cde95fa7d6c8b04737c2d13": 1 | ||||
|             }, | ||||
|             "head": { | ||||
|                 "5cde96047d6c8b20b577f016": 1, | ||||
|                 "5fdb4139e4ed5b5ea251e4ed": 1, | ||||
|                 "5fdb5950f5264a66150d1c6e": 1, | ||||
|                 "60a6aa8fd559ae040d0d951f": 1, | ||||
|                 "619f9e338858a474c8685cc9": 1, | ||||
|                 "62aca6a1310e67685a2fc2e7": 1, | ||||
|                 "6574aabee0423b9ebe0c79cf": 1 | ||||
|             } | ||||
|         } | ||||
|     }, | ||||
|     "pmcBEAR": { | ||||
|         "appearance": { | ||||
|             "body": { | ||||
|                 "5cc0858d14c02e000c6bea66": 5, | ||||
|                 "66546f823b51a4d21e0d17d7": 1, | ||||
|                 "5d1f565786f7743f8362bcd5": 2, | ||||
|                 "5fce3e0cfe40296c1d5fd782": 3, | ||||
|                 "6377266693a3b4967208e42b": 3, | ||||
|                 "5d1f564b86f7744bcb0acd16": 3, | ||||
|                 "6295e698e9de5e7b3751c47a": 3, | ||||
|                 "642e8ae07e17c882400c4f87": 3, | ||||
|                 "5d1f568486f7744bca3f0b98": 3 | ||||
|             }, | ||||
|             "feet": { | ||||
|                 "5cc085bb14c02e000e67a5c5": 5, | ||||
|                 "5d1f58bd86f7744bce0ee9ef": 2, | ||||
|                 "6377315993a3b4967208e437": 3, | ||||
|                 "5d1f588e86f7744bcc048753": 3, | ||||
|                 "65707a89f5a6f1412f0c5f7b": 3, | ||||
|                 "642ed40af5bdf1c04e01952e": 3, | ||||
|                 "5fce3e965a9f8c40685693bc": 3 | ||||
|             }, | ||||
|             "hands": { | ||||
|                 "5cc0876314c02e000c6bea6b": 1 | ||||
|             }, | ||||
|             "head": { | ||||
|                 "5cc084dd14c02e000b0550a3": 1, | ||||
|                 "5fdb50bb2b730a787b3f78cf": 1, | ||||
|                 "5fdb7571e4ed5b5ea251e529": 1, | ||||
|                 "60a6aaad42fd2735e4589978": 1, | ||||
|                 "619f94f5b90286142b59d45f": 1, | ||||
|                 "62a9e7d15ea3b87d6f642a28": 1, | ||||
|                 "6574aa9a1b144de18c0fba45": 1 | ||||
|             } | ||||
|         } | ||||
|     }, | ||||
|     "springEarly": { | ||||
|         "pmcUSEC": { | ||||
|             "appearance": { | ||||
|                 "body": { | ||||
|                     "5d1f56c686f7744bcd13459c": 1, | ||||
|                     "5fd3e9f71b735718c25cd9f8": 1, | ||||
|                     "66043728333907134309d647": 1, | ||||
|                     "66acbe49dc61999a6a03d4d6": 1, | ||||
|                     "660437e57502eca33a08caca": 1, | ||||
|                     "5d1f56f186f7744bcb0acd1a": 1, | ||||
|                     "5d1f56ff86f7743f8362bcd7": 1, | ||||
|                     "5d1f56a686f7744bce0ee9eb": 2, | ||||
|                     "5e9da17386f774054b6f79a3": 2, | ||||
|                     "5e4bb35286f77406a511c9bc": 2, | ||||
|                     "5d1f56e486f7744bce0ee9ed": 2 | ||||
|                 }, | ||||
|                 "feet": { | ||||
|                     "642d4d8eb6b75d4c89077cf9": 1, | ||||
|                     "5fcf940bce1ba36a513bb9cc": 1, | ||||
|                     "66acc8f719271bd6d00dec0b": 1, | ||||
|                     "6295e944e9de5e7b3751c4da": 1, | ||||
|                     "5d1f592286f7743f8362bcdb": 1, | ||||
|                     "5e4bb3b586f77406812bd579": 1, | ||||
|                     "5d1f590486f7744bcd13459e": 3, | ||||
|                     "5d1f58ed86f7744bcb0acd1c": 3 | ||||
|                 }, | ||||
|                 "hands": { | ||||
|                     "5cde95fa7d6c8b04737c2d13": 1 | ||||
|                 }, | ||||
|                 "head": { | ||||
|                     "5cde96047d6c8b20b577f016": 1, | ||||
|                     "5fdb4139e4ed5b5ea251e4ed": 1, | ||||
|                     "5fdb5950f5264a66150d1c6e": 1, | ||||
|                     "60a6aa8fd559ae040d0d951f": 1, | ||||
|                     "619f9e338858a474c8685cc9": 1, | ||||
|                     "62aca6a1310e67685a2fc2e7": 1, | ||||
|                     "6574aabee0423b9ebe0c79cf": 1 | ||||
|                 } | ||||
|             } | ||||
|         }, | ||||
|         "pmcBEAR": { | ||||
|             "appearance": { | ||||
|                 "body": { | ||||
|                     "657058fddf9b3231400e9188": 1, | ||||
|                     "6033a31e9ec839204e6a2f3e": 1, | ||||
|                     "5d1f567786f7744bcc04874f": 1, | ||||
|                     "5e9d9fa986f774054d6b89f2": 1, | ||||
|                     "5f5e401747344c2e4f6c42c5": 1, | ||||
|                     "642e8ae07e17c882400c4f87": 2, | ||||
|                     "5d1f568486f7744bca3f0b98": 2, | ||||
|                     "66acec1dc94f4bf5bc063a16": 2, | ||||
|                     "5e4bb31586f7740695730568": 2 | ||||
|                 }, | ||||
|                 "feet": { | ||||
|                     "5d1f58bd86f7744bce0ee9ef": 1, | ||||
|                     "6377315993a3b4967208e437": 1, | ||||
|                     "66043cf87502eca33a08cad2": 1, | ||||
|                     "5d1f58cb86f7744bca3f0b9a": 1, | ||||
|                     "5d1f58a086f7743f8362bcd9": 1, | ||||
|                     "617be9e4e02b3b3fa50fa8f2": 1, | ||||
|                     "5f5e40400bc58666c37e7819": 1, | ||||
|                     "66acebd4ede86671bb09584b": 3, | ||||
|                     "5d1f58ab86f7743014162042": 3 | ||||
|                 }, | ||||
|                 "hands": { | ||||
|                     "5cc0876314c02e000c6bea6b": 1 | ||||
|                 }, | ||||
|                 "head": { | ||||
|                     "5cc084dd14c02e000b0550a3": 1, | ||||
|                     "5fdb50bb2b730a787b3f78cf": 1, | ||||
|                     "5fdb7571e4ed5b5ea251e529": 1, | ||||
|                     "60a6aaad42fd2735e4589978": 1, | ||||
|                     "619f94f5b90286142b59d45f": 1, | ||||
|                     "62a9e7d15ea3b87d6f642a28": 1, | ||||
|                     "6574aa9a1b144de18c0fba45": 1 | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     }, | ||||
|     "spring": { | ||||
|         "pmcUSEC": { | ||||
|             "appearance": { | ||||
|                 "body": { | ||||
|                     "5cde95d97d6c8b647a3769b0": 1, | ||||
|                     "5fd3e9f71b735718c25cd9f8": 1, | ||||
|                     "66043728333907134309d647": 1, | ||||
|                     "5d4da0cb86f77450fe0a6629": 1, | ||||
|                     "5d1f56f186f7744bcb0acd1a": 1, | ||||
|                     "5f5e4075df4f3100376a8138": 1 | ||||
|                 }, | ||||
|                 "feet": { | ||||
|                     "5cde95ef7d6c8b04713c4f2d": 1, | ||||
|                     "6033a3fee29c9f6c9b14e74e": 1, | ||||
|                     "660436487502eca33a08cac8": 1, | ||||
|                     "6571cad4c8673f00290f5657": 1, | ||||
|                     "66acc8f719271bd6d00dec0b": 1, | ||||
|                     "5d1f592286f7743f8362bcdb": 1, | ||||
|                     "642d6941ff5ecad7810a8a61": 1, | ||||
|                     "5e9dcadd86f7743e20652f23": 1 | ||||
|                 }, | ||||
|                 "hands": { | ||||
|                     "5cde95fa7d6c8b04737c2d13": 1 | ||||
|                 }, | ||||
|                 "head": { | ||||
|                     "5cde96047d6c8b20b577f016": 1, | ||||
|                     "5fdb4139e4ed5b5ea251e4ed": 1, | ||||
|                     "5fdb5950f5264a66150d1c6e": 1, | ||||
|                     "60a6aa8fd559ae040d0d951f": 1, | ||||
|                     "619f9e338858a474c8685cc9": 1, | ||||
|                     "62aca6a1310e67685a2fc2e7": 1, | ||||
|                     "6574aabee0423b9ebe0c79cf": 1 | ||||
|                 } | ||||
|             } | ||||
|         }, | ||||
|         "pmcBEAR": { | ||||
|             "appearance": { | ||||
|                 "body": { | ||||
|                     "5cc0858d14c02e000c6bea66": 1, | ||||
|                     "5d1f564b86f7744bcb0acd16": 1, | ||||
|                     "6295e698e9de5e7b3751c47a": 1, | ||||
|                     "6033a31e9ec839204e6a2f3e": 1, | ||||
|                     "5fce3e47fe40296c1d5fd784": 1, | ||||
|                     "617bca4b4013b06b0b78df2a": 1, | ||||
|                     "5df89f1f86f77412631087ea": 1 | ||||
|                 }, | ||||
|                 "feet": { | ||||
|                     "5cc085bb14c02e000e67a5c5": 1, | ||||
|                     "5d1f588e86f7744bcc048753": 1, | ||||
|                     "66043cf87502eca33a08cad2": 1, | ||||
|                     "6033a3d8ed2e0509b15f9031": 1, | ||||
|                     "642e71620a69698d1b049f0a": 1, | ||||
|                     "617be9e4e02b3b3fa50fa8f2": 1, | ||||
|                     "642eea6f881906a7fe086841": 1, | ||||
|                     "5df89f8f86f77412672a1e38": 1, | ||||
|                     "5e9dc97c86f774054c19ac9a": 1, | ||||
|                     "5e4bb39386f774067f79de05": 1 | ||||
|                 }, | ||||
|                 "hands": { | ||||
|                     "5cc0876314c02e000c6bea6b": 1 | ||||
|                 }, | ||||
|                 "head": { | ||||
|                     "5cc084dd14c02e000b0550a3": 1, | ||||
|                     "5fdb50bb2b730a787b3f78cf": 1, | ||||
|                     "5fdb7571e4ed5b5ea251e529": 1, | ||||
|                     "60a6aaad42fd2735e4589978": 1, | ||||
|                     "619f94f5b90286142b59d45f": 1, | ||||
|                     "62a9e7d15ea3b87d6f642a28": 1, | ||||
|                     "6574aa9a1b144de18c0fba45": 1 | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     }, | ||||
|     "summer": { | ||||
|         "pmcUSEC": { | ||||
|             "appearance": { | ||||
|                 "body": { | ||||
|                     "5cde95d97d6c8b647a3769b0": 1, | ||||
|                     "5d1f56c686f7744bcd13459c": 1, | ||||
|                     "5fd3e9f71b735718c25cd9f8": 1, | ||||
|                     "66043728333907134309d647": 1, | ||||
|                     "5d4da0cb86f77450fe0a6629": 1, | ||||
|                     "66acbe49dc61999a6a03d4d6": 1, | ||||
|                     "64ef3efdb63b74469b6c1499": 1, | ||||
|                     "642c18b8a6a0660b560fb31c": 1, | ||||
|                     "5d1f56f186f7744bcb0acd1a": 1, | ||||
|                     "5f5e4075df4f3100376a8138": 1 | ||||
|                 }, | ||||
|                 "feet": { | ||||
|                     "5cde95ef7d6c8b04713c4f2d": 1, | ||||
|                     "6033a3fee29c9f6c9b14e74e": 1, | ||||
|                     "660436487502eca33a08cac8": 1, | ||||
|                     "6571cad4c8673f00290f5657": 1, | ||||
|                     "66acc8f719271bd6d00dec0b": 1, | ||||
|                     "5d1f593286f7743014162044": 1, | ||||
|                     "5d1f592286f7743f8362bcdb": 1, | ||||
|                     "642d6941ff5ecad7810a8a61": 1, | ||||
|                     "5e9dcadd86f7743e20652f23": 1 | ||||
|                 }, | ||||
|                 "hands": { | ||||
|                     "5cde95fa7d6c8b04737c2d13": 1 | ||||
|                 }, | ||||
|                 "head": { | ||||
|                     "5cde96047d6c8b20b577f016": 1, | ||||
|                     "5fdb4139e4ed5b5ea251e4ed": 1, | ||||
|                     "5fdb5950f5264a66150d1c6e": 1, | ||||
|                     "60a6aa8fd559ae040d0d951f": 1, | ||||
|                     "619f9e338858a474c8685cc9": 1, | ||||
|                     "62aca6a1310e67685a2fc2e7": 1, | ||||
|                     "6574aabee0423b9ebe0c79cf": 1 | ||||
|                 } | ||||
|             } | ||||
|         }, | ||||
|         "pmcBEAR": { | ||||
|             "appearance": { | ||||
|                 "body": { | ||||
|                     "5cc0858d14c02e000c6bea66": 1, | ||||
|                     "5d1f564b86f7744bcb0acd16": 1, | ||||
|                     "6295e698e9de5e7b3751c47a": 1, | ||||
|                     "6033a31e9ec839204e6a2f3e": 1, | ||||
|                     "5fce3e47fe40296c1d5fd784": 1, | ||||
|                     "617bca4b4013b06b0b78df2a": 1, | ||||
|                     "64ef3efdb63b74469b6c1499": 1, | ||||
|                     "5df89f1f86f77412631087ea": 1, | ||||
|                     "5e9d9fa986f774054d6b89f2": 1 | ||||
|                 }, | ||||
|                 "feet": { | ||||
|                     "5cc085bb14c02e000e67a5c5": 1, | ||||
|                     "5d1f588e86f7744bcc048753": 1, | ||||
|                     "66043cf87502eca33a08cad2": 1, | ||||
|                     "6033a3d8ed2e0509b15f9031": 1, | ||||
|                     "642e71620a69698d1b049f0a": 1, | ||||
|                     "617be9e4e02b3b3fa50fa8f2": 1, | ||||
|                     "642eea6f881906a7fe086841": 1, | ||||
|                     "5df89f8f86f77412672a1e38": 1, | ||||
|                     "5e9dc97c86f774054c19ac9a": 1, | ||||
|                     "5e4bb39386f774067f79de05": 1 | ||||
|                 }, | ||||
|                 "hands": { | ||||
|                     "5cc0876314c02e000c6bea6b": 1 | ||||
|                 }, | ||||
|                 "head": { | ||||
|                     "5cc084dd14c02e000b0550a3": 1, | ||||
|                     "5fdb50bb2b730a787b3f78cf": 1, | ||||
|                     "5fdb7571e4ed5b5ea251e529": 1, | ||||
|                     "60a6aaad42fd2735e4589978": 1, | ||||
|                     "619f94f5b90286142b59d45f": 1, | ||||
|                     "62a9e7d15ea3b87d6f642a28": 1, | ||||
|                     "6574aa9a1b144de18c0fba45": 1 | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     }, | ||||
|     "autumn": { | ||||
|         "pmcUSEC": { | ||||
|             "appearance": { | ||||
|                 "body": { | ||||
|                     "5d1f56c686f7744bcd13459c": 1, | ||||
|                     "637b945722e2a933ed0e33c8": 1, | ||||
|                     "6571cb0923aa6d72760a7f8f": 1, | ||||
|                     "6033a35f80ae5e2f970ba6bb": 1, | ||||
|                     "5d1f56e486f7744bce0ee9ed": 1, | ||||
|                     "66acbe49dc61999a6a03d4d6": 1, | ||||
|                     "660437e57502eca33a08caca": 1, | ||||
|                     "64ef3efdb63b74469b6c1499": 1, | ||||
|                     "5d1f56ff86f7743f8362bcd7": 1 | ||||
|                 }, | ||||
|                 "feet": { | ||||
|                     "642d4d8eb6b75d4c89077cf9": 1, | ||||
|                     "5fcf940bce1ba36a513bb9cc": 1, | ||||
|                     "637ba17aa10a96c2b605dbc2": 1, | ||||
|                     "6295e944e9de5e7b3751c4da": 1, | ||||
|                     "5e4bb3b586f77406812bd579": 1, | ||||
|                     "5f5e40a06760b4138443b341": 1 | ||||
|                 }, | ||||
|                 "hands": { | ||||
|                     "5cde95fa7d6c8b04737c2d13": 1 | ||||
|                 }, | ||||
|                 "head": { | ||||
|                     "5cde96047d6c8b20b577f016": 1, | ||||
|                     "5fdb4139e4ed5b5ea251e4ed": 1, | ||||
|                     "5fdb5950f5264a66150d1c6e": 1, | ||||
|                     "60a6aa8fd559ae040d0d951f": 1, | ||||
|                     "619f9e338858a474c8685cc9": 1, | ||||
|                     "62aca6a1310e67685a2fc2e7": 1, | ||||
|                     "6574aabee0423b9ebe0c79cf": 1 | ||||
|                 } | ||||
|             } | ||||
|         }, | ||||
|         "pmcBEAR": { | ||||
|             "appearance": { | ||||
|                 "body": { | ||||
|                     "6377266693a3b4967208e42b": 1, | ||||
|                     "5d1f568486f7744bca3f0b98": 1, | ||||
|                     "657058fddf9b3231400e9188": 1, | ||||
|                     "642ed297ac11c9eaf10d87e8": 1, | ||||
|                     "5d1f567786f7744bcc04874f": 1, | ||||
|                     "64ef3efdb63b74469b6c1499": 1, | ||||
|                     "6430119aac11c9eaf10d881b": 1, | ||||
|                     "5f5e401747344c2e4f6c42c5": 1 | ||||
|                 }, | ||||
|                 "feet": { | ||||
|                     "5d1f58bd86f7744bce0ee9ef": 1, | ||||
|                     "6377315993a3b4967208e437": 1, | ||||
|                     "642ed40af5bdf1c04e01952e": 1, | ||||
|                     "6295e63de08ed747e64ae991": 1, | ||||
|                     "5d1f58a086f7743f8362bcd9": 1, | ||||
|                     "66043d7ac8949a435906e434": 1, | ||||
|                     "5d1f58ab86f7743014162042": 1, | ||||
|                     "5f5e40400bc58666c37e7819": 1 | ||||
|                 }, | ||||
|                 "hands": { | ||||
|                     "5cc0876314c02e000c6bea6b": 1 | ||||
|                 }, | ||||
|                 "head": { | ||||
|                     "5cc084dd14c02e000b0550a3": 1, | ||||
|                     "5fdb50bb2b730a787b3f78cf": 1, | ||||
|                     "5fdb7571e4ed5b5ea251e529": 1, | ||||
|                     "60a6aaad42fd2735e4589978": 1, | ||||
|                     "619f94f5b90286142b59d45f": 1, | ||||
|                     "62a9e7d15ea3b87d6f642a28": 1, | ||||
|                     "6574aa9a1b144de18c0fba45": 1 | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     }, | ||||
|     "winter": { | ||||
|         "pmcUSEC": { | ||||
|             "appearance": { | ||||
|                 "body": { | ||||
|                     "5d1f56a686f7744bce0ee9eb": 1, | ||||
|                     "5e9da17386f774054b6f79a3": 1, | ||||
|                     "5e4bb35286f77406a511c9bc": 1, | ||||
|                     "5d1f56e486f7744bce0ee9ed": 1 | ||||
|                 }, | ||||
|                 "feet": { | ||||
|                     "5d1f590486f7744bcd13459e": 1, | ||||
|                     "5d1f58ed86f7744bcb0acd1c": 1 | ||||
|                 }, | ||||
|                 "hands": { | ||||
|                     "5cde95fa7d6c8b04737c2d13": 1 | ||||
|                 }, | ||||
|                 "head": { | ||||
|                     "5cde96047d6c8b20b577f016": 1, | ||||
|                     "5fdb4139e4ed5b5ea251e4ed": 1, | ||||
|                     "5fdb5950f5264a66150d1c6e": 1, | ||||
|                     "60a6aa8fd559ae040d0d951f": 1, | ||||
|                     "619f9e338858a474c8685cc9": 1, | ||||
|                     "62aca6a1310e67685a2fc2e7": 1, | ||||
|                     "6574aabee0423b9ebe0c79cf": 1 | ||||
|                 } | ||||
|             } | ||||
|         }, | ||||
|         "pmcBEAR": { | ||||
|             "appearance": { | ||||
|                 "body": { | ||||
|                     "642e8ae07e17c882400c4f87": 1, | ||||
|                     "5d1f568486f7744bca3f0b98": 1, | ||||
|                     "66acec1dc94f4bf5bc063a16": 1, | ||||
|                     "5e4bb31586f7740695730568": 1 | ||||
|                 }, | ||||
|                 "feet": { | ||||
|                     "66acebd4ede86671bb09584b": 1, | ||||
|                     "5d1f58ab86f7743014162042": 1 | ||||
|                 }, | ||||
|                 "hands": { | ||||
|                     "5cc0876314c02e000c6bea6b": 1 | ||||
|                 }, | ||||
|                 "head": { | ||||
|                     "5cc084dd14c02e000b0550a3": 1, | ||||
|                     "5fdb50bb2b730a787b3f78cf": 1, | ||||
|                     "5fdb7571e4ed5b5ea251e529": 1, | ||||
|                     "60a6aaad42fd2735e4589978": 1, | ||||
|                     "619f94f5b90286142b59d45f": 1, | ||||
|                     "62a9e7d15ea3b87d6f642a28": 1, | ||||
|                     "6574aa9a1b144de18c0fba45": 1 | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							|  | @ -0,0 +1,464 @@ | |||
| {     | ||||
|     "scavAmmo": { | ||||
|         "Caliber1143x23ACP": { | ||||
|             "5efb0fc6aeb21837e749c801": 1, | ||||
|             "5efb0d4f4bc50b58e81710f3": 3 | ||||
|         }, | ||||
|         "Caliber127x55": { | ||||
|             "5cadf6e5ae921500113bb973": 1 | ||||
|         }, | ||||
|         "Caliber12g": { | ||||
|             "5d6e6772a4b936088465b17c": 2, | ||||
|             "5d6e6806a4b936088465b17e": 2, | ||||
|             "5d6e67fba4b9361bc73bc779": 2, | ||||
|             "560d5e524bdc2d25448b4571": 2, | ||||
|             "5d6e6869a4b9361c140bcfde": 1, | ||||
|             "5d6e68b3a4b9361bca7e50b5": 1, | ||||
|             "58820d1224597753c90aeb13": 1, | ||||
|             "5d6e68dea4b9361bcc29e659": 1, | ||||
|             "5d6e6891a4b9361bd473feea": 1, | ||||
|             "5d6e68e6a4b9361c140bcfe0": 1, | ||||
|             "5d6e689ca4b9361bc8618956": 1 | ||||
|         }, | ||||
|         "Caliber20g": { | ||||
|             "5d6e695fa4b936359b35d852": 2, | ||||
|             "5d6e69b9a4b9361bc8618958": 2, | ||||
|             "5a38ebd9c4a282000d722a5b": 2, | ||||
|             "5d6e69c7a4b9360b6c0d54e4": 1, | ||||
|             "5d6e6a53a4b9361bd473feec": 1 | ||||
|         }, | ||||
|         "Caliber23x75": { | ||||
|             "5f647f31b6238e5dd066e196": 3, | ||||
|             "5e85a9a6eacf8c039e4e2ac1": 1 | ||||
|         }, | ||||
|         "Caliber366TKM": { | ||||
|             "59e6658b86f77411d949b250": 3, | ||||
|             "59e6542b86f77411dc52a77a": 1 | ||||
|         }, | ||||
|         "Caliber40mmRU": { | ||||
|             "5656eb674bdc2d35148b457c": 1 | ||||
|         }, | ||||
|         "Caliber40x46": { | ||||
|             "5ede4739e0350d05467f73e8": 1, | ||||
|             "5ede47405b097655935d7d16": 1, | ||||
|             "5ede474b0c226a66f5402622": 1, | ||||
|             "5ede475339ee016e8c534742": 1, | ||||
|             "5ede475b549eed7c6d5c18fb": 1, | ||||
|             "5f0c892565703e5c461894e9": 1 | ||||
|         }, | ||||
|         "Caliber46x30": { | ||||
|             "5ba26812d4351e003201fef1": 3, | ||||
|             "5ba26844d4351e00334c9475": 1 | ||||
|         }, | ||||
|         "Caliber545x39": { | ||||
|             "56dff216d2720bbd668b4568": 1, | ||||
|             "56dff338d2720bbd668b4569": 4, | ||||
|             "56dff421d2720b5f5a8b4567": 4, | ||||
|             "56dff4ecd2720b5f5a8b4568": 2, | ||||
|             "56dff4a2d2720bbd668b456a": 4, | ||||
|             "56dff0bed2720bb0668b4567": 3, | ||||
|             "56dff3afd2720bba668b4567": 1 | ||||
|         }, | ||||
|         "Caliber556x45NATO": { | ||||
|             "59e6927d86f77411da468256": 2, | ||||
|             "59e6918f86f7746c9f75e849": 2, | ||||
|             "59e68f6f86f7746c9f75e846": 4, | ||||
|             "59e6920f86f77411d82aa167": 5, | ||||
|             "54527a984bdc2d4e668b4567": 1 | ||||
|         }, | ||||
|         "Caliber57x28": { | ||||
|             "5cc86832d7f00c000d3a6e6c": 2, | ||||
|             "5cc80f79e4a949033c7343b2": 3, | ||||
|             "5cc86840d7f00c002412c56c": 3, | ||||
|             "5cc80f8fe4a949033b0224a2": 1, | ||||
|             "5cc80f53e4a949000e1ea4f8": 1 | ||||
|         }, | ||||
|         "Caliber68x51": { | ||||
|             "6529302b8c26af6326029fb7": 1 | ||||
|         }, | ||||
|         "Caliber762x25TT": { | ||||
|             "573602322459776445391df1": 2, | ||||
|             "573601b42459776410737435": 2, | ||||
|             "5735fdcd2459776445391d61": 1, | ||||
|             "5736026a245977644601dc61": 1 | ||||
|         }, | ||||
|         "Caliber762x35": { | ||||
|             "6196365d58ef8c428c287da1": 1, | ||||
|             "6196364158ef8c428c287d9f": 6, | ||||
|             "5fbe3ffdf8b6a877a729ea82": 3 | ||||
|         }, | ||||
|         "Caliber762x39": { | ||||
|             "59e4d3d286f774176a36250a": 2, | ||||
|             "64b7af734b75259c590fa895": 2, | ||||
|             "64b7af5a8532cf95ee0a0dbd": 6, | ||||
|             "59e4d24686f7741776641ac7": 4, | ||||
|             "59e4cf5286f7741778269d8a": 2, | ||||
|             "5656d7c34bdc2d9d198b4587": 1 | ||||
|         }, | ||||
|         "Caliber762x51": { | ||||
|             "5e023e88277cce2b522ff2b1": 2, | ||||
|             "5e023e6e34d52a55c3304f71": 2, | ||||
|             "5e023e53d4353e3302577c4c": 1 | ||||
|         }, | ||||
|         "Caliber762x54R": { | ||||
|             "64b8f7c241772715af0f9c3d": 2, | ||||
|             "64b8f7b5389d7ffd620ccba2": 2, | ||||
|             "64b8f7968532cf95ee0a0dbf": 2, | ||||
|             "5e023cf8186a883be655e54f": 2, | ||||
|             "5887431f2459777e1612938f": 1 | ||||
|         }, | ||||
|         "Caliber86x70": { | ||||
|             "5fc382b6d6fa9c00c571bbc3": 2, | ||||
|             "5fc382c1016cce60e8341b20": 1 | ||||
|         }, | ||||
|         "Caliber9x18PM": { | ||||
|             "5737218f245977612125ba51": 5, | ||||
|             "57372140245977611f70ee91": 5, | ||||
|             "5737207f24597760ff7b25f2": 2, | ||||
|             "573719762459775a626ccbc1": 3, | ||||
|             "57371f8d24597761006c6a81": 3, | ||||
|             "57371f2b24597761224311f1": 5, | ||||
|             "57371eb62459776125652ac1": 1, | ||||
|             "57371b192459775a9f58a5e0": 1, | ||||
|             "57371e4124597760ff7b25f1": 1 | ||||
|         }, | ||||
|         "Caliber9x19PARA": { | ||||
|             "5efb0e16aeb21837e749c7ff": 1, | ||||
|             "58864a4f2459770fcc257101": 7, | ||||
|             "5a3c16fe86f77452b62de32a": 12, | ||||
|             "5c3df7d588a4501f290594e5": 6, | ||||
|             "64b7bbb74b75259c590fa897": 4, | ||||
|             "56d59d3ad2720bdb418b4577": 2 | ||||
|         }, | ||||
|         "Caliber9x21": { | ||||
|             "5a26ac06c4a282000c5a90a8": 5, | ||||
|             "5a26abfac4a28232980eabff": 3, | ||||
|             "5a269f97c4a282000b151807": 1 | ||||
|         }, | ||||
|         "Caliber9x33R": { | ||||
|             "62330c40bdd19b369e1e53d1": 5, | ||||
|             "62330bfadc5883093563729b": 3, | ||||
|             "62330c18744e5e31df12f516": 1 | ||||
|         }, | ||||
|         "Caliber9x39": { | ||||
|             "6576f96220d53a5b8f3e395e": 7, | ||||
|             "57a0dfb82459774d3078b56c": 5, | ||||
|             "5c0d668f86f7747ccb7f13b2": 1 | ||||
|         }, | ||||
|         "Caliber127x33": { | ||||
|             "66a0d1c87d0d369e270bb9de": 10, | ||||
|             "66a0d1f88486c69fce00fdf6": 1 | ||||
|         } | ||||
|     }, | ||||
|     "pmcAmmo": { | ||||
|         "Caliber1143x23ACP": { | ||||
|             "5ea2a8e200685063ec28c05a": 10, | ||||
|             "5efb0fc6aeb21837e749c801": 5, | ||||
|             "5efb0d4f4bc50b58e81710f3": 30, | ||||
|             "5e81f423763d9f754677bf2e": 50, | ||||
|             "5efb0cabfb3e451d70735af5": 10 | ||||
|         }, | ||||
|         "Caliber127x55": { | ||||
|             "5cadf6e5ae921500113bb973": 80, | ||||
|             "5cadf6ddae9215051e1c23b2": 20 | ||||
|         }, | ||||
|         "Caliber12g": { | ||||
|             "5d6e6806a4b936088465b17e": 15, | ||||
|             "64b8ee384b75259c590fa89b": 6, | ||||
|             "5c0d591486f7744c505b416f": 5, | ||||
|             "5d6e68e6a4b9361c140bcfe0": 15, | ||||
|             "5d6e689ca4b9361bc8618956": 13, | ||||
|             "5d6e68c4a4b9361b93413f79": 9 | ||||
|         }, | ||||
|         "Caliber20g": { | ||||
|             "5d6e69c7a4b9360b6c0d54e4": 8, | ||||
|             "5d6e6a5fa4b93614ec501745": 6, | ||||
|             "5d6e6a53a4b9361bd473feec": 6, | ||||
|             "5d6e6a05a4b93618084f58d0": 3, | ||||
|             "5d6e6a42a4b9364f07165f52": 2 | ||||
|         }, | ||||
|         "Caliber23x75": { | ||||
|             "5f647f31b6238e5dd066e196": 60, | ||||
|             "5e85a9a6eacf8c039e4e2ac1": 30, | ||||
|             "5e85aa1a988a8701445df1f5": 10 | ||||
|         }, | ||||
|         "Caliber366TKM": { | ||||
|             "59e6542b86f77411dc52a77a": 5, | ||||
|             "59e655cb86f77411dc52a77b": 65, | ||||
|             "5f0596629e22f464da6bbdd9": 30 | ||||
|         }, | ||||
|         "Caliber40mmRU": { | ||||
|             "5656eb674bdc2d35148b457c": 1 | ||||
|         }, | ||||
|         "Caliber40x46": { | ||||
|             "5ede4739e0350d05467f73e8": 1, | ||||
|             "5ede47405b097655935d7d16": 1, | ||||
|             "5ede474b0c226a66f5402622": 1, | ||||
|             "5ede475339ee016e8c534742": 1, | ||||
|             "5ede475b549eed7c6d5c18fb": 1, | ||||
|             "5f0c892565703e5c461894e9": 1 | ||||
|         }, | ||||
|         "Caliber46x30": { | ||||
|             "5ba26844d4351e00334c9475": 70, | ||||
|             "64b6979341772715af0f9c39": 15, | ||||
|             "5ba2678ad4351e44f824b344": 10, | ||||
|             "5ba26835d4351e0035628ff5": 5 | ||||
|         }, | ||||
|         "Caliber545x39": { | ||||
|             "56dff0bed2720bb0668b4567": 5, | ||||
|             "56dff3afd2720bba668b4567": 40, | ||||
|             "56dff2ced2720bb4668b4567": 30, | ||||
|             "56dff061d2720bb5668b4567": 15, | ||||
|             "61962b617c6c7b169525f168": 5, | ||||
|             "56dfef82d2720bbd668b4567": 5 | ||||
|         }, | ||||
|         "Caliber556x45NATO": { | ||||
|             "5c0d5ae286f7741e46554302": 5, | ||||
|             "59e6920f86f77411d82aa167": 10, | ||||
|             "54527a984bdc2d4e668b4567": 50, | ||||
|             "60194943740c5d77f6705eea": 30, | ||||
|             "59e6906286f7746c9f75e847": 10, | ||||
|             "54527ac44bdc2d36668b4567": 5 | ||||
|         }, | ||||
|         "Caliber57x28": { | ||||
|             "5cc86840d7f00c002412c56c": 10, | ||||
|             "5cc80f8fe4a949033b0224a2": 15, | ||||
|             "5cc80f53e4a949000e1ea4f8": 28, | ||||
|             "5cc80f67e4a949035e43bbba": 7 | ||||
|         }, | ||||
|         "Caliber68x51": { | ||||
|             "6529302b8c26af6326029fb7": 1 | ||||
|         }, | ||||
|         "Caliber762x25TT": { | ||||
|             "5736026a245977644601dc61": 5, | ||||
|             "573603c924597764442bd9cb": 10, | ||||
|             "573603562459776430731618": 10 | ||||
|         }, | ||||
|         "Caliber762x35": { | ||||
|             "6196365d58ef8c428c287da1": 5, | ||||
|             "5fbe3ffdf8b6a877a729ea82": 55, | ||||
|             "619636be6db0f2477964e710": 30, | ||||
|             "64b8725c4b75259c590fa899": 10 | ||||
|         }, | ||||
|         "Caliber762x39": { | ||||
|             "5656d7c34bdc2d9d198b4587": 60, | ||||
|             "64b7af434b75259c590fa893": 35, | ||||
|             "59e0d99486f7744a32234762": 5 | ||||
|         }, | ||||
|         "Caliber762x51": { | ||||
|             "5e023e53d4353e3302577c4c": 60, | ||||
|             "58dd3ad986f77403051cba8f": 35, | ||||
|             "5a608bf24f39f98ffc77720e": 5 | ||||
|         }, | ||||
|         "Caliber762x54R": { | ||||
|             "5887431f2459777e1612938f": 50, | ||||
|             "59e77a2386f7742ee578960a": 25, | ||||
|             "5e023d34e8a400319a28ed44": 5 | ||||
|         }, | ||||
|         "Caliber86x70": { | ||||
|             "5fc382b6d6fa9c00c571bbc3": 75, | ||||
|             "5fc382c1016cce60e8341b20": 20, | ||||
|             "5fc275cf85fd526b824a571a": 5 | ||||
|         }, | ||||
|         "Caliber9x18PM": { | ||||
|             "5737201124597760fc4431f1": 35, | ||||
|             "573720e02459776143012541": 25, | ||||
|             "573718ba2459775a75491131": 25, | ||||
|             "57371aab2459775a77142f22": 10 | ||||
|         }, | ||||
|         "Caliber9x19PARA": { | ||||
|             "5c0d56a986f774449d5de529": 5, | ||||
|             "5efb0e16aeb21837e749c7ff": 25, | ||||
|             "56d59d3ad2720bdb418b4577": 65, | ||||
|             "5c925fa22e221601da359b7b": 5 | ||||
|         }, | ||||
|         "Caliber9x21": { | ||||
|             "5a26abfac4a28232980eabff": 12, | ||||
|             "5a269f97c4a282000b151807": 30, | ||||
|             "6576f93989f0062e741ba952": 12, | ||||
|             "5a26ac0ec4a28200741e1e18": 8 | ||||
|         }, | ||||
|         "Caliber9x33R": { | ||||
|             "62330bfadc5883093563729b": 8, | ||||
|             "62330c18744e5e31df12f516": 8, | ||||
|             "62330b3ed4dc74626d570b95": 2 | ||||
|         }, | ||||
|         "Caliber9x39": { | ||||
|             "57a0dfb82459774d3078b56c": 25, | ||||
|             "5c0d668f86f7747ccb7f13b2": 60, | ||||
|             "61962d879bb3d20b0946d385": 10, | ||||
|             "57a0e5022459774d1673f889": 5 | ||||
|         }, | ||||
|         "Caliber127x33": { | ||||
|             "66a0d1c87d0d369e270bb9de": 30, | ||||
|             "66a0d1f88486c69fce00fdf6": 60, | ||||
|             "66a0d1e0ed648d72fe064d06": 10 | ||||
|         } | ||||
|     }, | ||||
|     "bossAmmo": { | ||||
|         "Caliber1143x23ACP": { | ||||
|             "5ea2a8e200685063ec28c05a": 4, | ||||
|             "5efb0fc6aeb21837e749c801": 1, | ||||
|             "5efb0d4f4bc50b58e81710f3": 10, | ||||
|             "5e81f423763d9f754677bf2e": 18, | ||||
|             "5efb0cabfb3e451d70735af5": 10 | ||||
|         }, | ||||
|         "Caliber127x55": { | ||||
|             "5cadf6e5ae921500113bb973": 3, | ||||
|             "5cadf6ddae9215051e1c23b2": 12, | ||||
|             "5cadf6eeae921500134b2799": 8 | ||||
|         }, | ||||
|         "Caliber12g": { | ||||
|             "5d6e6806a4b936088465b17e": 7, | ||||
|             "64b8ee384b75259c590fa89b": 4, | ||||
|             "5d6e6911a4b9361bd5780d52": 3, | ||||
|             "5c0d591486f7744c505b416f": 5, | ||||
|             "5d6e6891a4b9361bd473feea": 2, | ||||
|             "5d6e68e6a4b9361c140bcfe0": 6, | ||||
|             "5d6e689ca4b9361bc8618956": 8, | ||||
|             "5d6e68c4a4b9361b93413f79": 8, | ||||
|             "5d6e68a8a4b9360b6c0d54e2": 3 | ||||
|         }, | ||||
|         "Caliber20g": { | ||||
|             "5d6e69c7a4b9360b6c0d54e4": 1, | ||||
|             "5d6e6a53a4b9361bd473feec": 4, | ||||
|             "5d6e6a05a4b93618084f58d0": 5, | ||||
|             "5d6e6a42a4b9364f07165f52": 5 | ||||
|         }, | ||||
|         "Caliber23x75": { | ||||
|             "5f647f31b6238e5dd066e196": 2, | ||||
|             "5e85a9a6eacf8c039e4e2ac1": 4, | ||||
|             "5e85aa1a988a8701445df1f5": 4 | ||||
|         }, | ||||
|         "Caliber366TKM": { | ||||
|             "59e6658b86f77411d949b250": 1, | ||||
|             "59e6542b86f77411dc52a77a": 2, | ||||
|             "59e655cb86f77411dc52a77b": 10, | ||||
|             "5f0596629e22f464da6bbdd9": 8 | ||||
|         }, | ||||
|         "Caliber40mmRU": { | ||||
|             "5656eb674bdc2d35148b457c": 1 | ||||
|         }, | ||||
|         "Caliber40x46": { | ||||
|             "5ede4739e0350d05467f73e8": 1, | ||||
|             "5ede47405b097655935d7d16": 1, | ||||
|             "5ede474b0c226a66f5402622": 1, | ||||
|             "5ede475339ee016e8c534742": 1, | ||||
|             "5ede475b549eed7c6d5c18fb": 1, | ||||
|             "5f0c892565703e5c461894e9": 1 | ||||
|         }, | ||||
|         "Caliber46x30": { | ||||
|             "5ba26812d4351e003201fef1": 2, | ||||
|             "5ba26844d4351e00334c9475": 4, | ||||
|             "5ba2678ad4351e44f824b344": 15, | ||||
|             "64b6979341772715af0f9c39": 15, | ||||
|             "5ba26835d4351e0035628ff5": 8 | ||||
|         }, | ||||
|         "Caliber545x39": { | ||||
|             "56dff3afd2720bba668b4567": 6, | ||||
|             "56dff2ced2720bb4668b4567": 12, | ||||
|             "56dff061d2720bb5668b4567": 20, | ||||
|             "61962b617c6c7b169525f168": 12, | ||||
|             "56dfef82d2720bbd668b4567": 9, | ||||
|             "56dff026d2720bb8668b4567": 8, | ||||
|             "5c0d5e4486f77478390952fe": 4 | ||||
|         }, | ||||
|         "Caliber556x45NATO": { | ||||
|             "5c0d5ae286f7741e46554302": 1, | ||||
|             "54527a984bdc2d4e668b4567": 7, | ||||
|             "60194943740c5d77f6705eea": 20, | ||||
|             "59e6906286f7746c9f75e847": 26, | ||||
|             "54527ac44bdc2d36668b4567": 30, | ||||
|             "59e690b686f7746c9f75e848": 7, | ||||
|             "601949593ae8f707c4608daa": 5 | ||||
|         }, | ||||
|         "Caliber57x28": { | ||||
|             "5cc80f8fe4a949033b0224a2": 5, | ||||
|             "5cc80f53e4a949000e1ea4f8": 21, | ||||
|             "5cc80f67e4a949035e43bbba": 15, | ||||
|             "5cc80f38e4a949001152b560": 12 | ||||
|         }, | ||||
|         "Caliber68x51": { | ||||
|             "6529302b8c26af6326029fb7": 10, | ||||
|             "6529243824cbe3c74a05e5c1": 5 | ||||
|         }, | ||||
|         "Caliber762x25TT": { | ||||
|             "5736026a245977644601dc61": 5, | ||||
|             "573603c924597764442bd9cb": 10, | ||||
|             "573603562459776430731618": 10 | ||||
|         }, | ||||
|         "Caliber762x35": { | ||||
|             "6196365d58ef8c428c287da1": 7, | ||||
|             "5fbe3ffdf8b6a877a729ea82": 6, | ||||
|             "619636be6db0f2477964e710": 23, | ||||
|             "64b8725c4b75259c590fa899": 20, | ||||
|             "5fd20ff893a8961fc660a954": 9 | ||||
|         }, | ||||
|         "Caliber762x39": { | ||||
|             "59e4cf5286f7741778269d8a": 4, | ||||
|             "5656d7c34bdc2d9d198b4587": 28, | ||||
|             "64b7af434b75259c590fa893": 33, | ||||
|             "59e0d99486f7744a32234762": 20, | ||||
|             "601aa3d2b2bcb34913271e6d": 12 | ||||
|         }, | ||||
|         "Caliber762x51": { | ||||
|             "5e023e53d4353e3302577c4c": 6, | ||||
|             "58dd3ad986f77403051cba8f": 27, | ||||
|             "5a608bf24f39f98ffc77720e": 19, | ||||
|             "5a6086ea4f39f99cd479502f": 9, | ||||
|             "5efb0c1bd79ff02a1f5e68d9": 2 | ||||
|         }, | ||||
|         "Caliber762x54R": { | ||||
|             "5e023cf8186a883be655e54f": 3, | ||||
|             "5887431f2459777e1612938f": 20, | ||||
|             "59e77a2386f7742ee578960a": 25, | ||||
|             "5e023d34e8a400319a28ed44": 22, | ||||
|             "560d61e84bdc2da74d8b4571": 15, | ||||
|             "5e023d48186a883be655e551": 10 | ||||
|         }, | ||||
|         "Caliber86x70": { | ||||
|             "5fc382b6d6fa9c00c571bbc3": 5, | ||||
|             "5fc382c1016cce60e8341b20": 8, | ||||
|             "5fc275cf85fd526b824a571a": 8, | ||||
|             "5fc382a9d724d907e2077dab": 5 | ||||
|         }, | ||||
|         "Caliber9x18PM": { | ||||
|             "57371e4124597760ff7b25f1": 3, | ||||
|             "5737201124597760fc4431f1": 5, | ||||
|             "573720e02459776143012541": 12, | ||||
|             "573718ba2459775a75491131": 18, | ||||
|             "57371aab2459775a77142f22": 12, | ||||
|             "573719df2459775a626ccbc2": 10 | ||||
|         }, | ||||
|         "Caliber9x19PARA": { | ||||
|             "5c0d56a986f774449d5de529": 9, | ||||
|             "5efb0e16aeb21837e749c7ff": 5, | ||||
|             "5a3c16fe86f77452b62de32a": 4, | ||||
|             "56d59d3ad2720bdb418b4577": 18, | ||||
|             "5c925fa22e221601da359b7b": 22, | ||||
|             "5efb0da7a29a85116f6ea05f": 9 | ||||
|         }, | ||||
|         "Caliber9x21": { | ||||
|             "5a269f97c4a282000b151807": 8, | ||||
|             "6576f93989f0062e741ba952": 18, | ||||
|             "5a26ac0ec4a28200741e1e18": 18, | ||||
|             "6576f4708ca9c4381d16cd9d": 8 | ||||
|         }, | ||||
|         "Caliber9x33R": { | ||||
|             "62330c18744e5e31df12f516": 9, | ||||
|             "62330b3ed4dc74626d570b95": 6 | ||||
|         }, | ||||
|         "Caliber9x39": { | ||||
|             "5c0d668f86f7747ccb7f13b2": 9, | ||||
|             "61962d879bb3d20b0946d385": 25, | ||||
|             "57a0e5022459774d1673f889": 25, | ||||
|             "5c0d688c86f77413ae3407b2": 12 | ||||
|         }, | ||||
|         "Caliber127x33": { | ||||
|             "66a0d1c87d0d369e270bb9de": 3, | ||||
|             "66a0d1f88486c69fce00fdf6": 30, | ||||
|             "66a0d1e0ed648d72fe064d06": 25,  | ||||
|             "668fe62ac62660a5d8071446": 12 | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,457 @@ | |||
| { | ||||
|     "pmcUSEC": { | ||||
|         "appearance": { | ||||
|             "body": { | ||||
|                 "5cde95d97d6c8b647a3769b0": 1, | ||||
|                 "66546f823b51a4d21e0d17d7": 1, | ||||
|                 "5d1f56a686f7744bce0ee9eb": 1, | ||||
|                 "5d1f56c686f7744bcd13459c": 3, | ||||
|                 "637b945722e2a933ed0e33c8": 3, | ||||
|                 "6571cb0923aa6d72760a7f8f": 3, | ||||
|                 "5fd3e9f71b735718c25cd9f8": 3, | ||||
|                 "642d9bbf6c06444bf7033855": 3, | ||||
|                 "6033a35f80ae5e2f970ba6bb": 5, | ||||
|                 "66043728333907134309d647": 5, | ||||
|                 "5d1f56e486f7744bce0ee9ed": 5, | ||||
|                 "6295e8c3e08ed747e64aea00": 5, | ||||
|                 "642c18b8a6a0660b560fb31c": 5, | ||||
|                 "66acbe49dc61999a6a03d4d6": 5 | ||||
|             }, | ||||
|             "feet": { | ||||
|                 "5cde95ef7d6c8b04713c4f2d": 1, | ||||
|                 "5d1f58ed86f7744bcb0acd1c": 1, | ||||
|                 "5d1f590486f7744bcd13459e": 3, | ||||
|                 "642d4d8eb6b75d4c89077cf9": 3, | ||||
|                 "6033a3fee29c9f6c9b14e74e": 3, | ||||
|                 "5fcf940bce1ba36a513bb9cc": 5, | ||||
|                 "660436487502eca33a08cac8": 5, | ||||
|                 "6571cad4c8673f00290f5657": 5, | ||||
|                 "637ba17aa10a96c2b605dbc2": 5, | ||||
|                 "5d1f591186f7744bcc048755": 5, | ||||
|                 "6295e944e9de5e7b3751c4da": 5, | ||||
|                 "642c19360a69698d1b049e12": 5, | ||||
|                 "66acc8f719271bd6d00dec0b": 5 | ||||
|             }, | ||||
|             "hands": { | ||||
|                 "5cde95fa7d6c8b04737c2d13": 1 | ||||
|             }, | ||||
|             "head": { | ||||
|                 "5cde96047d6c8b20b577f016": 1, | ||||
|                 "5fdb4139e4ed5b5ea251e4ed": 1, | ||||
|                 "5fdb5950f5264a66150d1c6e": 1, | ||||
|                 "60a6aa8fd559ae040d0d951f": 1, | ||||
|                 "619f9e338858a474c8685cc9": 1, | ||||
|                 "62aca6a1310e67685a2fc2e7": 1, | ||||
|                 "6574aabee0423b9ebe0c79cf": 1 | ||||
|             } | ||||
|         } | ||||
|     }, | ||||
|     "pmcBEAR": { | ||||
|         "appearance": { | ||||
|             "body": { | ||||
|                 "5cc0858d14c02e000c6bea66": 1, | ||||
|                 "66546f823b51a4d21e0d17d7": 1, | ||||
|                 "5d1f565786f7743f8362bcd5": 1, | ||||
|                 "5fce3e0cfe40296c1d5fd782": 3, | ||||
|                 "6377266693a3b4967208e42b": 3, | ||||
|                 "5d1f564b86f7744bcb0acd16": 3, | ||||
|                 "6295e698e9de5e7b3751c47a": 3, | ||||
|                 "642e8ae07e17c882400c4f87": 3, | ||||
|                 "5d1f568486f7744bca3f0b98": 3, | ||||
|                 "657058fddf9b3231400e9188": 5, | ||||
|                 "6033a31e9ec839204e6a2f3e": 5, | ||||
|                 "66043cc27502eca33a08cad0": 5, | ||||
|                 "5fce3e47fe40296c1d5fd784": 5, | ||||
|                 "642ed297ac11c9eaf10d87e8": 5, | ||||
|                 "66acec1dc94f4bf5bc063a16": 5 | ||||
|             }, | ||||
|             "feet": { | ||||
|                 "5cc085bb14c02e000e67a5c5": 1, | ||||
|                 "5d1f58bd86f7744bce0ee9ef": 1, | ||||
|                 "6377315993a3b4967208e437": 3, | ||||
|                 "5d1f588e86f7744bcc048753": 3, | ||||
|                 "65707a89f5a6f1412f0c5f7b": 3, | ||||
|                 "642ed40af5bdf1c04e01952e": 3, | ||||
|                 "5fce3e965a9f8c40685693bc": 3, | ||||
|                 "6295e63de08ed747e64ae991": 5, | ||||
|                 "66043cf87502eca33a08cad2": 5, | ||||
|                 "6033a3d8ed2e0509b15f9031": 5, | ||||
|                 "5d1f58cb86f7744bca3f0b9a": 5, | ||||
|                 "5d1f58a086f7743f8362bcd9": 5, | ||||
|                 "642e71620a69698d1b049f0a": 5, | ||||
|                 "66acebd4ede86671bb09584b": 5 | ||||
|             }, | ||||
|             "hands": { | ||||
|                 "5cc0876314c02e000c6bea6b": 1 | ||||
|             }, | ||||
|             "head": { | ||||
|                 "5cc084dd14c02e000b0550a3": 1, | ||||
|                 "5fdb50bb2b730a787b3f78cf": 1, | ||||
|                 "5fdb7571e4ed5b5ea251e529": 1, | ||||
|                 "60a6aaad42fd2735e4589978": 1, | ||||
|                 "619f94f5b90286142b59d45f": 1, | ||||
|                 "62a9e7d15ea3b87d6f642a28": 1, | ||||
|                 "6574aa9a1b144de18c0fba45": 1 | ||||
|             } | ||||
|         } | ||||
|     }, | ||||
|     "springEarly": { | ||||
|         "pmcUSEC": { | ||||
|             "appearance": { | ||||
|                 "body": { | ||||
|                     "5d1f56c686f7744bcd13459c": 1, | ||||
|                     "5fd3e9f71b735718c25cd9f8": 1, | ||||
|                     "66043728333907134309d647": 1, | ||||
|                     "66acbe49dc61999a6a03d4d6": 1, | ||||
|                     "660437e57502eca33a08caca": 1, | ||||
|                     "5d1f56f186f7744bcb0acd1a": 1, | ||||
|                     "5d1f56ff86f7743f8362bcd7": 1, | ||||
|                     "5d1f56a686f7744bce0ee9eb": 2, | ||||
|                     "5e9da17386f774054b6f79a3": 2, | ||||
|                     "5e4bb35286f77406a511c9bc": 2, | ||||
|                     "5d1f56e486f7744bce0ee9ed": 2 | ||||
|                 }, | ||||
|                 "feet": { | ||||
|                     "642d4d8eb6b75d4c89077cf9": 1, | ||||
|                     "5fcf940bce1ba36a513bb9cc": 1, | ||||
|                     "66acc8f719271bd6d00dec0b": 1, | ||||
|                     "6295e944e9de5e7b3751c4da": 1, | ||||
|                     "5d1f592286f7743f8362bcdb": 1, | ||||
|                     "5e4bb3b586f77406812bd579": 1, | ||||
|                     "5d1f590486f7744bcd13459e": 3, | ||||
|                     "5d1f58ed86f7744bcb0acd1c": 3 | ||||
|                 }, | ||||
|                 "hands": { | ||||
|                     "5cde95fa7d6c8b04737c2d13": 1 | ||||
|                 }, | ||||
|                 "head": { | ||||
|                     "5cde96047d6c8b20b577f016": 1, | ||||
|                     "5fdb4139e4ed5b5ea251e4ed": 1, | ||||
|                     "5fdb5950f5264a66150d1c6e": 1, | ||||
|                     "60a6aa8fd559ae040d0d951f": 1, | ||||
|                     "619f9e338858a474c8685cc9": 1, | ||||
|                     "62aca6a1310e67685a2fc2e7": 1, | ||||
|                     "6574aabee0423b9ebe0c79cf": 1 | ||||
|                 } | ||||
|             } | ||||
|         }, | ||||
|         "pmcBEAR": { | ||||
|             "appearance": { | ||||
|                 "body": { | ||||
|                     "657058fddf9b3231400e9188": 1, | ||||
|                     "6033a31e9ec839204e6a2f3e": 1, | ||||
|                     "5d1f567786f7744bcc04874f": 1, | ||||
|                     "5e9d9fa986f774054d6b89f2": 1, | ||||
|                     "5f5e401747344c2e4f6c42c5": 1, | ||||
|                     "642e8ae07e17c882400c4f87": 2, | ||||
|                     "5d1f568486f7744bca3f0b98": 2, | ||||
|                     "66acec1dc94f4bf5bc063a16": 2, | ||||
|                     "5e4bb31586f7740695730568": 2 | ||||
|                 }, | ||||
|                 "feet": { | ||||
|                     "5d1f58bd86f7744bce0ee9ef": 1, | ||||
|                     "6377315993a3b4967208e437": 1, | ||||
|                     "66043cf87502eca33a08cad2": 1, | ||||
|                     "5d1f58cb86f7744bca3f0b9a": 1, | ||||
|                     "5d1f58a086f7743f8362bcd9": 1, | ||||
|                     "617be9e4e02b3b3fa50fa8f2": 1, | ||||
|                     "5f5e40400bc58666c37e7819": 1, | ||||
|                     "66acebd4ede86671bb09584b": 3, | ||||
|                     "5d1f58ab86f7743014162042": 3 | ||||
|                 }, | ||||
|                 "hands": { | ||||
|                     "5cc0876314c02e000c6bea6b": 1 | ||||
|                 }, | ||||
|                 "head": { | ||||
|                     "5cc084dd14c02e000b0550a3": 1, | ||||
|                     "5fdb50bb2b730a787b3f78cf": 1, | ||||
|                     "5fdb7571e4ed5b5ea251e529": 1, | ||||
|                     "60a6aaad42fd2735e4589978": 1, | ||||
|                     "619f94f5b90286142b59d45f": 1, | ||||
|                     "62a9e7d15ea3b87d6f642a28": 1, | ||||
|                     "6574aa9a1b144de18c0fba45": 1 | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     }, | ||||
|     "spring": { | ||||
|         "pmcUSEC": { | ||||
|             "appearance": { | ||||
|                 "body": { | ||||
|                     "5cde95d97d6c8b647a3769b0": 1, | ||||
|                     "5fd3e9f71b735718c25cd9f8": 1, | ||||
|                     "66043728333907134309d647": 1, | ||||
|                     "5d4da0cb86f77450fe0a6629": 1, | ||||
|                     "5d1f56f186f7744bcb0acd1a": 1, | ||||
|                     "5f5e4075df4f3100376a8138": 1 | ||||
|                 }, | ||||
|                 "feet": { | ||||
|                     "5cde95ef7d6c8b04713c4f2d": 1, | ||||
|                     "6033a3fee29c9f6c9b14e74e": 1, | ||||
|                     "660436487502eca33a08cac8": 1, | ||||
|                     "6571cad4c8673f00290f5657": 1, | ||||
|                     "66acc8f719271bd6d00dec0b": 1, | ||||
|                     "5d1f592286f7743f8362bcdb": 1, | ||||
|                     "642d6941ff5ecad7810a8a61": 1, | ||||
|                     "5e9dcadd86f7743e20652f23": 1 | ||||
|                 }, | ||||
|                 "hands": { | ||||
|                     "5cde95fa7d6c8b04737c2d13": 1 | ||||
|                 }, | ||||
|                 "head": { | ||||
|                     "5cde96047d6c8b20b577f016": 1, | ||||
|                     "5fdb4139e4ed5b5ea251e4ed": 1, | ||||
|                     "5fdb5950f5264a66150d1c6e": 1, | ||||
|                     "60a6aa8fd559ae040d0d951f": 1, | ||||
|                     "619f9e338858a474c8685cc9": 1, | ||||
|                     "62aca6a1310e67685a2fc2e7": 1, | ||||
|                     "6574aabee0423b9ebe0c79cf": 1 | ||||
|                 } | ||||
|             } | ||||
|         }, | ||||
|         "pmcBEAR": { | ||||
|             "appearance": { | ||||
|                 "body": { | ||||
|                     "5cc0858d14c02e000c6bea66": 1, | ||||
|                     "5d1f564b86f7744bcb0acd16": 1, | ||||
|                     "6295e698e9de5e7b3751c47a": 1, | ||||
|                     "6033a31e9ec839204e6a2f3e": 1, | ||||
|                     "5fce3e47fe40296c1d5fd784": 1, | ||||
|                     "617bca4b4013b06b0b78df2a": 1, | ||||
|                     "5df89f1f86f77412631087ea": 1 | ||||
|                 }, | ||||
|                 "feet": { | ||||
|                     "5cc085bb14c02e000e67a5c5": 1, | ||||
|                     "5d1f588e86f7744bcc048753": 1, | ||||
|                     "66043cf87502eca33a08cad2": 1, | ||||
|                     "6033a3d8ed2e0509b15f9031": 1, | ||||
|                     "642e71620a69698d1b049f0a": 1, | ||||
|                     "617be9e4e02b3b3fa50fa8f2": 1, | ||||
|                     "642eea6f881906a7fe086841": 1, | ||||
|                     "5df89f8f86f77412672a1e38": 1, | ||||
|                     "5e9dc97c86f774054c19ac9a": 1, | ||||
|                     "5e4bb39386f774067f79de05": 1 | ||||
|                 }, | ||||
|                 "hands": { | ||||
|                     "5cc0876314c02e000c6bea6b": 1 | ||||
|                 }, | ||||
|                 "head": { | ||||
|                     "5cc084dd14c02e000b0550a3": 1, | ||||
|                     "5fdb50bb2b730a787b3f78cf": 1, | ||||
|                     "5fdb7571e4ed5b5ea251e529": 1, | ||||
|                     "60a6aaad42fd2735e4589978": 1, | ||||
|                     "619f94f5b90286142b59d45f": 1, | ||||
|                     "62a9e7d15ea3b87d6f642a28": 1, | ||||
|                     "6574aa9a1b144de18c0fba45": 1 | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     }, | ||||
|     "summer": { | ||||
|         "pmcUSEC": { | ||||
|             "appearance": { | ||||
|                 "body": { | ||||
|                     "5cde95d97d6c8b647a3769b0": 1, | ||||
|                     "5d1f56c686f7744bcd13459c": 1, | ||||
|                     "5fd3e9f71b735718c25cd9f8": 1, | ||||
|                     "66043728333907134309d647": 1, | ||||
|                     "5d4da0cb86f77450fe0a6629": 1, | ||||
|                     "66acbe49dc61999a6a03d4d6": 1, | ||||
|                     "64ef3efdb63b74469b6c1499": 1, | ||||
|                     "642c18b8a6a0660b560fb31c": 1, | ||||
|                     "5d1f56f186f7744bcb0acd1a": 1, | ||||
|                     "5f5e4075df4f3100376a8138": 1 | ||||
|                 }, | ||||
|                 "feet": { | ||||
|                     "5cde95ef7d6c8b04713c4f2d": 1, | ||||
|                     "6033a3fee29c9f6c9b14e74e": 1, | ||||
|                     "660436487502eca33a08cac8": 1, | ||||
|                     "6571cad4c8673f00290f5657": 1, | ||||
|                     "66acc8f719271bd6d00dec0b": 1, | ||||
|                     "5d1f593286f7743014162044": 1, | ||||
|                     "5d1f592286f7743f8362bcdb": 1, | ||||
|                     "642d6941ff5ecad7810a8a61": 1, | ||||
|                     "5e9dcadd86f7743e20652f23": 1 | ||||
|                 }, | ||||
|                 "hands": { | ||||
|                     "5cde95fa7d6c8b04737c2d13": 1 | ||||
|                 }, | ||||
|                 "head": { | ||||
|                     "5cde96047d6c8b20b577f016": 1, | ||||
|                     "5fdb4139e4ed5b5ea251e4ed": 1, | ||||
|                     "5fdb5950f5264a66150d1c6e": 1, | ||||
|                     "60a6aa8fd559ae040d0d951f": 1, | ||||
|                     "619f9e338858a474c8685cc9": 1, | ||||
|                     "62aca6a1310e67685a2fc2e7": 1, | ||||
|                     "6574aabee0423b9ebe0c79cf": 1 | ||||
|                 } | ||||
|             } | ||||
|         }, | ||||
|         "pmcBEAR": { | ||||
|             "appearance": { | ||||
|                 "body": { | ||||
|                     "5cc0858d14c02e000c6bea66": 1, | ||||
|                     "5d1f564b86f7744bcb0acd16": 1, | ||||
|                     "6295e698e9de5e7b3751c47a": 1, | ||||
|                     "6033a31e9ec839204e6a2f3e": 1, | ||||
|                     "5fce3e47fe40296c1d5fd784": 1, | ||||
|                     "617bca4b4013b06b0b78df2a": 1, | ||||
|                     "64ef3efdb63b74469b6c1499": 1, | ||||
|                     "5df89f1f86f77412631087ea": 1, | ||||
|                     "5e9d9fa986f774054d6b89f2": 1 | ||||
|                 }, | ||||
|                 "feet": { | ||||
|                     "5cc085bb14c02e000e67a5c5": 1, | ||||
|                     "5d1f588e86f7744bcc048753": 1, | ||||
|                     "66043cf87502eca33a08cad2": 1, | ||||
|                     "6033a3d8ed2e0509b15f9031": 1, | ||||
|                     "642e71620a69698d1b049f0a": 1, | ||||
|                     "617be9e4e02b3b3fa50fa8f2": 1, | ||||
|                     "642eea6f881906a7fe086841": 1, | ||||
|                     "5df89f8f86f77412672a1e38": 1, | ||||
|                     "5e9dc97c86f774054c19ac9a": 1, | ||||
|                     "5e4bb39386f774067f79de05": 1 | ||||
|                 }, | ||||
|                 "hands": { | ||||
|                     "5cc0876314c02e000c6bea6b": 1 | ||||
|                 }, | ||||
|                 "head": { | ||||
|                     "5cc084dd14c02e000b0550a3": 1, | ||||
|                     "5fdb50bb2b730a787b3f78cf": 1, | ||||
|                     "5fdb7571e4ed5b5ea251e529": 1, | ||||
|                     "60a6aaad42fd2735e4589978": 1, | ||||
|                     "619f94f5b90286142b59d45f": 1, | ||||
|                     "62a9e7d15ea3b87d6f642a28": 1, | ||||
|                     "6574aa9a1b144de18c0fba45": 1 | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     }, | ||||
|     "autumn": { | ||||
|         "pmcUSEC": { | ||||
|             "appearance": { | ||||
|                 "body": { | ||||
|                     "5d1f56c686f7744bcd13459c": 1, | ||||
|                     "637b945722e2a933ed0e33c8": 1, | ||||
|                     "6571cb0923aa6d72760a7f8f": 1, | ||||
|                     "6033a35f80ae5e2f970ba6bb": 1, | ||||
|                     "5d1f56e486f7744bce0ee9ed": 1, | ||||
|                     "66acbe49dc61999a6a03d4d6": 1, | ||||
|                     "660437e57502eca33a08caca": 1, | ||||
|                     "64ef3efdb63b74469b6c1499": 1, | ||||
|                     "5d1f56ff86f7743f8362bcd7": 1 | ||||
|                 }, | ||||
|                 "feet": { | ||||
|                     "642d4d8eb6b75d4c89077cf9": 1, | ||||
|                     "5fcf940bce1ba36a513bb9cc": 1, | ||||
|                     "637ba17aa10a96c2b605dbc2": 1, | ||||
|                     "6295e944e9de5e7b3751c4da": 1, | ||||
|                     "5e4bb3b586f77406812bd579": 1, | ||||
|                     "5f5e40a06760b4138443b341": 1 | ||||
|                 }, | ||||
|                 "hands": { | ||||
|                     "5cde95fa7d6c8b04737c2d13": 1 | ||||
|                 }, | ||||
|                 "head": { | ||||
|                     "5cde96047d6c8b20b577f016": 1, | ||||
|                     "5fdb4139e4ed5b5ea251e4ed": 1, | ||||
|                     "5fdb5950f5264a66150d1c6e": 1, | ||||
|                     "60a6aa8fd559ae040d0d951f": 1, | ||||
|                     "619f9e338858a474c8685cc9": 1, | ||||
|                     "62aca6a1310e67685a2fc2e7": 1, | ||||
|                     "6574aabee0423b9ebe0c79cf": 1 | ||||
|                 } | ||||
|             } | ||||
|         }, | ||||
|         "pmcBEAR": { | ||||
|             "appearance": { | ||||
|                 "body": { | ||||
|                     "6377266693a3b4967208e42b": 1, | ||||
|                     "5d1f568486f7744bca3f0b98": 1, | ||||
|                     "657058fddf9b3231400e9188": 1, | ||||
|                     "642ed297ac11c9eaf10d87e8": 1, | ||||
|                     "5d1f567786f7744bcc04874f": 1, | ||||
|                     "64ef3efdb63b74469b6c1499": 1, | ||||
|                     "6430119aac11c9eaf10d881b": 1, | ||||
|                     "5f5e401747344c2e4f6c42c5": 1 | ||||
|                 }, | ||||
|                 "feet": { | ||||
|                     "5d1f58bd86f7744bce0ee9ef": 1, | ||||
|                     "6377315993a3b4967208e437": 1, | ||||
|                     "642ed40af5bdf1c04e01952e": 1, | ||||
|                     "6295e63de08ed747e64ae991": 1, | ||||
|                     "5d1f58a086f7743f8362bcd9": 1, | ||||
|                     "66043d7ac8949a435906e434": 1, | ||||
|                     "5d1f58ab86f7743014162042": 1, | ||||
|                     "5f5e40400bc58666c37e7819": 1 | ||||
|                 }, | ||||
|                 "hands": { | ||||
|                     "5cc0876314c02e000c6bea6b": 1 | ||||
|                 }, | ||||
|                 "head": { | ||||
|                     "5cc084dd14c02e000b0550a3": 1, | ||||
|                     "5fdb50bb2b730a787b3f78cf": 1, | ||||
|                     "5fdb7571e4ed5b5ea251e529": 1, | ||||
|                     "60a6aaad42fd2735e4589978": 1, | ||||
|                     "619f94f5b90286142b59d45f": 1, | ||||
|                     "62a9e7d15ea3b87d6f642a28": 1, | ||||
|                     "6574aa9a1b144de18c0fba45": 1 | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     }, | ||||
|     "winter": { | ||||
|         "pmcUSEC": { | ||||
|             "appearance": { | ||||
|                 "body": { | ||||
|                     "5d1f56a686f7744bce0ee9eb": 1, | ||||
|                     "5e9da17386f774054b6f79a3": 1, | ||||
|                     "5e4bb35286f77406a511c9bc": 1, | ||||
|                     "5d1f56e486f7744bce0ee9ed": 1 | ||||
|                 }, | ||||
|                 "feet": { | ||||
|                     "5d1f590486f7744bcd13459e": 1, | ||||
|                     "5d1f58ed86f7744bcb0acd1c": 1 | ||||
|                 }, | ||||
|                 "hands": { | ||||
|                     "5cde95fa7d6c8b04737c2d13": 1 | ||||
|                 }, | ||||
|                 "head": { | ||||
|                     "5cde96047d6c8b20b577f016": 1, | ||||
|                     "5fdb4139e4ed5b5ea251e4ed": 1, | ||||
|                     "5fdb5950f5264a66150d1c6e": 1, | ||||
|                     "60a6aa8fd559ae040d0d951f": 1, | ||||
|                     "619f9e338858a474c8685cc9": 1, | ||||
|                     "62aca6a1310e67685a2fc2e7": 1, | ||||
|                     "6574aabee0423b9ebe0c79cf": 1 | ||||
|                 } | ||||
|             } | ||||
|         }, | ||||
|         "pmcBEAR": { | ||||
|             "appearance": { | ||||
|                 "body": { | ||||
|                     "642e8ae07e17c882400c4f87": 1, | ||||
|                     "5d1f568486f7744bca3f0b98": 1, | ||||
|                     "66acec1dc94f4bf5bc063a16": 1, | ||||
|                     "5e4bb31586f7740695730568": 1 | ||||
|                 }, | ||||
|                 "feet": { | ||||
|                     "66acebd4ede86671bb09584b": 1, | ||||
|                     "5d1f58ab86f7743014162042": 1 | ||||
|                 }, | ||||
|                 "hands": { | ||||
|                     "5cc0876314c02e000c6bea6b": 1 | ||||
|                 }, | ||||
|                 "head": { | ||||
|                     "5cc084dd14c02e000b0550a3": 1, | ||||
|                     "5fdb50bb2b730a787b3f78cf": 1, | ||||
|                     "5fdb7571e4ed5b5ea251e529": 1, | ||||
|                     "60a6aaad42fd2735e4589978": 1, | ||||
|                     "619f94f5b90286142b59d45f": 1, | ||||
|                     "62a9e7d15ea3b87d6f642a28": 1, | ||||
|                     "6574aa9a1b144de18c0fba45": 1 | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							|  | @ -0,0 +1,471 @@ | |||
| {     | ||||
|     "scavAmmo": { | ||||
|         "Caliber1143x23ACP": { | ||||
|             "5efb0fc6aeb21837e749c801": 1, | ||||
|             "5efb0d4f4bc50b58e81710f3": 3 | ||||
|         }, | ||||
|         "Caliber127x55": { | ||||
|             "5cadf6e5ae921500113bb973": 1 | ||||
|         }, | ||||
|         "Caliber12g": { | ||||
|             "5d6e6772a4b936088465b17c": 2, | ||||
|             "5d6e6806a4b936088465b17e": 2, | ||||
|             "5d6e67fba4b9361bc73bc779": 2, | ||||
|             "560d5e524bdc2d25448b4571": 2, | ||||
|             "5d6e6869a4b9361c140bcfde": 1, | ||||
|             "5d6e68b3a4b9361bca7e50b5": 1, | ||||
|             "58820d1224597753c90aeb13": 1, | ||||
|             "5d6e68dea4b9361bcc29e659": 1, | ||||
|             "5d6e6891a4b9361bd473feea": 1, | ||||
|             "5d6e68e6a4b9361c140bcfe0": 1, | ||||
|             "5d6e689ca4b9361bc8618956": 1 | ||||
|         }, | ||||
|         "Caliber20g": { | ||||
|             "5d6e695fa4b936359b35d852": 2, | ||||
|             "5d6e69b9a4b9361bc8618958": 2, | ||||
|             "5a38ebd9c4a282000d722a5b": 2, | ||||
|             "5d6e69c7a4b9360b6c0d54e4": 1, | ||||
|             "5d6e6a53a4b9361bd473feec": 1 | ||||
|         }, | ||||
|         "Caliber23x75": { | ||||
|             "5f647f31b6238e5dd066e196": 3, | ||||
|             "5e85a9a6eacf8c039e4e2ac1": 1 | ||||
|         }, | ||||
|         "Caliber366TKM": { | ||||
|             "59e6658b86f77411d949b250": 3, | ||||
|             "59e6542b86f77411dc52a77a": 1 | ||||
|         }, | ||||
|         "Caliber40mmRU": { | ||||
|             "5656eb674bdc2d35148b457c": 1 | ||||
|         }, | ||||
|         "Caliber40x46": { | ||||
|             "5ede4739e0350d05467f73e8": 1, | ||||
|             "5ede47405b097655935d7d16": 1, | ||||
|             "5ede474b0c226a66f5402622": 1, | ||||
|             "5ede475339ee016e8c534742": 1, | ||||
|             "5ede475b549eed7c6d5c18fb": 1, | ||||
|             "5f0c892565703e5c461894e9": 1 | ||||
|         }, | ||||
|         "Caliber46x30": { | ||||
|             "5ba26812d4351e003201fef1": 3, | ||||
|             "5ba26844d4351e00334c9475": 1 | ||||
|         }, | ||||
|         "Caliber545x39": { | ||||
|             "56dff216d2720bbd668b4568": 1, | ||||
|             "56dff338d2720bbd668b4569": 4, | ||||
|             "56dff421d2720b5f5a8b4567": 4, | ||||
|             "56dff4ecd2720b5f5a8b4568": 2, | ||||
|             "56dff4a2d2720bbd668b456a": 4, | ||||
|             "56dff0bed2720bb0668b4567": 3, | ||||
|             "56dff3afd2720bba668b4567": 1 | ||||
|         }, | ||||
|         "Caliber556x45NATO": { | ||||
|             "59e6927d86f77411da468256": 2, | ||||
|             "59e6918f86f7746c9f75e849": 2, | ||||
|             "59e68f6f86f7746c9f75e846": 4, | ||||
|             "59e6920f86f77411d82aa167": 5, | ||||
|             "54527a984bdc2d4e668b4567": 1 | ||||
|         }, | ||||
|         "Caliber57x28": { | ||||
|             "5cc86832d7f00c000d3a6e6c": 2, | ||||
|             "5cc80f79e4a949033c7343b2": 3, | ||||
|             "5cc86840d7f00c002412c56c": 3, | ||||
|             "5cc80f8fe4a949033b0224a2": 1, | ||||
|             "5cc80f53e4a949000e1ea4f8": 1 | ||||
|         }, | ||||
|         "Caliber68x51": { | ||||
|             "6529302b8c26af6326029fb7": 1 | ||||
|         }, | ||||
|         "Caliber762x25TT": { | ||||
|             "573602322459776445391df1": 2, | ||||
|             "573601b42459776410737435": 2, | ||||
|             "5735fdcd2459776445391d61": 1, | ||||
|             "5736026a245977644601dc61": 1 | ||||
|         }, | ||||
|         "Caliber762x35": { | ||||
|             "6196365d58ef8c428c287da1": 1, | ||||
|             "6196364158ef8c428c287d9f": 6, | ||||
|             "5fbe3ffdf8b6a877a729ea82": 3 | ||||
|         }, | ||||
|         "Caliber762x39": { | ||||
|             "59e4d3d286f774176a36250a": 2, | ||||
|             "64b7af734b75259c590fa895": 2, | ||||
|             "64b7af5a8532cf95ee0a0dbd": 6, | ||||
|             "59e4d24686f7741776641ac7": 4, | ||||
|             "59e4cf5286f7741778269d8a": 2, | ||||
|             "5656d7c34bdc2d9d198b4587": 1 | ||||
|         }, | ||||
|         "Caliber762x51": { | ||||
|             "5e023e88277cce2b522ff2b1": 2, | ||||
|             "5e023e6e34d52a55c3304f71": 2, | ||||
|             "5e023e53d4353e3302577c4c": 1 | ||||
|         }, | ||||
|         "Caliber762x54R": { | ||||
|             "64b8f7c241772715af0f9c3d": 2, | ||||
|             "64b8f7b5389d7ffd620ccba2": 2, | ||||
|             "64b8f7968532cf95ee0a0dbf": 2, | ||||
|             "5e023cf8186a883be655e54f": 2, | ||||
|             "5887431f2459777e1612938f": 1 | ||||
|         }, | ||||
|         "Caliber86x70": { | ||||
|             "5fc382b6d6fa9c00c571bbc3": 2, | ||||
|             "5fc382c1016cce60e8341b20": 1 | ||||
|         }, | ||||
|         "Caliber9x18PM": { | ||||
|             "5737218f245977612125ba51": 5, | ||||
|             "57372140245977611f70ee91": 5, | ||||
|             "5737207f24597760ff7b25f2": 2, | ||||
|             "573719762459775a626ccbc1": 3, | ||||
|             "57371f8d24597761006c6a81": 3, | ||||
|             "57371f2b24597761224311f1": 5, | ||||
|             "57371eb62459776125652ac1": 1, | ||||
|             "57371b192459775a9f58a5e0": 1, | ||||
|             "57371e4124597760ff7b25f1": 1 | ||||
|         }, | ||||
|         "Caliber9x19PARA": { | ||||
|             "5efb0e16aeb21837e749c7ff": 1, | ||||
|             "58864a4f2459770fcc257101": 7, | ||||
|             "5a3c16fe86f77452b62de32a": 12, | ||||
|             "5c3df7d588a4501f290594e5": 6, | ||||
|             "64b7bbb74b75259c590fa897": 4, | ||||
|             "56d59d3ad2720bdb418b4577": 2 | ||||
|         }, | ||||
|         "Caliber9x21": { | ||||
|             "5a26ac06c4a282000c5a90a8": 5, | ||||
|             "5a26abfac4a28232980eabff": 3, | ||||
|             "5a269f97c4a282000b151807": 1 | ||||
|         }, | ||||
|         "Caliber9x33R": { | ||||
|             "62330c40bdd19b369e1e53d1": 5, | ||||
|             "62330bfadc5883093563729b": 3, | ||||
|             "62330c18744e5e31df12f516": 1 | ||||
|         }, | ||||
|         "Caliber9x39": { | ||||
|             "6576f96220d53a5b8f3e395e": 7, | ||||
|             "57a0dfb82459774d3078b56c": 5, | ||||
|             "5c0d668f86f7747ccb7f13b2": 1 | ||||
|         }, | ||||
|         "Caliber127x33": { | ||||
|             "66a0d1c87d0d369e270bb9de": 10, | ||||
|             "66a0d1f88486c69fce00fdf6": 1 | ||||
|         } | ||||
|     }, | ||||
|     "pmcAmmo": { | ||||
|         "Caliber1143x23ACP": { | ||||
|             "5ea2a8e200685063ec28c05a": 20, | ||||
|             "5efb0d4f4bc50b58e81710f3": 10, | ||||
|             "5e81f423763d9f754677bf2e": 30, | ||||
|             "5efb0cabfb3e451d70735af5": 20 | ||||
|         }, | ||||
|         "Caliber127x55": { | ||||
|             "5cadf6e5ae921500113bb973": 15, | ||||
|             "5cadf6ddae9215051e1c23b2": 50, | ||||
|             "5cadf6eeae921500134b2799": 35 | ||||
|         }, | ||||
|         "Caliber12g": { | ||||
|             "5d6e6806a4b936088465b17e": 10, | ||||
|             "64b8ee384b75259c590fa89b": 20, | ||||
|             "5d6e6911a4b9361bd5780d52": 20, | ||||
|             "5c0d591486f7744c505b416f": 5, | ||||
|             "5d6e68e6a4b9361c140bcfe0": 5, | ||||
|             "5d6e689ca4b9361bc8618956": 5, | ||||
|             "5d6e68c4a4b9361b93413f79": 35, | ||||
|             "5d6e68a8a4b9360b6c0d54e2": 15 | ||||
|         }, | ||||
|         "Caliber20g": { | ||||
|             "5d6e6a5fa4b93614ec501745": 15, | ||||
|             "5d6e6a53a4b9361bd473feec": 15, | ||||
|             "5d6e6a05a4b93618084f58d0": 35, | ||||
|             "5d6e6a42a4b9364f07165f52": 35 | ||||
|         }, | ||||
|         "Caliber23x75": { | ||||
|             "5f647f31b6238e5dd066e196": 40, | ||||
|             "5e85a9a6eacf8c039e4e2ac1": 35, | ||||
|             "5e85aa1a988a8701445df1f5": 25 | ||||
|         }, | ||||
|         "Caliber366TKM": { | ||||
|             "59e655cb86f77411dc52a77b": 40, | ||||
|             "5f0596629e22f464da6bbdd9": 60 | ||||
|         }, | ||||
|         "Caliber40mmRU": { | ||||
|             "5656eb674bdc2d35148b457c": 1 | ||||
|         }, | ||||
|         "Caliber40x46": { | ||||
|             "5ede4739e0350d05467f73e8": 1, | ||||
|             "5ede47405b097655935d7d16": 1, | ||||
|             "5ede474b0c226a66f5402622": 1, | ||||
|             "5ede475339ee016e8c534742": 1, | ||||
|             "5ede475b549eed7c6d5c18fb": 1, | ||||
|             "5f0c892565703e5c461894e9": 1 | ||||
|         }, | ||||
|         "Caliber46x30": { | ||||
|             "5ba26844d4351e00334c9475": 40, | ||||
|             "64b6979341772715af0f9c39": 30, | ||||
|             "5ba2678ad4351e44f824b344": 20, | ||||
|             "5ba26835d4351e0035628ff5": 10 | ||||
|         }, | ||||
|         "Caliber545x39": { | ||||
|             "56dff2ced2720bb4668b4567": 30, | ||||
|             "56dff061d2720bb5668b4567": 50, | ||||
|             "61962b617c6c7b169525f168": 10, | ||||
|             "56dfef82d2720bbd668b4567": 10, | ||||
|             "56dff026d2720bb8668b4567": 5, | ||||
|             "5c0d5e4486f77478390952fe": 5 | ||||
|         }, | ||||
|         "Caliber556x45NATO": { | ||||
|             "5c0d5ae286f7741e46554302": 10, | ||||
|             "60194943740c5d77f6705eea": 25, | ||||
|             "59e6906286f7746c9f75e847": 25, | ||||
|             "54527ac44bdc2d36668b4567": 30, | ||||
|             "59e690b686f7746c9f75e848": 5, | ||||
|             "601949593ae8f707c4608daa": 5 | ||||
|         }, | ||||
|         "Caliber57x28": { | ||||
|             "5cc80f53e4a949000e1ea4f8": 20, | ||||
|             "5cc80f67e4a949035e43bbba": 40, | ||||
|             "5cc80f38e4a949001152b560": 30 | ||||
|         }, | ||||
|         "Caliber68x51": { | ||||
|             "6529302b8c26af6326029fb7": 80, | ||||
|             "6529243824cbe3c74a05e5c1": 20 | ||||
|         }, | ||||
|         "Caliber762x25TT": { | ||||
|             "573603c924597764442bd9cb": 10, | ||||
|             "573603562459776430731618": 10 | ||||
|         }, | ||||
|         "Caliber762x35": { | ||||
|             "6196365d58ef8c428c287da1": 5, | ||||
|             "5fbe3ffdf8b6a877a729ea82": 40, | ||||
|             "619636be6db0f2477964e710": 40, | ||||
|             "64b8725c4b75259c590fa899": 10, | ||||
|             "5fd20ff893a8961fc660a954": 5 | ||||
|         }, | ||||
|         "Caliber762x39": { | ||||
|             "5656d7c34bdc2d9d198b4587": 25, | ||||
|             "64b7af434b75259c590fa893": 50, | ||||
|             "59e0d99486f7744a32234762": 20, | ||||
|             "601aa3d2b2bcb34913271e6d": 5 | ||||
|         }, | ||||
|         "Caliber762x51": { | ||||
|             "5e023e53d4353e3302577c4c": 20, | ||||
|             "58dd3ad986f77403051cba8f": 45, | ||||
|             "5a608bf24f39f98ffc77720e": 20, | ||||
|             "5a6086ea4f39f99cd479502f": 10, | ||||
|             "5efb0c1bd79ff02a1f5e68d9": 5 | ||||
|         }, | ||||
|         "Caliber762x54R": { | ||||
|             "5887431f2459777e1612938f": 30, | ||||
|             "59e77a2386f7742ee578960a": 45, | ||||
|             "5e023d34e8a400319a28ed44": 20, | ||||
|             "560d61e84bdc2da74d8b4571": 5 | ||||
|         }, | ||||
|         "Caliber86x70": { | ||||
|             "5fc382b6d6fa9c00c571bbc3": 20, | ||||
|             "5fc382c1016cce60e8341b20": 40, | ||||
|             "5fc275cf85fd526b824a571a": 25, | ||||
|             "5fc382a9d724d907e2077dab": 5 | ||||
|         }, | ||||
|         "Caliber9x18PM": { | ||||
|             "5737201124597760fc4431f1": 15, | ||||
|             "573720e02459776143012541": 20, | ||||
|             "573718ba2459775a75491131": 30, | ||||
|             "57371aab2459775a77142f22": 20, | ||||
|             "573719df2459775a626ccbc2": 15 | ||||
|         }, | ||||
|         "Caliber9x19PARA": { | ||||
|             "5c0d56a986f774449d5de529": 10, | ||||
|             "5efb0e16aeb21837e749c7ff": 15, | ||||
|             "56d59d3ad2720bdb418b4577": 50, | ||||
|             "5c925fa22e221601da359b7b": 20, | ||||
|             "5efb0da7a29a85116f6ea05f": 5 | ||||
|         }, | ||||
|         "Caliber9x21": { | ||||
|             "5a269f97c4a282000b151807": 25, | ||||
|             "6576f93989f0062e741ba952": 25, | ||||
|             "5a26ac0ec4a28200741e1e18": 12, | ||||
|             "6576f4708ca9c4381d16cd9d": 8 | ||||
|         }, | ||||
|         "Caliber9x33R": { | ||||
|             "62330c18744e5e31df12f516": 9, | ||||
|             "62330b3ed4dc74626d570b95": 6 | ||||
|         }, | ||||
|         "Caliber9x39": { | ||||
|             "5c0d668f86f7747ccb7f13b2": 20, | ||||
|             "61962d879bb3d20b0946d385": 50, | ||||
|             "57a0e5022459774d1673f889": 25, | ||||
|             "5c0d688c86f77413ae3407b2": 5 | ||||
|         }, | ||||
|         "Caliber127x33": { | ||||
|             "66a0d1c87d0d369e270bb9de": 5, | ||||
|             "66a0d1f88486c69fce00fdf6": 60, | ||||
|             "66a0d1e0ed648d72fe064d06": 30, | ||||
|             "668fe62ac62660a5d8071446": 5 | ||||
|         } | ||||
|     }, | ||||
|     "bossAmmo": { | ||||
|         "Caliber1143x23ACP": { | ||||
|             "5ea2a8e200685063ec28c05a": 4, | ||||
|             "5efb0fc6aeb21837e749c801": 1, | ||||
|             "5efb0d4f4bc50b58e81710f3": 10, | ||||
|             "5e81f423763d9f754677bf2e": 18, | ||||
|             "5efb0cabfb3e451d70735af5": 10 | ||||
|         }, | ||||
|         "Caliber127x55": { | ||||
|             "5cadf6e5ae921500113bb973": 3, | ||||
|             "5cadf6ddae9215051e1c23b2": 12, | ||||
|             "5cadf6eeae921500134b2799": 8 | ||||
|         }, | ||||
|         "Caliber12g": { | ||||
|             "5d6e6806a4b936088465b17e": 7, | ||||
|             "64b8ee384b75259c590fa89b": 4, | ||||
|             "5d6e6911a4b9361bd5780d52": 3, | ||||
|             "5c0d591486f7744c505b416f": 5, | ||||
|             "5d6e6891a4b9361bd473feea": 2, | ||||
|             "5d6e68e6a4b9361c140bcfe0": 6, | ||||
|             "5d6e689ca4b9361bc8618956": 8, | ||||
|             "5d6e68c4a4b9361b93413f79": 8, | ||||
|             "5d6e68a8a4b9360b6c0d54e2": 3 | ||||
|         }, | ||||
|         "Caliber20g": { | ||||
|             "5d6e69c7a4b9360b6c0d54e4": 1, | ||||
|             "5d6e6a53a4b9361bd473feec": 4, | ||||
|             "5d6e6a05a4b93618084f58d0": 5, | ||||
|             "5d6e6a42a4b9364f07165f52": 5 | ||||
|         }, | ||||
|         "Caliber23x75": { | ||||
|             "5f647f31b6238e5dd066e196": 2, | ||||
|             "5e85a9a6eacf8c039e4e2ac1": 4, | ||||
|             "5e85aa1a988a8701445df1f5": 4 | ||||
|         }, | ||||
|         "Caliber366TKM": { | ||||
|             "59e6658b86f77411d949b250": 1, | ||||
|             "59e6542b86f77411dc52a77a": 2, | ||||
|             "59e655cb86f77411dc52a77b": 10, | ||||
|             "5f0596629e22f464da6bbdd9": 8 | ||||
|         }, | ||||
|         "Caliber40mmRU": { | ||||
|             "5656eb674bdc2d35148b457c": 1 | ||||
|         }, | ||||
|         "Caliber40x46": { | ||||
|             "5ede4739e0350d05467f73e8": 1, | ||||
|             "5ede47405b097655935d7d16": 1, | ||||
|             "5ede474b0c226a66f5402622": 1, | ||||
|             "5ede475339ee016e8c534742": 1, | ||||
|             "5ede475b549eed7c6d5c18fb": 1, | ||||
|             "5f0c892565703e5c461894e9": 1 | ||||
|         }, | ||||
|         "Caliber46x30": { | ||||
|             "5ba26812d4351e003201fef1": 2, | ||||
|             "5ba26844d4351e00334c9475": 4, | ||||
|             "5ba2678ad4351e44f824b344": 15, | ||||
|             "64b6979341772715af0f9c39": 15, | ||||
|             "5ba26835d4351e0035628ff5": 8 | ||||
|         }, | ||||
|         "Caliber545x39": { | ||||
|             "56dff3afd2720bba668b4567": 6, | ||||
|             "56dff2ced2720bb4668b4567": 12, | ||||
|             "56dff061d2720bb5668b4567": 20, | ||||
|             "61962b617c6c7b169525f168": 12, | ||||
|             "56dfef82d2720bbd668b4567": 9, | ||||
|             "56dff026d2720bb8668b4567": 8, | ||||
|             "5c0d5e4486f77478390952fe": 4 | ||||
|         }, | ||||
|         "Caliber556x45NATO": { | ||||
|             "5c0d5ae286f7741e46554302": 1, | ||||
|             "54527a984bdc2d4e668b4567": 7, | ||||
|             "60194943740c5d77f6705eea": 20, | ||||
|             "59e6906286f7746c9f75e847": 26, | ||||
|             "54527ac44bdc2d36668b4567": 30, | ||||
|             "59e690b686f7746c9f75e848": 7, | ||||
|             "601949593ae8f707c4608daa": 5 | ||||
|         }, | ||||
|         "Caliber57x28": { | ||||
|             "5cc80f8fe4a949033b0224a2": 5, | ||||
|             "5cc80f53e4a949000e1ea4f8": 21, | ||||
|             "5cc80f67e4a949035e43bbba": 15, | ||||
|             "5cc80f38e4a949001152b560": 12 | ||||
|         }, | ||||
|         "Caliber68x51": { | ||||
|             "6529302b8c26af6326029fb7": 10, | ||||
|             "6529243824cbe3c74a05e5c1": 5 | ||||
|         }, | ||||
|         "Caliber762x25TT": { | ||||
|             "5736026a245977644601dc61": 5, | ||||
|             "573603c924597764442bd9cb": 10, | ||||
|             "573603562459776430731618": 10 | ||||
|         }, | ||||
|         "Caliber762x35": { | ||||
|             "6196365d58ef8c428c287da1": 7, | ||||
|             "5fbe3ffdf8b6a877a729ea82": 6, | ||||
|             "619636be6db0f2477964e710": 23, | ||||
|             "64b8725c4b75259c590fa899": 20, | ||||
|             "5fd20ff893a8961fc660a954": 9 | ||||
|         }, | ||||
|         "Caliber762x39": { | ||||
|             "59e4cf5286f7741778269d8a": 4, | ||||
|             "5656d7c34bdc2d9d198b4587": 28, | ||||
|             "64b7af434b75259c590fa893": 33, | ||||
|             "59e0d99486f7744a32234762": 20, | ||||
|             "601aa3d2b2bcb34913271e6d": 12 | ||||
|         }, | ||||
|         "Caliber762x51": { | ||||
|             "5e023e53d4353e3302577c4c": 6, | ||||
|             "58dd3ad986f77403051cba8f": 27, | ||||
|             "5a608bf24f39f98ffc77720e": 19, | ||||
|             "5a6086ea4f39f99cd479502f": 9, | ||||
|             "5efb0c1bd79ff02a1f5e68d9": 2 | ||||
|         }, | ||||
|         "Caliber762x54R": { | ||||
|             "5e023cf8186a883be655e54f": 3, | ||||
|             "5887431f2459777e1612938f": 20, | ||||
|             "59e77a2386f7742ee578960a": 25, | ||||
|             "5e023d34e8a400319a28ed44": 22, | ||||
|             "560d61e84bdc2da74d8b4571": 15, | ||||
|             "5e023d48186a883be655e551": 10 | ||||
|         }, | ||||
|         "Caliber86x70": { | ||||
|             "5fc382b6d6fa9c00c571bbc3": 5, | ||||
|             "5fc382c1016cce60e8341b20": 8, | ||||
|             "5fc275cf85fd526b824a571a": 8, | ||||
|             "5fc382a9d724d907e2077dab": 5 | ||||
|         }, | ||||
|         "Caliber9x18PM": { | ||||
|             "57371e4124597760ff7b25f1": 3, | ||||
|             "5737201124597760fc4431f1": 5, | ||||
|             "573720e02459776143012541": 12, | ||||
|             "573718ba2459775a75491131": 18, | ||||
|             "57371aab2459775a77142f22": 12, | ||||
|             "573719df2459775a626ccbc2": 10 | ||||
|         }, | ||||
|         "Caliber9x19PARA": { | ||||
|             "5c0d56a986f774449d5de529": 9, | ||||
|             "5efb0e16aeb21837e749c7ff": 5, | ||||
|             "5a3c16fe86f77452b62de32a": 4, | ||||
|             "56d59d3ad2720bdb418b4577": 18, | ||||
|             "5c925fa22e221601da359b7b": 22, | ||||
|             "5efb0da7a29a85116f6ea05f": 9 | ||||
|         }, | ||||
|         "Caliber9x21": { | ||||
|             "5a269f97c4a282000b151807": 8, | ||||
|             "6576f93989f0062e741ba952": 18, | ||||
|             "5a26ac0ec4a28200741e1e18": 18, | ||||
|             "6576f4708ca9c4381d16cd9d": 8 | ||||
|         }, | ||||
|         "Caliber9x33R": { | ||||
|             "62330c18744e5e31df12f516": 9, | ||||
|             "62330b3ed4dc74626d570b95": 6 | ||||
|         }, | ||||
|         "Caliber9x39": { | ||||
|             "5c0d668f86f7747ccb7f13b2": 9, | ||||
|             "61962d879bb3d20b0946d385": 25, | ||||
|             "57a0e5022459774d1673f889": 25, | ||||
|             "5c0d688c86f77413ae3407b2": 12 | ||||
|         }, | ||||
|         "Caliber127x33": { | ||||
|             "66a0d1c87d0d369e270bb9de": 3, | ||||
|             "66a0d1f88486c69fce00fdf6": 30, | ||||
|             "66a0d1e0ed648d72fe064d06": 25,  | ||||
|             "668fe62ac62660a5d8071446": 12 | ||||
|         } | ||||
|     } | ||||
| } | ||||
Some files were not shown because too many files have changed in this diff Show More
		Loading…
	
		Reference in New Issue