Updated Progressive Bot System
This commit is contained in:
		
							parent
							
								
									b7a439a282
								
							
						
					
					
						commit
						7fee303436
					
				|  | @ -1,7 +1,7 @@ | |||
| [General] | ||||
| gameName=spt | ||||
| modid=0 | ||||
| version=d2025.1.8.0 | ||||
| version=d2025.1.14.0 | ||||
| newestVersion= | ||||
| category="1," | ||||
| nexusFileStatus=1 | ||||
|  |  | |||
|  | @ -1,6 +1,6 @@ | |||
| { | ||||
|     "name": "Acids Progressive Bot System", | ||||
|     "version": "1.4.0", | ||||
|     "version": "1.4.1", | ||||
|     "sptVersion": "~3.10", | ||||
|     "loadBefore": [], | ||||
|     "loadAfter": [ | ||||
|  |  | |||
|  | @ -11980,7 +11980,7 @@ | |||
|                 "mod_pistol_grip": 100, | ||||
|                 "mod_pistol_grip_akms": 0, | ||||
|                 "mod_pistolgrip": 0, | ||||
|                 "mod_pistolgrip_000": 0, | ||||
|                 "mod_pistolgrip_000": 100, | ||||
|                 "mod_reciever": 100, | ||||
|                 "mod_scope": 13, | ||||
|                 "mod_scope_000": 0, | ||||
|  |  | |||
|  | @ -3,8 +3,10 @@ | |||
|         "equipment": { | ||||
|             "FirstPrimaryWeapon": { | ||||
|                 "LongRange": { | ||||
|                     "5c07c60e0db834002330051f": 30, | ||||
|                     "5bfea6e90db834001b7347f3": 20 | ||||
|                     "5c07c60e0db834002330051f": 25, | ||||
|                     "5bfea6e90db834001b7347f3": 15, | ||||
|                     "623063e994fc3f7b302a9696": 8, | ||||
|                     "5447a9cd4bdc2dbd208b4567": 8 | ||||
|                 }, | ||||
|                 "ShortRange": { | ||||
|                     "5a7828548dc32e5a9c28b516": 20, | ||||
|  | @ -50,8 +52,10 @@ | |||
|             }, | ||||
|             "SecondPrimaryWeapon": { | ||||
|                 "LongRange": { | ||||
|                     "5c07c60e0db834002330051f": 30, | ||||
|                     "5bfea6e90db834001b7347f3": 20 | ||||
|                     "5c07c60e0db834002330051f": 25, | ||||
|                     "5bfea6e90db834001b7347f3": 15, | ||||
|                     "623063e994fc3f7b302a9696": 8, | ||||
|                     "5447a9cd4bdc2dbd208b4567": 8 | ||||
|                 }, | ||||
|                 "ShortRange": { | ||||
|                     "5a7828548dc32e5a9c28b516": 20, | ||||
|  |  | |||
|  | @ -6378,11 +6378,7 @@ | |||
|       "5a789261c5856700186c65d3" | ||||
|     ] | ||||
|   }, | ||||
|   "5a787fdfc5856700142fdd9a": { | ||||
|     "mod_scope": [ | ||||
|       "609b9e31506cf869cf3eaf41" | ||||
|     ] | ||||
|   }, | ||||
|   "5a787fdfc5856700142fdd9a": {}, | ||||
|   "5a788031c585673f2b5c1c79": { | ||||
|     "mod_foregrip": [ | ||||
|       "5c7fc87d2e221644f31c0298", | ||||
|  |  | |||
|  | @ -11990,7 +11990,7 @@ | |||
|                 "mod_pistol_grip": 100, | ||||
|                 "mod_pistol_grip_akms": 0, | ||||
|                 "mod_pistolgrip": 0, | ||||
|                 "mod_pistolgrip_000": 0, | ||||
|                 "mod_pistolgrip_000": 100, | ||||
|                 "mod_reciever": 100, | ||||
|                 "mod_scope": 13, | ||||
|                 "mod_scope_000": 0, | ||||
|  |  | |||
|  | @ -6,7 +6,9 @@ | |||
|                     "5c07c60e0db834002330051f": 25, | ||||
|                     "5d43021ca4b9362eab4b5e25": 3, | ||||
|                     "5b0bbe4e5acfc40dc528a72d": 1, | ||||
|                     "5bfea6e90db834001b7347f3": 20 | ||||
|                     "5bfea6e90db834001b7347f3": 15, | ||||
|                     "623063e994fc3f7b302a9696": 8, | ||||
|                     "5447a9cd4bdc2dbd208b4567": 8 | ||||
|                 }, | ||||
|                 "ShortRange": { | ||||
|                     "5a7828548dc32e5a9c28b516": 15, | ||||
|  | @ -59,7 +61,9 @@ | |||
|                     "5c07c60e0db834002330051f": 25, | ||||
|                     "5d43021ca4b9362eab4b5e25": 3, | ||||
|                     "5b0bbe4e5acfc40dc528a72d": 1, | ||||
|                     "5bfea6e90db834001b7347f3": 20 | ||||
|                     "5bfea6e90db834001b7347f3": 15, | ||||
|                     "623063e994fc3f7b302a9696": 8, | ||||
|                     "5447a9cd4bdc2dbd208b4567": 8 | ||||
|                 }, | ||||
|                 "ShortRange": { | ||||
|                     "5a7828548dc32e5a9c28b516": 15, | ||||
|  |  | |||
|  | @ -6607,11 +6607,7 @@ | |||
|       "5a789261c5856700186c65d3" | ||||
|     ] | ||||
|   }, | ||||
|   "5a787fdfc5856700142fdd9a": { | ||||
|     "mod_scope": [ | ||||
|       "609b9e31506cf869cf3eaf41" | ||||
|     ] | ||||
|   }, | ||||
|   "5a787fdfc5856700142fdd9a": {}, | ||||
|   "5a788031c585673f2b5c1c79": { | ||||
|     "mod_foregrip": [ | ||||
|       "5c7fc87d2e221644f31c0298", | ||||
|  |  | |||
|  | @ -12002,7 +12002,7 @@ | |||
|                 "mod_pistol_grip": 100, | ||||
|                 "mod_pistol_grip_akms": 0, | ||||
|                 "mod_pistolgrip": 0, | ||||
|                 "mod_pistolgrip_000": 0, | ||||
|                 "mod_pistolgrip_000": 100, | ||||
|                 "mod_reciever": 100, | ||||
|                 "mod_scope": 13, | ||||
|                 "mod_scope_000": 0, | ||||
|  |  | |||
|  | @ -4,10 +4,12 @@ | |||
|             "FirstPrimaryWeapon": { | ||||
|                 "LongRange": { | ||||
|                     "5c07c60e0db834002330051f": 25, | ||||
|                     "5d43021ca4b9362eab4b5e25": 25, | ||||
|                     "5d43021ca4b9362eab4b5e25": 20, | ||||
|                     "5b0bbe4e5acfc40dc528a72d": 15, | ||||
|                     "5bfea6e90db834001b7347f3": 25, | ||||
|                     "5df8ce05b11454561e39243b": 10 | ||||
|                     "5bfea6e90db834001b7347f3": 20, | ||||
|                     "5df8ce05b11454561e39243b": 15, | ||||
|                     "623063e994fc3f7b302a9696": 8, | ||||
|                     "5447a9cd4bdc2dbd208b4567": 8 | ||||
|                 }, | ||||
|                 "ShortRange": { | ||||
|                     "5a7828548dc32e5a9c28b516": 5, | ||||
|  | @ -75,10 +77,12 @@ | |||
|             "SecondPrimaryWeapon": { | ||||
|                 "LongRange": { | ||||
|                     "5c07c60e0db834002330051f": 25, | ||||
|                     "5d43021ca4b9362eab4b5e25": 25, | ||||
|                     "5d43021ca4b9362eab4b5e25": 20, | ||||
|                     "5b0bbe4e5acfc40dc528a72d": 15, | ||||
|                     "5bfea6e90db834001b7347f3": 25, | ||||
|                     "5df8ce05b11454561e39243b": 10 | ||||
|                     "5bfea6e90db834001b7347f3": 20, | ||||
|                     "5df8ce05b11454561e39243b": 15, | ||||
|                     "623063e994fc3f7b302a9696": 8, | ||||
|                     "5447a9cd4bdc2dbd208b4567": 8 | ||||
|                 }, | ||||
|                 "ShortRange": { | ||||
|                     "5a7828548dc32e5a9c28b516": 5, | ||||
|  | @ -753,6 +757,7 @@ | |||
|                 "56e335e4d2720b6c058b456d": 20, | ||||
|                 "5ca20d5986f774331e7c9602": 10, | ||||
|                 "5e9dcf5986f7746c417435b3": 10, | ||||
|                 "59e763f286f7742ee57895da": 15, | ||||
|                 "6038d614d10cbf667352dd44": 1, | ||||
|                 "6034d103ca006d2dca39b3f0": 1, | ||||
|                 "656ddcf0f02d7bcea90bf395": 1, | ||||
|  |  | |||
|  | @ -6708,11 +6708,7 @@ | |||
|       "5a789261c5856700186c65d3" | ||||
|     ] | ||||
|   }, | ||||
|   "5a787fdfc5856700142fdd9a": { | ||||
|     "mod_scope": [ | ||||
|       "609b9e31506cf869cf3eaf41" | ||||
|     ] | ||||
|   }, | ||||
|   "5a787fdfc5856700142fdd9a": {}, | ||||
|   "5a788031c585673f2b5c1c79": { | ||||
|     "mod_foregrip": [ | ||||
|       "5c7fc87d2e221644f31c0298", | ||||
|  |  | |||
|  | @ -11994,7 +11994,7 @@ | |||
|                 "mod_pistol_grip": 100, | ||||
|                 "mod_pistol_grip_akms": 0, | ||||
|                 "mod_pistolgrip": 0, | ||||
|                 "mod_pistolgrip_000": 0, | ||||
|                 "mod_pistolgrip_000": 100, | ||||
|                 "mod_reciever": 100, | ||||
|                 "mod_scope": 13, | ||||
|                 "mod_scope_000": 0, | ||||
|  |  | |||
|  | @ -7529,11 +7529,7 @@ | |||
|       "5a789261c5856700186c65d3" | ||||
|     ] | ||||
|   }, | ||||
|   "5a787fdfc5856700142fdd9a": { | ||||
|     "mod_scope": [ | ||||
|       "609b9e31506cf869cf3eaf41" | ||||
|     ] | ||||
|   }, | ||||
|   "5a787fdfc5856700142fdd9a": {}, | ||||
|   "5a788031c585673f2b5c1c79": { | ||||
|     "mod_foregrip": [ | ||||
|       "5cda9bcfd7f00c0c0b53e900", | ||||
|  |  | |||
|  | @ -11982,7 +11982,7 @@ | |||
|                 "mod_pistol_grip": 100, | ||||
|                 "mod_pistol_grip_akms": 0, | ||||
|                 "mod_pistolgrip": 0, | ||||
|                 "mod_pistolgrip_000": 0, | ||||
|                 "mod_pistolgrip_000": 100, | ||||
|                 "mod_reciever": 100, | ||||
|                 "mod_scope": 13, | ||||
|                 "mod_scope_000": 0, | ||||
|  |  | |||
|  | @ -7319,11 +7319,7 @@ | |||
|       "5a789261c5856700186c65d3" | ||||
|     ] | ||||
|   }, | ||||
|   "5a787fdfc5856700142fdd9a": { | ||||
|     "mod_scope": [ | ||||
|       "609b9e31506cf869cf3eaf41" | ||||
|     ] | ||||
|   }, | ||||
|   "5a787fdfc5856700142fdd9a": {}, | ||||
|   "5a788031c585673f2b5c1c79": { | ||||
|     "mod_foregrip": [ | ||||
|       "5cda9bcfd7f00c0c0b53e900", | ||||
|  |  | |||
|  | @ -11982,7 +11982,7 @@ | |||
|                 "mod_pistol_grip": 100, | ||||
|                 "mod_pistol_grip_akms": 0, | ||||
|                 "mod_pistolgrip": 0, | ||||
|                 "mod_pistolgrip_000": 0, | ||||
|                 "mod_pistolgrip_000": 100, | ||||
|                 "mod_reciever": 100, | ||||
|                 "mod_scope": 13, | ||||
|                 "mod_scope_000": 0, | ||||
|  |  | |||
|  | @ -7023,11 +7023,7 @@ | |||
|       "5a789261c5856700186c65d3" | ||||
|     ] | ||||
|   }, | ||||
|   "5a787fdfc5856700142fdd9a": { | ||||
|     "mod_scope": [ | ||||
|       "609b9e31506cf869cf3eaf41" | ||||
|     ] | ||||
|   }, | ||||
|   "5a787fdfc5856700142fdd9a": {}, | ||||
|   "5a788031c585673f2b5c1c79": { | ||||
|     "mod_foregrip": [ | ||||
|       "5cda9bcfd7f00c0c0b53e900", | ||||
|  |  | |||
|  | @ -12038,7 +12038,7 @@ | |||
|                 "mod_pistol_grip": 100, | ||||
|                 "mod_pistol_grip_akms": 0, | ||||
|                 "mod_pistolgrip": 0, | ||||
|                 "mod_pistolgrip_000": 0, | ||||
|                 "mod_pistolgrip_000": 100, | ||||
|                 "mod_reciever": 100, | ||||
|                 "mod_scope": 13, | ||||
|                 "mod_scope_000": 0, | ||||
|  |  | |||
|  | @ -7006,11 +7006,7 @@ | |||
|       "5a789261c5856700186c65d3" | ||||
|     ] | ||||
|   }, | ||||
|   "5a787fdfc5856700142fdd9a": { | ||||
|     "mod_scope": [ | ||||
|       "609b9e31506cf869cf3eaf41" | ||||
|     ] | ||||
|   }, | ||||
|   "5a787fdfc5856700142fdd9a": {}, | ||||
|   "5a788031c585673f2b5c1c79": { | ||||
|     "mod_foregrip": [ | ||||
|       "5cda9bcfd7f00c0c0b53e900", | ||||
|  |  | |||
|  | @ -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; | ||||
|     } | ||||
| } | ||||
|  | @ -75,24 +75,6 @@ export class APBSBotLevelGenerator | |||
|                     return result;                     | ||||
|                 } | ||||
| 
 | ||||
|                 if (!botGenerationDetails.isPmc && !botGenerationDetails.isPlayerScav && ModConfig.config.enableScavCustomLevelDeltas) | ||||
|                 { | ||||
|                     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; | ||||
|                 } | ||||
| 
 | ||||
|                 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; | ||||
|  |  | |||
|  | @ -33,18 +33,18 @@ export class RaidInformation | |||
|         }, | ||||
|         "laboratory": | ||||
|         { | ||||
|             "LongRange": 5, | ||||
|             "ShortRange": 95 | ||||
|             "LongRange": 10, | ||||
|             "ShortRange": 90 | ||||
|         }, | ||||
|         "factory4_night": | ||||
|         { | ||||
|             "LongRange": 1, | ||||
|             "ShortRange": 99 | ||||
|             "LongRange": 5, | ||||
|             "ShortRange": 95 | ||||
|         }, | ||||
|         "factory4_day": | ||||
|         { | ||||
|             "LongRange": 1, | ||||
|             "ShortRange": 99 | ||||
|             "LongRange": 5, | ||||
|             "ShortRange": 95 | ||||
|         }, | ||||
|         "Interchange": | ||||
|         { | ||||
|  |  | |||
|  | @ -16,6 +16,11 @@ export class BlacklistHelper | |||
|     ) | ||||
|     {} | ||||
| 
 | ||||
|     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); | ||||
|  | @ -46,6 +51,8 @@ export class BlacklistHelper | |||
|         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 | ||||
|  | @ -76,7 +83,7 @@ export class BlacklistHelper | |||
|             } | ||||
|             if (itemDetails == undefined || itemDetails._parent != "5485a8684bdc2da71d8b4567") | ||||
|             { | ||||
|                 this.apbsLogger.log(Logging.WARN, `"${ammoBlacklist[item]}" in Ammo Blacklist is either an invalid ammunition or item ID.`) | ||||
|                 if (!this.invalidAmmoIDs.includes(ammoBlacklist[item])) this.invalidAmmoIDs.push(ammoBlacklist[item]) | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | @ -109,7 +116,7 @@ export class BlacklistHelper | |||
|             } | ||||
|             if (itemDetails == undefined) | ||||
|             { | ||||
|                 this.apbsLogger.log(Logging.WARN, `"${equipmentBlacklist[item]}" in Equipment Blacklist is an invalid item ID.`) | ||||
|                 if (!this.invalidEquipmentIDs.includes(equipmentBlacklist[item])) this.invalidEquipmentIDs.push(equipmentBlacklist[item]) | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | @ -178,7 +185,7 @@ export class BlacklistHelper | |||
|             } | ||||
|             if (itemDetails == undefined) | ||||
|             { | ||||
|                 this.apbsLogger.log(Logging.WARN, `"${weaponBlacklist[item]}" in Weapon Blacklist is an invalid item ID.`) | ||||
|                 if (!this.invalidWeaponIDs.includes(weaponBlacklist[item])) this.invalidWeaponIDs.push(weaponBlacklist[item]) | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | @ -219,7 +226,7 @@ export class BlacklistHelper | |||
|             } | ||||
|             if (itemDetails == undefined) | ||||
|             { | ||||
|                 this.apbsLogger.log(Logging.WARN, `"${attachmentBlacklist[item]}" in Attachment Blacklist is either an invalid attachment or item ID.`) | ||||
|                 if (!this.invalidAttachmentIDs.includes(attachmentBlacklist[item])) this.invalidAttachmentIDs.push(attachmentBlacklist[item]) | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | @ -233,4 +240,36 @@ export class BlacklistHelper | |||
| 
 | ||||
|         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.`) | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | @ -100,27 +100,8 @@ export class ModdedImportHelper | |||
|             "671d8b8c0959c721a50ca838" | ||||
|         ] | ||||
| 
 | ||||
|         this.clothingBlacklist = [ | ||||
|             "668bc5cd834c88e06b08b645", // All of this is Artem hands, because they are being configured as Body instead...Crackboooonnneee!!
 | ||||
|             "668bc5cd834c88e06b08b64a", | ||||
|             "668bc5cd834c88e06b08b64d", | ||||
|             "668bc5cd834c88e06b08b650", | ||||
|             "668bc5cd834c88e06b08b652", | ||||
|             "668bc5cd834c88e06b08b655", | ||||
|             "668bc5cd834c88e06b08b658", | ||||
|             "668bc5cd834c88e06b08b65b", | ||||
|             "668bc5cd834c88e06b08b65e", | ||||
|             "668bc5cd834c88e06b08b662", | ||||
|             "668bc5cd834c88e06b08b665", | ||||
|             "668bc5cd834c88e06b08b668", | ||||
|             "668bc5cd834c88e06b08b66b", | ||||
|             "668bc5cd834c88e06b08b66e", | ||||
|             "668bc5cd834c88e06b08b671", | ||||
|             "668bc5cd834c88e06b08b674", | ||||
|             "668bc5cd834c88e06b08b677", | ||||
|             "668bc5cd834c88e06b08b67a", | ||||
|             "668bc5cd834c88e06b08b67d" | ||||
|         ] | ||||
|         // This is empty now because Crackbone fixed Artem - but I'm leaving this here for future use
 | ||||
|         this.clothingBlacklist = [] | ||||
|     } | ||||
| 
 | ||||
|     public tiersTable = []; | ||||
|  | @ -142,14 +123,14 @@ export class ModdedImportHelper | |||
|         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: ITemplateItem = {}; | ||||
|         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, BaseClasses.WEAPON, "Weapons"); | ||||
|         this.getModdedItems(weapons as ITemplateItem, BaseClasses.WEAPON, "Weapons"); | ||||
|     } | ||||
| 
 | ||||
|     private buildVanillaEquipmentList(): void | ||||
|  | @ -157,19 +138,19 @@ export class ModdedImportHelper | |||
|         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: ITemplateItem = {}; | ||||
|         const armours = {}; | ||||
|         vanillaItemList.equipment.ArmorVest.forEach(element => armours[element] = this.getItem(element)) | ||||
| 
 | ||||
|         const headwear: ITemplateItem = {}; | ||||
|         const headwear = {}; | ||||
|         vanillaItemList.equipment.Headwear.forEach(element => headwear[element] = this.getItem(element)) | ||||
| 
 | ||||
|         const tacticalVests: ITemplateItem = {};         | ||||
|         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, BaseClasses.ARMOR, "Armours"); | ||||
|         this.getModdedItems(headwear, BaseClasses.HEADWEAR, "Helmets"); | ||||
|         this.getModdedItems(tacticalVests, BaseClasses.VEST, "Vests"); | ||||
|         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 | ||||
|  | @ -177,15 +158,15 @@ export class ModdedImportHelper | |||
|         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: ICustomizationItem = {}; | ||||
|         const body = {}; | ||||
|         vanillaClothingList.appearance.body.forEach(element => body[element] = this.getCustomization(element)) | ||||
| 
 | ||||
|         const feet: ICustomizationItem = {}; | ||||
|         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, "Body"); | ||||
|         this.getModdedClothing(feet, "Feet"); | ||||
|         this.getModdedClothing(body as ICustomizationItem, "Body"); | ||||
|         this.getModdedClothing(feet as ICustomizationItem, "Feet"); | ||||
|     } | ||||
| 
 | ||||
|     private getModdedClothing(clothingList: ICustomizationItem, className: string): void | ||||
|  |  | |||
|  | @ -60,6 +60,7 @@ 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  | ||||
| { | ||||
|  | @ -213,6 +214,8 @@ export class InstanceManager | |||
|         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" }); | ||||
| 
 | ||||
|  |  | |||
|  | @ -11980,7 +11980,7 @@ | |||
|                 "mod_pistol_grip": 100, | ||||
|                 "mod_pistol_grip_akms": 0, | ||||
|                 "mod_pistolgrip": 0, | ||||
|                 "mod_pistolgrip_000": 0, | ||||
|                 "mod_pistolgrip_000": 100, | ||||
|                 "mod_reciever": 100, | ||||
|                 "mod_scope": 13, | ||||
|                 "mod_scope_000": 0, | ||||
|  |  | |||
|  | @ -3,8 +3,10 @@ | |||
|         "equipment": { | ||||
|             "FirstPrimaryWeapon": { | ||||
|                 "LongRange": { | ||||
|                     "5c07c60e0db834002330051f": 30, | ||||
|                     "5bfea6e90db834001b7347f3": 20 | ||||
|                     "5c07c60e0db834002330051f": 25, | ||||
|                     "5bfea6e90db834001b7347f3": 15, | ||||
|                     "623063e994fc3f7b302a9696": 8, | ||||
|                     "5447a9cd4bdc2dbd208b4567": 8 | ||||
|                 }, | ||||
|                 "ShortRange": { | ||||
|                     "5a7828548dc32e5a9c28b516": 20, | ||||
|  | @ -50,8 +52,10 @@ | |||
|             }, | ||||
|             "SecondPrimaryWeapon": { | ||||
|                 "LongRange": { | ||||
|                     "5c07c60e0db834002330051f": 30, | ||||
|                     "5bfea6e90db834001b7347f3": 20 | ||||
|                     "5c07c60e0db834002330051f": 25, | ||||
|                     "5bfea6e90db834001b7347f3": 15, | ||||
|                     "623063e994fc3f7b302a9696": 8, | ||||
|                     "5447a9cd4bdc2dbd208b4567": 8 | ||||
|                 }, | ||||
|                 "ShortRange": { | ||||
|                     "5a7828548dc32e5a9c28b516": 20, | ||||
|  |  | |||
|  | @ -6378,11 +6378,7 @@ | |||
|       "5a789261c5856700186c65d3" | ||||
|     ] | ||||
|   }, | ||||
|   "5a787fdfc5856700142fdd9a": { | ||||
|     "mod_scope": [ | ||||
|       "609b9e31506cf869cf3eaf41" | ||||
|     ] | ||||
|   }, | ||||
|   "5a787fdfc5856700142fdd9a": {}, | ||||
|   "5a788031c585673f2b5c1c79": { | ||||
|     "mod_foregrip": [ | ||||
|       "5c7fc87d2e221644f31c0298", | ||||
|  |  | |||
|  | @ -11990,7 +11990,7 @@ | |||
|                 "mod_pistol_grip": 100, | ||||
|                 "mod_pistol_grip_akms": 0, | ||||
|                 "mod_pistolgrip": 0, | ||||
|                 "mod_pistolgrip_000": 0, | ||||
|                 "mod_pistolgrip_000": 100, | ||||
|                 "mod_reciever": 100, | ||||
|                 "mod_scope": 13, | ||||
|                 "mod_scope_000": 0, | ||||
|  |  | |||
|  | @ -6,7 +6,9 @@ | |||
|                     "5c07c60e0db834002330051f": 25, | ||||
|                     "5d43021ca4b9362eab4b5e25": 3, | ||||
|                     "5b0bbe4e5acfc40dc528a72d": 1, | ||||
|                     "5bfea6e90db834001b7347f3": 20 | ||||
|                     "5bfea6e90db834001b7347f3": 15, | ||||
|                     "623063e994fc3f7b302a9696": 8, | ||||
|                     "5447a9cd4bdc2dbd208b4567": 8 | ||||
|                 }, | ||||
|                 "ShortRange": { | ||||
|                     "5a7828548dc32e5a9c28b516": 15, | ||||
|  | @ -59,7 +61,9 @@ | |||
|                     "5c07c60e0db834002330051f": 25, | ||||
|                     "5d43021ca4b9362eab4b5e25": 3, | ||||
|                     "5b0bbe4e5acfc40dc528a72d": 1, | ||||
|                     "5bfea6e90db834001b7347f3": 20 | ||||
|                     "5bfea6e90db834001b7347f3": 15, | ||||
|                     "623063e994fc3f7b302a9696": 8, | ||||
|                     "5447a9cd4bdc2dbd208b4567": 8 | ||||
|                 }, | ||||
|                 "ShortRange": { | ||||
|                     "5a7828548dc32e5a9c28b516": 15, | ||||
|  |  | |||
|  | @ -6607,11 +6607,7 @@ | |||
|       "5a789261c5856700186c65d3" | ||||
|     ] | ||||
|   }, | ||||
|   "5a787fdfc5856700142fdd9a": { | ||||
|     "mod_scope": [ | ||||
|       "609b9e31506cf869cf3eaf41" | ||||
|     ] | ||||
|   }, | ||||
|   "5a787fdfc5856700142fdd9a": {}, | ||||
|   "5a788031c585673f2b5c1c79": { | ||||
|     "mod_foregrip": [ | ||||
|       "5c7fc87d2e221644f31c0298", | ||||
|  |  | |||
|  | @ -12002,7 +12002,7 @@ | |||
|                 "mod_pistol_grip": 100, | ||||
|                 "mod_pistol_grip_akms": 0, | ||||
|                 "mod_pistolgrip": 0, | ||||
|                 "mod_pistolgrip_000": 0, | ||||
|                 "mod_pistolgrip_000": 100, | ||||
|                 "mod_reciever": 100, | ||||
|                 "mod_scope": 13, | ||||
|                 "mod_scope_000": 0, | ||||
|  |  | |||
|  | @ -4,10 +4,12 @@ | |||
|             "FirstPrimaryWeapon": { | ||||
|                 "LongRange": { | ||||
|                     "5c07c60e0db834002330051f": 25, | ||||
|                     "5d43021ca4b9362eab4b5e25": 25, | ||||
|                     "5d43021ca4b9362eab4b5e25": 20, | ||||
|                     "5b0bbe4e5acfc40dc528a72d": 15, | ||||
|                     "5bfea6e90db834001b7347f3": 25, | ||||
|                     "5df8ce05b11454561e39243b": 10 | ||||
|                     "5bfea6e90db834001b7347f3": 20, | ||||
|                     "5df8ce05b11454561e39243b": 15, | ||||
|                     "623063e994fc3f7b302a9696": 8, | ||||
|                     "5447a9cd4bdc2dbd208b4567": 8 | ||||
|                 }, | ||||
|                 "ShortRange": { | ||||
|                     "5a7828548dc32e5a9c28b516": 5, | ||||
|  | @ -75,10 +77,12 @@ | |||
|             "SecondPrimaryWeapon": { | ||||
|                 "LongRange": { | ||||
|                     "5c07c60e0db834002330051f": 25, | ||||
|                     "5d43021ca4b9362eab4b5e25": 25, | ||||
|                     "5d43021ca4b9362eab4b5e25": 20, | ||||
|                     "5b0bbe4e5acfc40dc528a72d": 15, | ||||
|                     "5bfea6e90db834001b7347f3": 25, | ||||
|                     "5df8ce05b11454561e39243b": 10 | ||||
|                     "5bfea6e90db834001b7347f3": 20, | ||||
|                     "5df8ce05b11454561e39243b": 15, | ||||
|                     "623063e994fc3f7b302a9696": 8, | ||||
|                     "5447a9cd4bdc2dbd208b4567": 8 | ||||
|                 }, | ||||
|                 "ShortRange": { | ||||
|                     "5a7828548dc32e5a9c28b516": 5, | ||||
|  | @ -753,6 +757,7 @@ | |||
|                 "56e335e4d2720b6c058b456d": 20, | ||||
|                 "5ca20d5986f774331e7c9602": 10, | ||||
|                 "5e9dcf5986f7746c417435b3": 10, | ||||
|                 "59e763f286f7742ee57895da": 15, | ||||
|                 "6038d614d10cbf667352dd44": 1, | ||||
|                 "6034d103ca006d2dca39b3f0": 1, | ||||
|                 "656ddcf0f02d7bcea90bf395": 1, | ||||
|  |  | |||
|  | @ -6708,11 +6708,7 @@ | |||
|       "5a789261c5856700186c65d3" | ||||
|     ] | ||||
|   }, | ||||
|   "5a787fdfc5856700142fdd9a": { | ||||
|     "mod_scope": [ | ||||
|       "609b9e31506cf869cf3eaf41" | ||||
|     ] | ||||
|   }, | ||||
|   "5a787fdfc5856700142fdd9a": {}, | ||||
|   "5a788031c585673f2b5c1c79": { | ||||
|     "mod_foregrip": [ | ||||
|       "5c7fc87d2e221644f31c0298", | ||||
|  |  | |||
|  | @ -11994,7 +11994,7 @@ | |||
|                 "mod_pistol_grip": 100, | ||||
|                 "mod_pistol_grip_akms": 0, | ||||
|                 "mod_pistolgrip": 0, | ||||
|                 "mod_pistolgrip_000": 0, | ||||
|                 "mod_pistolgrip_000": 100, | ||||
|                 "mod_reciever": 100, | ||||
|                 "mod_scope": 13, | ||||
|                 "mod_scope_000": 0, | ||||
|  |  | |||
|  | @ -7529,11 +7529,7 @@ | |||
|       "5a789261c5856700186c65d3" | ||||
|     ] | ||||
|   }, | ||||
|   "5a787fdfc5856700142fdd9a": { | ||||
|     "mod_scope": [ | ||||
|       "609b9e31506cf869cf3eaf41" | ||||
|     ] | ||||
|   }, | ||||
|   "5a787fdfc5856700142fdd9a": {}, | ||||
|   "5a788031c585673f2b5c1c79": { | ||||
|     "mod_foregrip": [ | ||||
|       "5cda9bcfd7f00c0c0b53e900", | ||||
|  |  | |||
|  | @ -11982,7 +11982,7 @@ | |||
|                 "mod_pistol_grip": 100, | ||||
|                 "mod_pistol_grip_akms": 0, | ||||
|                 "mod_pistolgrip": 0, | ||||
|                 "mod_pistolgrip_000": 0, | ||||
|                 "mod_pistolgrip_000": 100, | ||||
|                 "mod_reciever": 100, | ||||
|                 "mod_scope": 13, | ||||
|                 "mod_scope_000": 0, | ||||
|  |  | |||
|  | @ -7319,11 +7319,7 @@ | |||
|       "5a789261c5856700186c65d3" | ||||
|     ] | ||||
|   }, | ||||
|   "5a787fdfc5856700142fdd9a": { | ||||
|     "mod_scope": [ | ||||
|       "609b9e31506cf869cf3eaf41" | ||||
|     ] | ||||
|   }, | ||||
|   "5a787fdfc5856700142fdd9a": {}, | ||||
|   "5a788031c585673f2b5c1c79": { | ||||
|     "mod_foregrip": [ | ||||
|       "5cda9bcfd7f00c0c0b53e900", | ||||
|  |  | |||
|  | @ -11982,7 +11982,7 @@ | |||
|                 "mod_pistol_grip": 100, | ||||
|                 "mod_pistol_grip_akms": 0, | ||||
|                 "mod_pistolgrip": 0, | ||||
|                 "mod_pistolgrip_000": 0, | ||||
|                 "mod_pistolgrip_000": 100, | ||||
|                 "mod_reciever": 100, | ||||
|                 "mod_scope": 13, | ||||
|                 "mod_scope_000": 0, | ||||
|  |  | |||
|  | @ -7023,11 +7023,7 @@ | |||
|       "5a789261c5856700186c65d3" | ||||
|     ] | ||||
|   }, | ||||
|   "5a787fdfc5856700142fdd9a": { | ||||
|     "mod_scope": [ | ||||
|       "609b9e31506cf869cf3eaf41" | ||||
|     ] | ||||
|   }, | ||||
|   "5a787fdfc5856700142fdd9a": {}, | ||||
|   "5a788031c585673f2b5c1c79": { | ||||
|     "mod_foregrip": [ | ||||
|       "5cda9bcfd7f00c0c0b53e900", | ||||
|  |  | |||
|  | @ -12038,7 +12038,7 @@ | |||
|                 "mod_pistol_grip": 100, | ||||
|                 "mod_pistol_grip_akms": 0, | ||||
|                 "mod_pistolgrip": 0, | ||||
|                 "mod_pistolgrip_000": 0, | ||||
|                 "mod_pistolgrip_000": 100, | ||||
|                 "mod_reciever": 100, | ||||
|                 "mod_scope": 13, | ||||
|                 "mod_scope_000": 0, | ||||
|  |  | |||
|  | @ -7006,11 +7006,7 @@ | |||
|       "5a789261c5856700186c65d3" | ||||
|     ] | ||||
|   }, | ||||
|   "5a787fdfc5856700142fdd9a": { | ||||
|     "mod_scope": [ | ||||
|       "609b9e31506cf869cf3eaf41" | ||||
|     ] | ||||
|   }, | ||||
|   "5a787fdfc5856700142fdd9a": {}, | ||||
|   "5a788031c585673f2b5c1c79": { | ||||
|     "mod_foregrip": [ | ||||
|       "5cda9bcfd7f00c0c0b53e900", | ||||
|  |  | |||
|  | @ -0,0 +1,28 @@ | |||
| [General] | ||||
| gameName=spt | ||||
| modid=0 | ||||
| version=d2025.1.8.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.0", | ||||
|     "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,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,167 @@ | |||
| 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;                     | ||||
|                 } | ||||
| 
 | ||||
|                 if (!botGenerationDetails.isPmc && !botGenerationDetails.isPlayerScav && ModConfig.config.enableScavCustomLevelDeltas) | ||||
|                 { | ||||
|                     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; | ||||
|                 } | ||||
| 
 | ||||
|                 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": 5, | ||||
|             "ShortRange": 95 | ||||
|         }, | ||||
|         "factory4_night": | ||||
|         { | ||||
|             "LongRange": 1, | ||||
|             "ShortRange": 99 | ||||
|         }, | ||||
|         "factory4_day": | ||||
|         { | ||||
|             "LongRange": 1, | ||||
|             "ShortRange": 99 | ||||
|         }, | ||||
|         "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,236 @@ | |||
| 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 | ||||
|     ) | ||||
|     {} | ||||
| 
 | ||||
|     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); | ||||
|     } | ||||
| 
 | ||||
|     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") | ||||
|             { | ||||
|                 this.apbsLogger.log(Logging.WARN, `"${ammoBlacklist[item]}" in Ammo Blacklist is either an invalid ammunition or item ID.`) | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     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) | ||||
|             { | ||||
|                 this.apbsLogger.log(Logging.WARN, `"${equipmentBlacklist[item]}" in Equipment Blacklist is an invalid item ID.`) | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     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) | ||||
|             { | ||||
|                 this.apbsLogger.log(Logging.WARN, `"${weaponBlacklist[item]}" in Weapon Blacklist is an invalid item ID.`) | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     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) | ||||
|             { | ||||
|                 this.apbsLogger.log(Logging.WARN, `"${attachmentBlacklist[item]}" in Attachment Blacklist is either an invalid attachment or item ID.`) | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|      | ||||
|     private getItem(tpl: string): ITemplateItem | ||||
|     { | ||||
|         if (tpl in this.database.getItems()) | ||||
|         { | ||||
|             return this.database.getItems()[tpl]; | ||||
|         } | ||||
| 
 | ||||
|         return undefined; | ||||
|     } | ||||
| } | ||||
|  | @ -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,672 @@ | |||
| /* 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.clothingBlacklist = [ | ||||
|             "668bc5cd834c88e06b08b645", // All of this is Artem hands, because they are being configured as Body instead...Crackboooonnneee!!
 | ||||
|             "668bc5cd834c88e06b08b64a", | ||||
|             "668bc5cd834c88e06b08b64d", | ||||
|             "668bc5cd834c88e06b08b650", | ||||
|             "668bc5cd834c88e06b08b652", | ||||
|             "668bc5cd834c88e06b08b655", | ||||
|             "668bc5cd834c88e06b08b658", | ||||
|             "668bc5cd834c88e06b08b65b", | ||||
|             "668bc5cd834c88e06b08b65e", | ||||
|             "668bc5cd834c88e06b08b662", | ||||
|             "668bc5cd834c88e06b08b665", | ||||
|             "668bc5cd834c88e06b08b668", | ||||
|             "668bc5cd834c88e06b08b66b", | ||||
|             "668bc5cd834c88e06b08b66e", | ||||
|             "668bc5cd834c88e06b08b671", | ||||
|             "668bc5cd834c88e06b08b674", | ||||
|             "668bc5cd834c88e06b08b677", | ||||
|             "668bc5cd834c88e06b08b67a", | ||||
|             "668bc5cd834c88e06b08b67d" | ||||
|         ] | ||||
|     } | ||||
| 
 | ||||
|     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: ITemplateItem = {}; | ||||
|         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, 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: ITemplateItem = {}; | ||||
|         vanillaItemList.equipment.ArmorVest.forEach(element => armours[element] = this.getItem(element)) | ||||
| 
 | ||||
|         const headwear: ITemplateItem = {}; | ||||
|         vanillaItemList.equipment.Headwear.forEach(element => headwear[element] = this.getItem(element)) | ||||
| 
 | ||||
|         const tacticalVests: ITemplateItem = {};         | ||||
|         vanillaItemList.equipment.TacticalVest.forEach(element => tacticalVests[element] = this.getItem(element)) | ||||
|          | ||||
|         // Push these lists to the function to filter and import
 | ||||
|         this.getModdedItems(armours, BaseClasses.ARMOR, "Armours"); | ||||
|         this.getModdedItems(headwear, BaseClasses.HEADWEAR, "Helmets"); | ||||
|         this.getModdedItems(tacticalVests, 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: ICustomizationItem = {}; | ||||
|         vanillaClothingList.appearance.body.forEach(element => body[element] = this.getCustomization(element)) | ||||
| 
 | ||||
|         const feet: ICustomizationItem = {}; | ||||
|         vanillaClothingList.appearance.feet.forEach(element => feet[element] = this.getCustomization(element)) | ||||
| 
 | ||||
|         // Push these lists to the function to filter and import
 | ||||
|         this.getModdedClothing(body, "Body"); | ||||
|         this.getModdedClothing(feet, "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; | ||||
|     } | ||||
| } | ||||
Some files were not shown because too many files have changed in this diff Show More
		Loading…
	
		Reference in New Issue