diff --git a/project/.swcrc b/project/.swcrc index 7bed62cc..5a8f797e 100644 --- a/project/.swcrc +++ b/project/.swcrc @@ -15,14 +15,10 @@ "keepClassNames": true, "baseUrl": "./", "paths": { - "@spt/*": [ - "src/*" - ] + "@spt/*": ["src/*"] } }, - "exclude": [ - "node_modules/" - ], + "exclude": ["node_modules/"], "module": { "type": "commonjs", "strict": false, diff --git a/project/assets/configs/airdrop.json b/project/assets/configs/airdrop.json index 560cc432..71aefac1 100644 --- a/project/assets/configs/airdrop.json +++ b/project/assets/configs/airdrop.json @@ -104,12 +104,7 @@ "max": 50 } }, - "armorLevelWhitelist": [ - 0, - 4, - 5, - 6 - ], + "armorLevelWhitelist": [0, 4, 5, 6], "allowBossItems": false }, "weaponArmor": { @@ -181,13 +176,7 @@ "max": 50 } }, - "armorLevelWhitelist": [ - 0, - 3, - 4, - 5, - 6 - ], + "armorLevelWhitelist": [0, 3, 4, 5, 6], "allowBossItems": false }, "foodMedical": { @@ -267,9 +256,7 @@ "max": 50 } }, - "armorLevelWhitelist": [ - 0 - ], + "armorLevelWhitelist": [0], "allowBossItems": false }, "barter": { @@ -350,10 +337,8 @@ "max": 50 } }, - "armorLevelWhitelist": [ - 0 - ], + "armorLevelWhitelist": [0], "allowBossItems": false } } -} \ No newline at end of file +} diff --git a/project/assets/configs/bot.json b/project/assets/configs/bot.json index 239a2d2d..17cf3ddd 100644 --- a/project/assets/configs/bot.json +++ b/project/assets/configs/bot.json @@ -47,8 +47,8 @@ "sectactPriestEvent": 10, "pmcUSEC": 15, "pmcBEAR": 15, - "peacemaker": 10, - "skier": 10 + "peacemaker": 10, + "skier": 10 }, "bosses": [ "bossBully", @@ -277,12 +277,9 @@ }, "chanceAssaultScavHasPlayerScavName": 10, "secureContainerAmmoStackCount": 20, - "botRolesWithDogTags": [ - "pmcbear", - "pmcusec" - ], + "botRolesWithDogTags": ["pmcbear", "pmcusec"], "revenge": { - "pmcBot": ["pmcBot","gifter"], + "pmcBot": ["pmcBot", "gifter"], "arenaFighter": ["pmcBot", "gifter"], "arenaFighterEvent": ["pmcBot", "gifter"], "bossKnight": ["exUsec", "gifter", "bossKnight", "followerBigPipe", "followerBirdEye"], @@ -430,8 +427,8 @@ "544fb37f4bdc2dee738b4567": 2 }, "shooterbtr": {}, - "skier": {}, - "peacemaker": {} + "skier": {}, + "peacemaker": {} }, "equipment": { "assault": { @@ -495,9 +492,7 @@ "lightIsActiveNightChancePercent": 90, "laserIsActiveChancePercent": 85, "forceStock": true, - "weaponSlotIdsToMakeRequired": [ - "mod_reciever" - ] + "weaponSlotIdsToMakeRequired": ["mod_reciever"] }, "bossbully": { "nvgIsActiveChanceDayPercent": 10, @@ -776,11 +771,9 @@ "scopeLimit": 1, "lightLaserLimit": 1 }, - "weaponSlotIdsToMakeRequired": [ - "mod_reciever" - ] + "weaponSlotIdsToMakeRequired": ["mod_reciever"] }, - "peacemaker": { + "peacemaker": { "nvgIsActiveChanceDayPercent": 10, "nvgIsActiveChanceNightPercent": 95, "faceShieldIsActiveChancePercent": 100, @@ -793,7 +786,7 @@ "lightLaserLimit": 1 } }, - "skier": { + "skier": { "nvgIsActiveChanceDayPercent": 10, "nvgIsActiveChanceNightPercent": 95, "faceShieldIsActiveChancePercent": 100, @@ -926,11 +919,7 @@ "laserIsActiveChancePercent": 85, "forceOnlyArmoredRigWhenNoArmor": true, "filterPlatesByLevel": true, - "weaponSlotIdsToMakeRequired": [ - "mod_reciever", - "mod_stock", - "mod_muzzle" - ], + "weaponSlotIdsToMakeRequired": ["mod_reciever", "mod_stock", "mod_muzzle"], "randomisation": [ { "levelRange": { @@ -1148,11 +1137,7 @@ "Scabbard": 100, "TacticalVest": 90 }, - "randomisedArmorSlots": [ - "Headwear", - "ArmorVest", - "TacticalVest" - ], + "randomisedArmorSlots": ["Headwear", "ArmorVest", "TacticalVest"], "randomisedWeaponModSlots": [ "mod_scope", "mod_scope_000", @@ -1250,11 +1235,7 @@ "SecondPrimaryWeapon": 10, "FaceCover": 50 }, - "randomisedArmorSlots": [ - "Headwear", - "TacticalVest", - "ArmorVest" - ], + "randomisedArmorSlots": ["Headwear", "TacticalVest", "ArmorVest"], "randomisedWeaponModSlots": [ "mod_scope", "mod_scope_000", @@ -1321,11 +1302,7 @@ "mod_muzzle_000": 95, "mod_muzzle_001": 95 }, - "randomisedArmorSlots": [ - "Headwear", - "TacticalVest", - "ArmorVest" - ], + "randomisedArmorSlots": ["Headwear", "TacticalVest", "ArmorVest"], "randomisedWeaponModSlots": [ "mod_scope", "mod_scope_000", @@ -1397,30 +1374,15 @@ "65392f611406374f82152ba5", "653931da5db71d30ab1d6296" ], - "mod_nvg": [ - "5c11046cd174af02a012e42b" - ], - "mod_reciever": [ - "5d4405aaa4b9361e6a4e6bd3" - ], - "mod_stock": [ - "5cde739cd7f00c0010373bd3" - ], - "mod_rear_sight": [ - "5a0ed824fcdbcb0176308b0d" - ], - "mod_front_sight": [ - "5a0f096dfcdbcb0176308b15" - ] + "mod_nvg": ["5c11046cd174af02a012e42b"], + "mod_reciever": ["5d4405aaa4b9361e6a4e6bd3"], + "mod_stock": ["5cde739cd7f00c0010373bd3"], + "mod_rear_sight": ["5a0ed824fcdbcb0176308b0d"], + "mod_front_sight": ["5a0f096dfcdbcb0176308b15"] }, "cartridge": { - "Caliber23x75": [ - "5e85a9f4add9fe03027d9bf1" - ], - "Caliber127x55": [ - "5cadf6e5ae921500113bb973", - "5cadf6ddae9215051e1c23b2" - ] + "Caliber23x75": ["5e85a9f4add9fe03027d9bf1"], + "Caliber127x55": ["5cadf6e5ae921500113bb973", "5cadf6ddae9215051e1c23b2"] } } ], @@ -2677,10 +2639,7 @@ "569668774bdc2da2298b4568": 0, "5696686a4bdc2da3298b456a": 0 }, - "walletTplPool": [ - "5783c43d2459774bbe137486", - "60b0f6c058e0b0481a09ad11" - ] + "walletTplPool": ["5783c43d2459774bbe137486", "60b0f6c058e0b0481a09ad11"] }, "currencyStackSize": { "default": { @@ -2705,7 +2664,7 @@ "1": 8, "2": 4, "5": 4, - "10": 1 + "10": 1 } }, "assault": { @@ -2735,7 +2694,14 @@ } } }, - "lowProfileGasBlockTpls": ["61702f1b67085e45ef140b26", "5dfa3d45dfc58d14537c20b0", "5bb20dcad4351e3bac1212da", "56eabcd4d2720b66698b4574", "6065dc8a132d4d12c81fd8e3", "55d4af3a4bdc2d972f8b456f"], + "lowProfileGasBlockTpls": [ + "61702f1b67085e45ef140b26", + "5dfa3d45dfc58d14537c20b0", + "5bb20dcad4351e3bac1212da", + "56eabcd4d2720b66698b4574", + "6065dc8a132d4d12c81fd8e3", + "55d4af3a4bdc2d972f8b456f" + ], "disableLootOnBotTypes": [], "assaultToBossConversion": { "bossConvertEnabled": false, @@ -2758,4 +2724,4 @@ } } } -} \ No newline at end of file +} diff --git a/project/assets/configs/core.json b/project/assets/configs/core.json index e3d7776f..46d4d48e 100644 --- a/project/assets/configs/core.json +++ b/project/assets/configs/core.json @@ -27,11 +27,11 @@ "commandoFeatures": { "giveCommandEnabled": true }, - "commandUseLimits": { - "StashRows": 15 - } + "commandUseLimits": { + "StashRows": 15 + } }, - "createNewProfileTypesBlacklist": [] + "createNewProfileTypesBlacklist": [] }, - "customWatermarkLocaleKeys": [] + "customWatermarkLocaleKeys": [] } diff --git a/project/assets/configs/gifts.json b/project/assets/configs/gifts.json index 5cc13d92..681a737b 100644 --- a/project/assets/configs/gifts.json +++ b/project/assets/configs/gifts.json @@ -220,7 +220,7 @@ "slotId": "Helmet_back" } ], - "maxToSendPlayer": 1 + "maxToSendPlayer": 1 }, "NewYear2021": { "sender": "System", @@ -449,7 +449,7 @@ "slotId": "mod_charge" } ], - "maxToSendPlayer": 1 + "maxToSendPlayer": 1 }, "Christmas2022": { "items": [ @@ -504,7 +504,7 @@ "timestampToSend": 42069, "associatedEvent": "Christmas", "collectionTimeHours": 48, - "maxToSendPlayer": 1 + "maxToSendPlayer": 1 }, "1CLICKDRESSUP": { "items": [ @@ -669,7 +669,7 @@ "timestampToSend": 42069, "collectionTimeHours": 48, "associatedEvent": "Promo", - "maxToSendPlayer": 1 + "maxToSendPlayer": 1 }, "BARMALEY": { "items": [ @@ -831,7 +831,7 @@ "timestampToSend": 42069, "collectionTimeHours": 48, "associatedEvent": "Promo", - "maxToSendPlayer": 1 + "maxToSendPlayer": 1 }, "S00NS00N": { "items": [ @@ -913,7 +913,7 @@ "timestampToSend": 42069, "collectionTimeHours": 48, "associatedEvent": "Promo", - "maxToSendPlayer": 1 + "maxToSendPlayer": 1 }, "TRAMBON": { "items": [ @@ -1091,7 +1091,7 @@ "timestampToSend": 42069, "collectionTimeHours": 48, "associatedEvent": "Promo", - "maxToSendPlayer": 1 + "maxToSendPlayer": 1 }, "PINEWOOD": { "items": [ @@ -1181,7 +1181,7 @@ "timestampToSend": 42069, "collectionTimeHours": 48, "associatedEvent": "Promo", - "maxToSendPlayer": 1 + "maxToSendPlayer": 1 }, "HESOYAM": { "items": [ @@ -1199,7 +1199,7 @@ "messageText": "HESOYAM", "collectionTimeHours": 48, "associatedEvent": "Promo", - "maxToSendPlayer": 1 + "maxToSendPlayer": 1 }, "PraporGiftDay1": { "items": [ @@ -1235,7 +1235,7 @@ "trader": "PRAPOR", "localeTextId": "5fd4c8b59e4b2a58b34bbd28 0", "collectionTimeHours": 48, - "maxToSendPlayer": 5 + "maxToSendPlayer": 5 }, "PraporGiftDay2": { "items": [ @@ -1248,7 +1248,7 @@ }, "parentId": "64b996c9d0de4697180359b6" }, - { + { "_id": "a89275c1b18874ed7452a6d7", "_tpl": "5751a25924597722c463c472", "slotId": "main", @@ -1298,7 +1298,7 @@ "trader": "PRAPOR", "localeTextId": "5fd4c8d49e4b2a58b34bbd29 0", "collectionTimeHours": 48, - "maxToSendPlayer": 5 + "maxToSendPlayer": 5 }, "KAPPA4U": { "items": [ @@ -1316,7 +1316,7 @@ "messageText": "Easy Kappa", "collectionTimeHours": 48, "associatedEvent": "Promo", - "maxToSendPlayer": 1 + "maxToSendPlayer": 1 }, "ENDOFWIPE": { "items": [ @@ -1343,7 +1343,7 @@ "localeTextId": "626e5d63bc92c87fd22a943f 0", "collectionTimeHours": 48, "associatedEvent": "Promo", - "maxToSendPlayer": 1 + "maxToSendPlayer": 1 }, "IAMADIRTYLITTLEGOBLIN": { "items": [ @@ -1361,7 +1361,7 @@ "messageText": "You dirty little cheating goblin", "collectionTimeHours": 48, "associatedEvent": "Promo", - "maxToSendPlayer": 5 + "maxToSendPlayer": 5 }, "CHOMP": { "items": [ @@ -1379,7 +1379,7 @@ "messageText": "caw caw", "collectionTimeHours": 48, "associatedEvent": "Promo", - "maxToSendPlayer": 1 + "maxToSendPlayer": 1 }, "CWX": { "items": [ @@ -1397,7 +1397,7 @@ "messageText": "un oh stinky", "collectionTimeHours": 48, "associatedEvent": "Promo", - "maxToSendPlayer": 1 + "maxToSendPlayer": 1 }, "VALENS": { "items": [ @@ -1538,7 +1538,7 @@ "messageText": "It's time to pew pew.", "collectionTimeHours": 48, "associatedEvent": "Promo", - "maxToSendPlayer": 1 + "maxToSendPlayer": 1 }, "TERKOIZ": { "items": [ @@ -1556,7 +1556,7 @@ "messageText": "Out of the way, i'm a motorist", "collectionTimeHours": 48, "associatedEvent": "Promo", - "maxToSendPlayer": 1 + "maxToSendPlayer": 1 }, "WAFFLE": { "items": [ @@ -1583,7 +1583,7 @@ "messageText": "JONKLER NO", "collectionTimeHours": 48, "associatedEvent": "Promo", - "maxToSendPlayer": 1 + "maxToSendPlayer": 1 }, "NIGHTWING": { "items": [ @@ -1610,8 +1610,8 @@ "messageText": "JONKLER NO", "collectionTimeHours": 48, "associatedEvent": "Promo", - "maxToSendToPlayer": 1, - "maxToSendPlayer": 1 + "maxToSendToPlayer": 1, + "maxToSendPlayer": 1 }, "BSGBIRTHDAY2023": { "sender": "System", @@ -1758,7 +1758,7 @@ "slotId": "main" } ], - "maxToSendPlayer": 1 + "maxToSendPlayer": 1 }, "GROUNDZERO": { "items": [ @@ -1772,7 +1772,7 @@ "messageText": "GROUNDZERO", "collectionTimeHours": 48, "associatedEvent": "Promo", - "maxToSendPlayer": 1 + "maxToSendPlayer": 1 }, "IAMMIGHTY": { "items": [ @@ -2013,7 +2013,7 @@ "messageText": "IAMMIGHTY", "collectionTimeHours": 48, "associatedEvent": "Promo", - "maxToSendPlayer": 1 + "maxToSendPlayer": 1 }, "ARMORPLATES": { "items": [ @@ -2148,7 +2148,7 @@ "messageText": "ARMORPLATES", "collectionTimeHours": 48, "associatedEvent": "Promo", - "maxToSendPlayer": 1 + "maxToSendPlayer": 1 }, "RICHANDEXPENSIVE": { "items": [ @@ -2217,7 +2217,7 @@ "messageText": "RICHANDEXPENSIVE", "collectionTimeHours": 48, "associatedEvent": "Promo", - "maxToSendPlayer": 1 + "maxToSendPlayer": 1 }, "LEFTHANDHEADEYES": { "items": [ @@ -2244,7 +2244,7 @@ "messageText": "LEFTHANDHEADEYES", "collectionTimeHours": 48, "associatedEvent": "Promo", - "maxToSendPlayer": 1 + "maxToSendPlayer": 1 }, "EDITPROFILE": { "items": [ @@ -2667,7 +2667,7 @@ "localeTextId": "5a2d28f786f77436023be4a5 0", "collectionTimeHours": 72, "associatedEvent": "Promo", - "maxToSendPlayer": 50 + "maxToSendPlayer": 50 }, "TWITCHNEWYEARS2023": { "items": [ @@ -3082,7 +3082,7 @@ "localeTextId": "5e0653ba86f774478f700632 3", "collectionTimeHours": 72, "associatedEvent": "Promo", - "maxToSendPlayer": 1 + "maxToSendPlayer": 1 }, "LUNARNEWYEAR2024": { "items": [ @@ -3276,7 +3276,7 @@ "associatedEvent": "Promo", "collectionTimeHours": 72, "messageText": "Thank you for activating the code.Thank you for activating the code.Thank you for activating the code.Thank you for activating the code.Thank you for activating the code.Thank you for activating the code.Thank you for activating the code.Thank you for activating the code.Thank you for activating the code.Thank you for activating the code.Thank you for activating the code.Thank you for activating the code.Thank you for activating the code.Thank you for activating the code.Thank you for activating the code.Thank you for activating the code.Thank you for activating the code.", - "maxToSendPlayer": 1 + "maxToSendPlayer": 1 }, "ETSREWARD": { "items": [ @@ -3524,7 +3524,7 @@ "associatedEvent": "Promo", "collectionTimeHours": 72, "messageText": "Greetings, warrior. I've heard you've been helping out our local hard workers with their stuff, testing everything out, so to speak. That's a good deed, soldier, great job. The higher-ups sent you a little present as a token of gratitude. Keep it up!Greetings, warrior. I've heard you've been helping out our local hard workers with their stuff, testing everything out, so to speak. That's a good deed, soldier, great job. The higher-ups sent you a little present as a token of gratitude. Keep it up!Greetings, warrior. I've heard you've been helping out our local hard workers with their stuff, testing everything out, so to speak. That's a good deed, soldier, great job. The higher-ups sent you a little present as a token of gratitude. Keep it up!Greetings, warrior. I've heard you've been helping out our local hard workers with their stuff, testing everything out, so to speak. That's a good deed, soldier, great job. The higher-ups sent you a little present as a token of gratitude. Keep it up!Greetings, warrior. I've heard you've been helping out our local hard workers with their stuff, testing everything out, so to speak. That's a good deed, soldier, great job. The higher-ups sent you a little present as a token of gratitude. Keep it up!Greetings, warrior. I've heard you've been helping out our local hard workers with their stuff, testing everything out, so to speak. That's a good deed, soldier, great job. The higher-ups sent you a little present as a token of gratitude. Keep it up!Greetings, warrior. I've heard you've been helping out our local hard workers with their stuff, testing everything out, so to speak. That's a good deed, soldier, great job. The higher-ups sent you a little present as a token of gratitude. Keep it up!Greetings, warrior. I've heard you've been helping out our local hard workers with their stuff, testing everything out, so to speak. That's a good deed, soldier, great job. The higher-ups sent you a little present as a token of gratitude. Keep it up!Greetings, warrior. I've heard you've been helping out our local hard workers with their stuff, testing everything out, so to speak. That's a good deed, soldier, great job. The higher-ups sent you a little present as a token of gratitude. Keep it up!Greetings, warrior. I've heard you've been helping out our local hard workers with their stuff, testing everything out, so to speak. That's a good deed, soldier, great job. The higher-ups sent you a little present as a token of gratitude. Keep it up!Greetings, warrior. I've heard you've been helping out our local hard workers with their stuff, testing everything out, so to speak. That's a good deed, soldier, great job. The higher-ups sent you a little present as a token of gratitude. Keep it up!Greetings, warrior. I've heard you've been helping out our local hard workers with their stuff, testing everything out, so to speak. That's a good deed, soldier, great job. The higher-ups sent you a little present as a token of gratitude. Keep it up!Greetings, warrior. I've heard you've been helping out our local hard workers with their stuff, testing everything out, so to speak. That's a good deed, soldier, great job. The higher-ups sent you a little present as a token of gratitude. Keep it up!Greetings, warrior. I've heard you've been helping out our local hard workers with their stuff, testing everything out, so to speak. That's a good deed, soldier, great job. The higher-ups sent you a little present as a token of gratitude. Keep it up!Greetings, warrior. I've heard you've been helping out our local hard workers with their stuff, testing everything out, so to speak. That's a good deed, soldier, great job. The higher-ups sent you a little present as a token of gratitude. Keep it up!Привет, боец. Слыхал, ты местным работягам активно помогал, проверял всё на прочность, так сказать. Это дело правильное, молодец, вояка. Ребята сверху тебе за это подарочек передали в знак благодарности. Продолжай в том же духе!Promo code is activated", - "maxToSendPlayer": 1 + "maxToSendPlayer": 1 }, "KONTOROVICH": { "items": [ @@ -3721,7 +3721,7 @@ "associatedEvent": "Promo", "collectionTimeHours": 72, "messageText": "Thank you for purchasing of the first book in EFT series by A, Kontorovich. We are glad to give you this theme package with ingame items.", - "maxToSendPlayer": 1 + "maxToSendPlayer": 1 }, "UNHEARD": { "items": [ @@ -3739,3234 +3739,3744 @@ "messageText": "Have a nice 20 minute adventure in the blatant plagiarist game. In and out", "collectionTimeHours": 72, "associatedEvent": "Promo", - "maxToSendPlayer": 1 + "maxToSendPlayer": 1 }, - "TOURNAMENTGIFT": { - "items": [{ - "_id": "668014ea2b680c65290bbd0a", - "_tpl": "5449016a4bdc2d6f028b456f", - "upd": { - "StackObjectsCount": 500000 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd0b", - "_tpl": "5449016a4bdc2d6f028b456f", - "upd": { - "StackObjectsCount": 500000 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd0c", - "_tpl": "5449016a4bdc2d6f028b456f", - "upd": { - "StackObjectsCount": 500000 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd0d", - "_tpl": "5449016a4bdc2d6f028b456f", - "upd": { - "StackObjectsCount": 500000 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd0e", - "_tpl": "5449016a4bdc2d6f028b456f", - "upd": { - "StackObjectsCount": 500000 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd0f", - "_tpl": "5449016a4bdc2d6f028b456f", - "upd": { - "StackObjectsCount": 500000 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd10", - "_tpl": "5449016a4bdc2d6f028b456f", - "upd": { - "StackObjectsCount": 500000 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd11", - "_tpl": "5449016a4bdc2d6f028b456f", - "upd": { - "StackObjectsCount": 500000 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd12", - "_tpl": "5449016a4bdc2d6f028b456f", - "upd": { - "StackObjectsCount": 500000 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd13", - "_tpl": "5449016a4bdc2d6f028b456f", - "upd": { - "StackObjectsCount": 500000 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd14", - "_tpl": "5449016a4bdc2d6f028b456f", - "upd": { - "StackObjectsCount": 500000 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd15", - "_tpl": "5449016a4bdc2d6f028b456f", - "upd": { - "StackObjectsCount": 500000 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd16", - "_tpl": "5449016a4bdc2d6f028b456f", - "upd": { - "StackObjectsCount": 500000 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd17", - "_tpl": "5449016a4bdc2d6f028b456f", - "upd": { - "StackObjectsCount": 500000 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd18", - "_tpl": "5449016a4bdc2d6f028b456f", - "upd": { - "StackObjectsCount": 500000 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd19", - "_tpl": "5449016a4bdc2d6f028b456f", - "upd": { - "StackObjectsCount": 500000 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd1a", - "_tpl": "5449016a4bdc2d6f028b456f", - "upd": { - "StackObjectsCount": 500000 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd1b", - "_tpl": "5449016a4bdc2d6f028b456f", - "upd": { - "StackObjectsCount": 500000 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd1c", - "_tpl": "5449016a4bdc2d6f028b456f", - "upd": { - "StackObjectsCount": 500000 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd1d", - "_tpl": "5449016a4bdc2d6f028b456f", - "upd": { - "StackObjectsCount": 500000 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd1e", - "_tpl": "5449016a4bdc2d6f028b456f", - "upd": { - "StackObjectsCount": 500000 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd1f", - "_tpl": "5449016a4bdc2d6f028b456f", - "upd": { - "StackObjectsCount": 500000 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd20", - "_tpl": "5449016a4bdc2d6f028b456f", - "upd": { - "StackObjectsCount": 500000 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd21", - "_tpl": "5449016a4bdc2d6f028b456f", - "upd": { - "StackObjectsCount": 500000 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd22", - "_tpl": "5449016a4bdc2d6f028b456f", - "upd": { - "StackObjectsCount": 500000 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd23", - "_tpl": "5449016a4bdc2d6f028b456f", - "upd": { - "StackObjectsCount": 500000 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd24", - "_tpl": "5449016a4bdc2d6f028b456f", - "upd": { - "StackObjectsCount": 500000 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd25", - "_tpl": "5449016a4bdc2d6f028b456f", - "upd": { - "StackObjectsCount": 500000 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd26", - "_tpl": "5449016a4bdc2d6f028b456f", - "upd": { - "StackObjectsCount": 500000 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd27", - "_tpl": "5449016a4bdc2d6f028b456f", - "upd": { - "StackObjectsCount": 500000 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd29", - "_tpl": "5696686a4bdc2da3298b456a", - "upd": { - "StackObjectsCount": 10000 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd2b", - "_tpl": "569668774bdc2da2298b4568", - "upd": { - "StackObjectsCount": 10000 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd2d", - "_tpl": "5c0e531d86f7747fa23f4d42", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd2e", - "_tpl": "5c0e531d86f7747fa23f4d42", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd2f", - "_tpl": "5c0e531d86f7747fa23f4d42", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd30", - "_tpl": "5c0e531d86f7747fa23f4d42", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd31", - "_tpl": "5c0e531d86f7747fa23f4d42", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd32", - "_tpl": "5c0e531d86f7747fa23f4d42", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd33", - "_tpl": "5c0e531d86f7747fa23f4d42", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd34", - "_tpl": "5c0e531d86f7747fa23f4d42", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd35", - "_tpl": "5c0e531d86f7747fa23f4d42", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd36", - "_tpl": "5c0e531d86f7747fa23f4d42", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd37", - "_tpl": "5c0e531d86f7747fa23f4d42", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd38", - "_tpl": "5c0e531d86f7747fa23f4d42", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd39", - "_tpl": "5c0e531d86f7747fa23f4d42", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd3a", - "_tpl": "5c0e531d86f7747fa23f4d42", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd3b", - "_tpl": "5c0e531d86f7747fa23f4d42", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd3c", - "_tpl": "5c0e531d86f7747fa23f4d42", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd3d", - "_tpl": "5c0e531d86f7747fa23f4d42", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd3e", - "_tpl": "5c0e531d86f7747fa23f4d42", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd3f", - "_tpl": "5c0e531d86f7747fa23f4d42", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd40", - "_tpl": "5c0e531d86f7747fa23f4d42", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd42", - "_tpl": "5c0126f40db834002a125382", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd44", - "_tpl": "5c12688486f77426843c7d32", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd46", - "_tpl": "590c5d4b86f774784e1b9c45", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd47", - "_tpl": "590c5d4b86f774784e1b9c45", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd48", - "_tpl": "590c5d4b86f774784e1b9c45", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd49", - "_tpl": "590c5d4b86f774784e1b9c45", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd4a", - "_tpl": "590c5d4b86f774784e1b9c45", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd4b", - "_tpl": "590c5d4b86f774784e1b9c45", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd4c", - "_tpl": "590c5d4b86f774784e1b9c45", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd4d", - "_tpl": "590c5d4b86f774784e1b9c45", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd4e", - "_tpl": "590c5d4b86f774784e1b9c45", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd4f", - "_tpl": "590c5d4b86f774784e1b9c45", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd51", - "_tpl": "5c0fa877d174af02a012e1cf", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd52", - "_tpl": "5c0fa877d174af02a012e1cf", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd53", - "_tpl": "5c0fa877d174af02a012e1cf", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd54", - "_tpl": "5c0fa877d174af02a012e1cf", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd55", - "_tpl": "5c0fa877d174af02a012e1cf", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd57", - "_tpl": "5e8488fa988a8701445df1e4", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd58", - "_tpl": "5e8488fa988a8701445df1e4", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd59", - "_tpl": "5e8488fa988a8701445df1e4", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd5a", - "_tpl": "5e8488fa988a8701445df1e4", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd5b", - "_tpl": "5e8488fa988a8701445df1e4", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd5c", - "_tpl": "5e8488fa988a8701445df1e4", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd5d", - "_tpl": "5e8488fa988a8701445df1e4", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd5e", - "_tpl": "5e8488fa988a8701445df1e4", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd5f", - "_tpl": "5e8488fa988a8701445df1e4", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd60", - "_tpl": "5e8488fa988a8701445df1e4", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd62", - "_tpl": "5af0548586f7743a532b7e99", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd63", - "_tpl": "5af0548586f7743a532b7e99", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd64", - "_tpl": "5af0548586f7743a532b7e99", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd65", - "_tpl": "5af0548586f7743a532b7e99", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd66", - "_tpl": "5af0548586f7743a532b7e99", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd67", - "_tpl": "5af0548586f7743a532b7e99", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd69", - "_tpl": "5c0e534186f7747fa1419867", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd6a", - "_tpl": "5c0e534186f7747fa1419867", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd6b", - "_tpl": "5c0e534186f7747fa1419867", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd6c", - "_tpl": "5c0e534186f7747fa1419867", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd6d", - "_tpl": "5c0e534186f7747fa1419867", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd6e", - "_tpl": "5c0e534186f7747fa1419867", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd6f", - "_tpl": "5c0e534186f7747fa1419867", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd70", - "_tpl": "5c0e534186f7747fa1419867", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd71", - "_tpl": "5c0e534186f7747fa1419867", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd72", - "_tpl": "5c0e534186f7747fa1419867", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd73", - "_tpl": "5c0e534186f7747fa1419867", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd74", - "_tpl": "5c0e534186f7747fa1419867", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd75", - "_tpl": "5c0e534186f7747fa1419867", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd76", - "_tpl": "5c0e534186f7747fa1419867", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd77", - "_tpl": "5c0e534186f7747fa1419867", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd78", - "_tpl": "5c0e534186f7747fa1419867", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd79", - "_tpl": "5c0e534186f7747fa1419867", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd7a", - "_tpl": "5c0e534186f7747fa1419867", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd7b", - "_tpl": "5c0e534186f7747fa1419867", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd7c", - "_tpl": "5c0e534186f7747fa1419867", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd7e", - "_tpl": "637b620db7afa97bfc3d7009", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd7f", - "_tpl": "637b620db7afa97bfc3d7009", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd80", - "_tpl": "637b620db7afa97bfc3d7009", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd81", - "_tpl": "637b620db7afa97bfc3d7009", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd82", - "_tpl": "637b620db7afa97bfc3d7009", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd83", - "_tpl": "637b620db7afa97bfc3d7009", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd84", - "_tpl": "637b620db7afa97bfc3d7009", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd85", - "_tpl": "637b620db7afa97bfc3d7009", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd86", - "_tpl": "637b620db7afa97bfc3d7009", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd87", - "_tpl": "637b620db7afa97bfc3d7009", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd88", - "_tpl": "637b620db7afa97bfc3d7009", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd89", - "_tpl": "637b620db7afa97bfc3d7009", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd8a", - "_tpl": "637b620db7afa97bfc3d7009", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd8b", - "_tpl": "637b620db7afa97bfc3d7009", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd8c", - "_tpl": "637b620db7afa97bfc3d7009", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd8d", - "_tpl": "637b620db7afa97bfc3d7009", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd8e", - "_tpl": "637b620db7afa97bfc3d7009", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd8f", - "_tpl": "637b620db7afa97bfc3d7009", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd90", - "_tpl": "637b620db7afa97bfc3d7009", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd91", - "_tpl": "637b620db7afa97bfc3d7009", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd93", - "_tpl": "5d02778e86f774203e7dedbe", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd94", - "_tpl": "5d02778e86f774203e7dedbe", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd95", - "_tpl": "5d02778e86f774203e7dedbe", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd96", - "_tpl": "5d02778e86f774203e7dedbe", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd97", - "_tpl": "5d02778e86f774203e7dedbe", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd99", - "_tpl": "5d02797c86f774203f38e30a", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd9a", - "_tpl": "5d02797c86f774203f38e30a", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd9b", - "_tpl": "5d02797c86f774203f38e30a", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd9c", - "_tpl": "5d02797c86f774203f38e30a", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd9d", - "_tpl": "5d02797c86f774203f38e30a", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbd9f", - "_tpl": "5b3b99265acfc4704b4a1afb", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbda0", - "_tpl": "5b3b99265acfc4704b4a1afb", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbda1", - "_tpl": "5b3b99265acfc4704b4a1afb", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbda2", - "_tpl": "5b3b99265acfc4704b4a1afb", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbda3", - "_tpl": "5b3b99265acfc4704b4a1afb", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbda4", - "_tpl": "5b3b99265acfc4704b4a1afb", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbda5", - "_tpl": "5b3b99265acfc4704b4a1afb", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbda6", - "_tpl": "5b3b99265acfc4704b4a1afb", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbda7", - "_tpl": "5b3b99265acfc4704b4a1afb", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbda8", - "_tpl": "5b3b99265acfc4704b4a1afb", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbda9", - "_tpl": "5b3b99265acfc4704b4a1afb", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbdaa", - "_tpl": "5b3b99265acfc4704b4a1afb", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbdac", - "_tpl": "618ba27d9008e4636a67f61d", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbdad", - "_tpl": "618ba27d9008e4636a67f61d", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbdae", - "_tpl": "618ba27d9008e4636a67f61d", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbdaf", - "_tpl": "618ba27d9008e4636a67f61d", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbdb0", - "_tpl": "618ba27d9008e4636a67f61d", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbdb1", - "_tpl": "618ba27d9008e4636a67f61d", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbdb2", - "_tpl": "618ba27d9008e4636a67f61d", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbdb3", - "_tpl": "618ba27d9008e4636a67f61d", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbdb4", - "_tpl": "618ba27d9008e4636a67f61d", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbdb5", - "_tpl": "618ba27d9008e4636a67f61d", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbdb6", - "_tpl": "618ba27d9008e4636a67f61d", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbdb7", - "_tpl": "618ba27d9008e4636a67f61d", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbdb9", - "_tpl": "617151c1d92c473c770214ab", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbdba", - "_tpl": "617151c1d92c473c770214ab", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbdbb", - "_tpl": "617151c1d92c473c770214ab", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbdbc", - "_tpl": "617151c1d92c473c770214ab", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbdbd", - "_tpl": "617151c1d92c473c770214ab", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbdbe", - "_tpl": "617151c1d92c473c770214ab", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbdbf", - "_tpl": "617151c1d92c473c770214ab", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbdc0", - "_tpl": "617151c1d92c473c770214ab", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbdc1", - "_tpl": "617151c1d92c473c770214ab", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbdc2", - "_tpl": "617151c1d92c473c770214ab", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbdc3", - "_tpl": "617151c1d92c473c770214ab", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbdc4", - "_tpl": "617151c1d92c473c770214ab", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbdc9", - "_tpl": "5bfea6e90db834001b7347f3", - "upd": { - "FireMode": { - "FireMode": "single" - }, - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbdca", - "_tpl": "5bfea7ad0db834001c38f1ee", - "parentId": "668014ea2b680c65290bbdc9", - "slotId": "mod_magazine" - }, { - "_id": "668014ea2b680c65290bbdcb", - "_tpl": "5bfeb32b0db834001a6694d9", - "parentId": "668014ea2b680c65290bbdc9", - "slotId": "mod_stock" - }, { - "_id": "668014ea2b680c65290bbdcc", - "_tpl": "5bfebc320db8340019668d79", - "parentId": "668014ea2b680c65290bbdc9", - "slotId": "mod_barrel" - }, { - "_id": "668014ea2b680c65290bbdcd", - "_tpl": "5bfea6e90db834001b7347f3", - "upd": { - "FireMode": { - "FireMode": "single" - }, - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbdce", - "_tpl": "5bfea7ad0db834001c38f1ee", - "parentId": "668014ea2b680c65290bbdcd", - "slotId": "mod_magazine" - }, { - "_id": "668014ea2b680c65290bbdcf", - "_tpl": "5bfeb32b0db834001a6694d9", - "parentId": "668014ea2b680c65290bbdcd", - "slotId": "mod_stock" - }, { - "_id": "668014ea2b680c65290bbdd0", - "_tpl": "5bfebc320db8340019668d79", - "parentId": "668014ea2b680c65290bbdcd", - "slotId": "mod_barrel" - }, { - "_id": "668014ea2b680c65290bbdd1", - "_tpl": "5bfea6e90db834001b7347f3", - "upd": { - "FireMode": { - "FireMode": "single" - }, - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbdd2", - "_tpl": "5bfea7ad0db834001c38f1ee", - "parentId": "668014ea2b680c65290bbdd1", - "slotId": "mod_magazine" - }, { - "_id": "668014ea2b680c65290bbdd3", - "_tpl": "5bfeb32b0db834001a6694d9", - "parentId": "668014ea2b680c65290bbdd1", - "slotId": "mod_stock" - }, { - "_id": "668014ea2b680c65290bbdd4", - "_tpl": "5bfebc320db8340019668d79", - "parentId": "668014ea2b680c65290bbdd1", - "slotId": "mod_barrel" - }, { - "_id": "668014ea2b680c65290bbdd5", - "_tpl": "5bfea6e90db834001b7347f3", - "upd": { - "FireMode": { - "FireMode": "single" - }, - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbdd6", - "_tpl": "5bfea7ad0db834001c38f1ee", - "parentId": "668014ea2b680c65290bbdd5", - "slotId": "mod_magazine" - }, { - "_id": "668014ea2b680c65290bbdd7", - "_tpl": "5bfeb32b0db834001a6694d9", - "parentId": "668014ea2b680c65290bbdd5", - "slotId": "mod_stock" - }, { - "_id": "668014ea2b680c65290bbdd8", - "_tpl": "5bfebc320db8340019668d79", - "parentId": "668014ea2b680c65290bbdd5", - "slotId": "mod_barrel" - }, { - "_id": "668014ea2b680c65290bbdd9", - "_tpl": "5bfea6e90db834001b7347f3", - "upd": { - "FireMode": { - "FireMode": "single" - }, - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbdda", - "_tpl": "5bfea7ad0db834001c38f1ee", - "parentId": "668014ea2b680c65290bbdd9", - "slotId": "mod_magazine" - }, { - "_id": "668014ea2b680c65290bbddb", - "_tpl": "5bfeb32b0db834001a6694d9", - "parentId": "668014ea2b680c65290bbdd9", - "slotId": "mod_stock" - }, { - "_id": "668014ea2b680c65290bbddc", - "_tpl": "5bfebc320db8340019668d79", - "parentId": "668014ea2b680c65290bbdd9", - "slotId": "mod_barrel" - }, { - "_id": "668014ea2b680c65290bbddd", - "_tpl": "5bfea6e90db834001b7347f3", - "upd": { - "FireMode": { - "FireMode": "single" - }, - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbdde", - "_tpl": "5bfea7ad0db834001c38f1ee", - "parentId": "668014ea2b680c65290bbddd", - "slotId": "mod_magazine" - }, { - "_id": "668014ea2b680c65290bbddf", - "_tpl": "5bfeb32b0db834001a6694d9", - "parentId": "668014ea2b680c65290bbddd", - "slotId": "mod_stock" - }, { - "_id": "668014ea2b680c65290bbde0", - "_tpl": "5bfebc320db8340019668d79", - "parentId": "668014ea2b680c65290bbddd", - "slotId": "mod_barrel" - }, { - "_id": "668014ea2b680c65290bbde1", - "_tpl": "5bfea6e90db834001b7347f3", - "upd": { - "FireMode": { - "FireMode": "single" - }, - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbde2", - "_tpl": "5bfea7ad0db834001c38f1ee", - "parentId": "668014ea2b680c65290bbde1", - "slotId": "mod_magazine" - }, { - "_id": "668014ea2b680c65290bbde3", - "_tpl": "5bfeb32b0db834001a6694d9", - "parentId": "668014ea2b680c65290bbde1", - "slotId": "mod_stock" - }, { - "_id": "668014ea2b680c65290bbde4", - "_tpl": "5bfebc320db8340019668d79", - "parentId": "668014ea2b680c65290bbde1", - "slotId": "mod_barrel" - }, { - "_id": "668014ea2b680c65290bbde5", - "_tpl": "5bfea6e90db834001b7347f3", - "upd": { - "FireMode": { - "FireMode": "single" - }, - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbde6", - "_tpl": "5bfea7ad0db834001c38f1ee", - "parentId": "668014ea2b680c65290bbde5", - "slotId": "mod_magazine" - }, { - "_id": "668014ea2b680c65290bbde7", - "_tpl": "5bfeb32b0db834001a6694d9", - "parentId": "668014ea2b680c65290bbde5", - "slotId": "mod_stock" - }, { - "_id": "668014ea2b680c65290bbde8", - "_tpl": "5bfebc320db8340019668d79", - "parentId": "668014ea2b680c65290bbde5", - "slotId": "mod_barrel" - }, { - "_id": "668014ea2b680c65290bbde9", - "_tpl": "5bfea6e90db834001b7347f3", - "upd": { - "FireMode": { - "FireMode": "single" - }, - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbdea", - "_tpl": "5bfea7ad0db834001c38f1ee", - "parentId": "668014ea2b680c65290bbde9", - "slotId": "mod_magazine" - }, { - "_id": "668014ea2b680c65290bbdeb", - "_tpl": "5bfeb32b0db834001a6694d9", - "parentId": "668014ea2b680c65290bbde9", - "slotId": "mod_stock" - }, { - "_id": "668014ea2b680c65290bbdec", - "_tpl": "5bfebc320db8340019668d79", - "parentId": "668014ea2b680c65290bbde9", - "slotId": "mod_barrel" - }, { - "_id": "668014ea2b680c65290bbded", - "_tpl": "5bfea6e90db834001b7347f3", - "upd": { - "FireMode": { - "FireMode": "single" - }, - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbdee", - "_tpl": "5bfea7ad0db834001c38f1ee", - "parentId": "668014ea2b680c65290bbded", - "slotId": "mod_magazine" - }, { - "_id": "668014ea2b680c65290bbdef", - "_tpl": "5bfeb32b0db834001a6694d9", - "parentId": "668014ea2b680c65290bbded", - "slotId": "mod_stock" - }, { - "_id": "668014ea2b680c65290bbdf0", - "_tpl": "5bfebc320db8340019668d79", - "parentId": "668014ea2b680c65290bbded", - "slotId": "mod_barrel" - }, { - "_id": "668014ea2b680c65290bbdf1", - "_tpl": "5bfea6e90db834001b7347f3", - "upd": { - "FireMode": { - "FireMode": "single" - }, - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbdf2", - "_tpl": "5bfea7ad0db834001c38f1ee", - "parentId": "668014ea2b680c65290bbdf1", - "slotId": "mod_magazine" - }, { - "_id": "668014ea2b680c65290bbdf3", - "_tpl": "5bfeb32b0db834001a6694d9", - "parentId": "668014ea2b680c65290bbdf1", - "slotId": "mod_stock" - }, { - "_id": "668014ea2b680c65290bbdf4", - "_tpl": "5bfebc320db8340019668d79", - "parentId": "668014ea2b680c65290bbdf1", - "slotId": "mod_barrel" - }, { - "_id": "668014ea2b680c65290bbdf5", - "_tpl": "5bfea6e90db834001b7347f3", - "upd": { - "FireMode": { - "FireMode": "single" - }, - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbdf6", - "_tpl": "5bfea7ad0db834001c38f1ee", - "parentId": "668014ea2b680c65290bbdf5", - "slotId": "mod_magazine" - }, { - "_id": "668014ea2b680c65290bbdf7", - "_tpl": "5bfeb32b0db834001a6694d9", - "parentId": "668014ea2b680c65290bbdf5", - "slotId": "mod_stock" - }, { - "_id": "668014ea2b680c65290bbdf8", - "_tpl": "5bfebc320db8340019668d79", - "parentId": "668014ea2b680c65290bbdf5", - "slotId": "mod_barrel" - }, { - "_id": "668014ea2b680c65290bbdfa", - "_tpl": "5a608bf24f39f98ffc77720e", - "upd": { - "StackObjectsCount": 40 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbdfb", - "_tpl": "5a608bf24f39f98ffc77720e", - "upd": { - "StackObjectsCount": 40 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbdfc", - "_tpl": "5a608bf24f39f98ffc77720e", - "upd": { - "StackObjectsCount": 40 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbdfd", - "_tpl": "5a608bf24f39f98ffc77720e", - "upd": { - "StackObjectsCount": 40 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbdfe", - "_tpl": "5a608bf24f39f98ffc77720e", - "upd": { - "StackObjectsCount": 40 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbdff", - "_tpl": "5a608bf24f39f98ffc77720e", - "upd": { - "StackObjectsCount": 40 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbe00", - "_tpl": "5a608bf24f39f98ffc77720e", - "upd": { - "StackObjectsCount": 40 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbe01", - "_tpl": "5a608bf24f39f98ffc77720e", - "upd": { - "StackObjectsCount": 40 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbe02", - "_tpl": "5a608bf24f39f98ffc77720e", - "upd": { - "StackObjectsCount": 40 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbe03", - "_tpl": "5a608bf24f39f98ffc77720e", - "upd": { - "StackObjectsCount": 40 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbe05", - "_tpl": "58dd3ad986f77403051cba8f", - "upd": { - "StackObjectsCount": 40 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbe06", - "_tpl": "58dd3ad986f77403051cba8f", - "upd": { - "StackObjectsCount": 40 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbe07", - "_tpl": "58dd3ad986f77403051cba8f", - "upd": { - "StackObjectsCount": 40 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbe08", - "_tpl": "58dd3ad986f77403051cba8f", - "upd": { - "StackObjectsCount": 40 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbe09", - "_tpl": "58dd3ad986f77403051cba8f", - "upd": { - "StackObjectsCount": 40 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbe0a", - "_tpl": "58dd3ad986f77403051cba8f", - "upd": { - "StackObjectsCount": 40 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbe0b", - "_tpl": "58dd3ad986f77403051cba8f", - "upd": { - "StackObjectsCount": 40 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbe0c", - "_tpl": "58dd3ad986f77403051cba8f", - "upd": { - "StackObjectsCount": 40 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbe0d", - "_tpl": "58dd3ad986f77403051cba8f", - "upd": { - "StackObjectsCount": 40 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbe0e", - "_tpl": "58dd3ad986f77403051cba8f", - "upd": { - "StackObjectsCount": 40 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbe10", - "_tpl": "5c0a840b86f7742ffa4f2482", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbe12", - "_tpl": "5b6d9ce188a4501afc1b2b25", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbe14", - "_tpl": "5aafbcd986f7745e590fff23", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbe16", - "_tpl": "5c093db286f7740a1b2617e3", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbe18", - "_tpl": "5c127c4486f7745625356c13", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbe1a", - "_tpl": "5c093e3486f77430cb02e593", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - }, { - "_id": "668014ea2b680c65290bbe1c", - "_tpl": "619cbf7d23893217ec30b689", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "668014ea2b680c65290bbd08", - "slotId": "main" - } - ], - "sender": "System", + "TOURNAMENTGIFT": { + "items": [ + { + "_id": "668014ea2b680c65290bbd0a", + "_tpl": "5449016a4bdc2d6f028b456f", + "upd": { + "StackObjectsCount": 500000 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd0b", + "_tpl": "5449016a4bdc2d6f028b456f", + "upd": { + "StackObjectsCount": 500000 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd0c", + "_tpl": "5449016a4bdc2d6f028b456f", + "upd": { + "StackObjectsCount": 500000 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd0d", + "_tpl": "5449016a4bdc2d6f028b456f", + "upd": { + "StackObjectsCount": 500000 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd0e", + "_tpl": "5449016a4bdc2d6f028b456f", + "upd": { + "StackObjectsCount": 500000 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd0f", + "_tpl": "5449016a4bdc2d6f028b456f", + "upd": { + "StackObjectsCount": 500000 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd10", + "_tpl": "5449016a4bdc2d6f028b456f", + "upd": { + "StackObjectsCount": 500000 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd11", + "_tpl": "5449016a4bdc2d6f028b456f", + "upd": { + "StackObjectsCount": 500000 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd12", + "_tpl": "5449016a4bdc2d6f028b456f", + "upd": { + "StackObjectsCount": 500000 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd13", + "_tpl": "5449016a4bdc2d6f028b456f", + "upd": { + "StackObjectsCount": 500000 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd14", + "_tpl": "5449016a4bdc2d6f028b456f", + "upd": { + "StackObjectsCount": 500000 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd15", + "_tpl": "5449016a4bdc2d6f028b456f", + "upd": { + "StackObjectsCount": 500000 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd16", + "_tpl": "5449016a4bdc2d6f028b456f", + "upd": { + "StackObjectsCount": 500000 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd17", + "_tpl": "5449016a4bdc2d6f028b456f", + "upd": { + "StackObjectsCount": 500000 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd18", + "_tpl": "5449016a4bdc2d6f028b456f", + "upd": { + "StackObjectsCount": 500000 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd19", + "_tpl": "5449016a4bdc2d6f028b456f", + "upd": { + "StackObjectsCount": 500000 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd1a", + "_tpl": "5449016a4bdc2d6f028b456f", + "upd": { + "StackObjectsCount": 500000 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd1b", + "_tpl": "5449016a4bdc2d6f028b456f", + "upd": { + "StackObjectsCount": 500000 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd1c", + "_tpl": "5449016a4bdc2d6f028b456f", + "upd": { + "StackObjectsCount": 500000 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd1d", + "_tpl": "5449016a4bdc2d6f028b456f", + "upd": { + "StackObjectsCount": 500000 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd1e", + "_tpl": "5449016a4bdc2d6f028b456f", + "upd": { + "StackObjectsCount": 500000 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd1f", + "_tpl": "5449016a4bdc2d6f028b456f", + "upd": { + "StackObjectsCount": 500000 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd20", + "_tpl": "5449016a4bdc2d6f028b456f", + "upd": { + "StackObjectsCount": 500000 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd21", + "_tpl": "5449016a4bdc2d6f028b456f", + "upd": { + "StackObjectsCount": 500000 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd22", + "_tpl": "5449016a4bdc2d6f028b456f", + "upd": { + "StackObjectsCount": 500000 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd23", + "_tpl": "5449016a4bdc2d6f028b456f", + "upd": { + "StackObjectsCount": 500000 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd24", + "_tpl": "5449016a4bdc2d6f028b456f", + "upd": { + "StackObjectsCount": 500000 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd25", + "_tpl": "5449016a4bdc2d6f028b456f", + "upd": { + "StackObjectsCount": 500000 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd26", + "_tpl": "5449016a4bdc2d6f028b456f", + "upd": { + "StackObjectsCount": 500000 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd27", + "_tpl": "5449016a4bdc2d6f028b456f", + "upd": { + "StackObjectsCount": 500000 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd29", + "_tpl": "5696686a4bdc2da3298b456a", + "upd": { + "StackObjectsCount": 10000 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd2b", + "_tpl": "569668774bdc2da2298b4568", + "upd": { + "StackObjectsCount": 10000 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd2d", + "_tpl": "5c0e531d86f7747fa23f4d42", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd2e", + "_tpl": "5c0e531d86f7747fa23f4d42", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd2f", + "_tpl": "5c0e531d86f7747fa23f4d42", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd30", + "_tpl": "5c0e531d86f7747fa23f4d42", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd31", + "_tpl": "5c0e531d86f7747fa23f4d42", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd32", + "_tpl": "5c0e531d86f7747fa23f4d42", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd33", + "_tpl": "5c0e531d86f7747fa23f4d42", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd34", + "_tpl": "5c0e531d86f7747fa23f4d42", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd35", + "_tpl": "5c0e531d86f7747fa23f4d42", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd36", + "_tpl": "5c0e531d86f7747fa23f4d42", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd37", + "_tpl": "5c0e531d86f7747fa23f4d42", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd38", + "_tpl": "5c0e531d86f7747fa23f4d42", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd39", + "_tpl": "5c0e531d86f7747fa23f4d42", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd3a", + "_tpl": "5c0e531d86f7747fa23f4d42", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd3b", + "_tpl": "5c0e531d86f7747fa23f4d42", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd3c", + "_tpl": "5c0e531d86f7747fa23f4d42", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd3d", + "_tpl": "5c0e531d86f7747fa23f4d42", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd3e", + "_tpl": "5c0e531d86f7747fa23f4d42", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd3f", + "_tpl": "5c0e531d86f7747fa23f4d42", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd40", + "_tpl": "5c0e531d86f7747fa23f4d42", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd42", + "_tpl": "5c0126f40db834002a125382", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd44", + "_tpl": "5c12688486f77426843c7d32", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd46", + "_tpl": "590c5d4b86f774784e1b9c45", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd47", + "_tpl": "590c5d4b86f774784e1b9c45", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd48", + "_tpl": "590c5d4b86f774784e1b9c45", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd49", + "_tpl": "590c5d4b86f774784e1b9c45", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd4a", + "_tpl": "590c5d4b86f774784e1b9c45", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd4b", + "_tpl": "590c5d4b86f774784e1b9c45", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd4c", + "_tpl": "590c5d4b86f774784e1b9c45", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd4d", + "_tpl": "590c5d4b86f774784e1b9c45", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd4e", + "_tpl": "590c5d4b86f774784e1b9c45", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd4f", + "_tpl": "590c5d4b86f774784e1b9c45", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd51", + "_tpl": "5c0fa877d174af02a012e1cf", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd52", + "_tpl": "5c0fa877d174af02a012e1cf", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd53", + "_tpl": "5c0fa877d174af02a012e1cf", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd54", + "_tpl": "5c0fa877d174af02a012e1cf", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd55", + "_tpl": "5c0fa877d174af02a012e1cf", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd57", + "_tpl": "5e8488fa988a8701445df1e4", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd58", + "_tpl": "5e8488fa988a8701445df1e4", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd59", + "_tpl": "5e8488fa988a8701445df1e4", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd5a", + "_tpl": "5e8488fa988a8701445df1e4", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd5b", + "_tpl": "5e8488fa988a8701445df1e4", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd5c", + "_tpl": "5e8488fa988a8701445df1e4", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd5d", + "_tpl": "5e8488fa988a8701445df1e4", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd5e", + "_tpl": "5e8488fa988a8701445df1e4", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd5f", + "_tpl": "5e8488fa988a8701445df1e4", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd60", + "_tpl": "5e8488fa988a8701445df1e4", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd62", + "_tpl": "5af0548586f7743a532b7e99", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd63", + "_tpl": "5af0548586f7743a532b7e99", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd64", + "_tpl": "5af0548586f7743a532b7e99", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd65", + "_tpl": "5af0548586f7743a532b7e99", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd66", + "_tpl": "5af0548586f7743a532b7e99", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd67", + "_tpl": "5af0548586f7743a532b7e99", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd69", + "_tpl": "5c0e534186f7747fa1419867", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd6a", + "_tpl": "5c0e534186f7747fa1419867", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd6b", + "_tpl": "5c0e534186f7747fa1419867", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd6c", + "_tpl": "5c0e534186f7747fa1419867", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd6d", + "_tpl": "5c0e534186f7747fa1419867", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd6e", + "_tpl": "5c0e534186f7747fa1419867", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd6f", + "_tpl": "5c0e534186f7747fa1419867", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd70", + "_tpl": "5c0e534186f7747fa1419867", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd71", + "_tpl": "5c0e534186f7747fa1419867", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd72", + "_tpl": "5c0e534186f7747fa1419867", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd73", + "_tpl": "5c0e534186f7747fa1419867", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd74", + "_tpl": "5c0e534186f7747fa1419867", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd75", + "_tpl": "5c0e534186f7747fa1419867", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd76", + "_tpl": "5c0e534186f7747fa1419867", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd77", + "_tpl": "5c0e534186f7747fa1419867", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd78", + "_tpl": "5c0e534186f7747fa1419867", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd79", + "_tpl": "5c0e534186f7747fa1419867", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd7a", + "_tpl": "5c0e534186f7747fa1419867", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd7b", + "_tpl": "5c0e534186f7747fa1419867", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd7c", + "_tpl": "5c0e534186f7747fa1419867", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd7e", + "_tpl": "637b620db7afa97bfc3d7009", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd7f", + "_tpl": "637b620db7afa97bfc3d7009", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd80", + "_tpl": "637b620db7afa97bfc3d7009", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd81", + "_tpl": "637b620db7afa97bfc3d7009", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd82", + "_tpl": "637b620db7afa97bfc3d7009", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd83", + "_tpl": "637b620db7afa97bfc3d7009", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd84", + "_tpl": "637b620db7afa97bfc3d7009", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd85", + "_tpl": "637b620db7afa97bfc3d7009", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd86", + "_tpl": "637b620db7afa97bfc3d7009", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd87", + "_tpl": "637b620db7afa97bfc3d7009", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd88", + "_tpl": "637b620db7afa97bfc3d7009", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd89", + "_tpl": "637b620db7afa97bfc3d7009", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd8a", + "_tpl": "637b620db7afa97bfc3d7009", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd8b", + "_tpl": "637b620db7afa97bfc3d7009", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd8c", + "_tpl": "637b620db7afa97bfc3d7009", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd8d", + "_tpl": "637b620db7afa97bfc3d7009", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd8e", + "_tpl": "637b620db7afa97bfc3d7009", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd8f", + "_tpl": "637b620db7afa97bfc3d7009", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd90", + "_tpl": "637b620db7afa97bfc3d7009", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd91", + "_tpl": "637b620db7afa97bfc3d7009", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd93", + "_tpl": "5d02778e86f774203e7dedbe", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd94", + "_tpl": "5d02778e86f774203e7dedbe", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd95", + "_tpl": "5d02778e86f774203e7dedbe", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd96", + "_tpl": "5d02778e86f774203e7dedbe", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd97", + "_tpl": "5d02778e86f774203e7dedbe", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd99", + "_tpl": "5d02797c86f774203f38e30a", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd9a", + "_tpl": "5d02797c86f774203f38e30a", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd9b", + "_tpl": "5d02797c86f774203f38e30a", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd9c", + "_tpl": "5d02797c86f774203f38e30a", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd9d", + "_tpl": "5d02797c86f774203f38e30a", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbd9f", + "_tpl": "5b3b99265acfc4704b4a1afb", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbda0", + "_tpl": "5b3b99265acfc4704b4a1afb", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbda1", + "_tpl": "5b3b99265acfc4704b4a1afb", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbda2", + "_tpl": "5b3b99265acfc4704b4a1afb", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbda3", + "_tpl": "5b3b99265acfc4704b4a1afb", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbda4", + "_tpl": "5b3b99265acfc4704b4a1afb", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbda5", + "_tpl": "5b3b99265acfc4704b4a1afb", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbda6", + "_tpl": "5b3b99265acfc4704b4a1afb", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbda7", + "_tpl": "5b3b99265acfc4704b4a1afb", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbda8", + "_tpl": "5b3b99265acfc4704b4a1afb", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbda9", + "_tpl": "5b3b99265acfc4704b4a1afb", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbdaa", + "_tpl": "5b3b99265acfc4704b4a1afb", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbdac", + "_tpl": "618ba27d9008e4636a67f61d", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbdad", + "_tpl": "618ba27d9008e4636a67f61d", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbdae", + "_tpl": "618ba27d9008e4636a67f61d", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbdaf", + "_tpl": "618ba27d9008e4636a67f61d", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbdb0", + "_tpl": "618ba27d9008e4636a67f61d", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbdb1", + "_tpl": "618ba27d9008e4636a67f61d", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbdb2", + "_tpl": "618ba27d9008e4636a67f61d", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbdb3", + "_tpl": "618ba27d9008e4636a67f61d", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbdb4", + "_tpl": "618ba27d9008e4636a67f61d", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbdb5", + "_tpl": "618ba27d9008e4636a67f61d", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbdb6", + "_tpl": "618ba27d9008e4636a67f61d", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbdb7", + "_tpl": "618ba27d9008e4636a67f61d", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbdb9", + "_tpl": "617151c1d92c473c770214ab", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbdba", + "_tpl": "617151c1d92c473c770214ab", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbdbb", + "_tpl": "617151c1d92c473c770214ab", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbdbc", + "_tpl": "617151c1d92c473c770214ab", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbdbd", + "_tpl": "617151c1d92c473c770214ab", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbdbe", + "_tpl": "617151c1d92c473c770214ab", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbdbf", + "_tpl": "617151c1d92c473c770214ab", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbdc0", + "_tpl": "617151c1d92c473c770214ab", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbdc1", + "_tpl": "617151c1d92c473c770214ab", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbdc2", + "_tpl": "617151c1d92c473c770214ab", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbdc3", + "_tpl": "617151c1d92c473c770214ab", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbdc4", + "_tpl": "617151c1d92c473c770214ab", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbdc9", + "_tpl": "5bfea6e90db834001b7347f3", + "upd": { + "FireMode": { + "FireMode": "single" + }, + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbdca", + "_tpl": "5bfea7ad0db834001c38f1ee", + "parentId": "668014ea2b680c65290bbdc9", + "slotId": "mod_magazine" + }, + { + "_id": "668014ea2b680c65290bbdcb", + "_tpl": "5bfeb32b0db834001a6694d9", + "parentId": "668014ea2b680c65290bbdc9", + "slotId": "mod_stock" + }, + { + "_id": "668014ea2b680c65290bbdcc", + "_tpl": "5bfebc320db8340019668d79", + "parentId": "668014ea2b680c65290bbdc9", + "slotId": "mod_barrel" + }, + { + "_id": "668014ea2b680c65290bbdcd", + "_tpl": "5bfea6e90db834001b7347f3", + "upd": { + "FireMode": { + "FireMode": "single" + }, + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbdce", + "_tpl": "5bfea7ad0db834001c38f1ee", + "parentId": "668014ea2b680c65290bbdcd", + "slotId": "mod_magazine" + }, + { + "_id": "668014ea2b680c65290bbdcf", + "_tpl": "5bfeb32b0db834001a6694d9", + "parentId": "668014ea2b680c65290bbdcd", + "slotId": "mod_stock" + }, + { + "_id": "668014ea2b680c65290bbdd0", + "_tpl": "5bfebc320db8340019668d79", + "parentId": "668014ea2b680c65290bbdcd", + "slotId": "mod_barrel" + }, + { + "_id": "668014ea2b680c65290bbdd1", + "_tpl": "5bfea6e90db834001b7347f3", + "upd": { + "FireMode": { + "FireMode": "single" + }, + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbdd2", + "_tpl": "5bfea7ad0db834001c38f1ee", + "parentId": "668014ea2b680c65290bbdd1", + "slotId": "mod_magazine" + }, + { + "_id": "668014ea2b680c65290bbdd3", + "_tpl": "5bfeb32b0db834001a6694d9", + "parentId": "668014ea2b680c65290bbdd1", + "slotId": "mod_stock" + }, + { + "_id": "668014ea2b680c65290bbdd4", + "_tpl": "5bfebc320db8340019668d79", + "parentId": "668014ea2b680c65290bbdd1", + "slotId": "mod_barrel" + }, + { + "_id": "668014ea2b680c65290bbdd5", + "_tpl": "5bfea6e90db834001b7347f3", + "upd": { + "FireMode": { + "FireMode": "single" + }, + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbdd6", + "_tpl": "5bfea7ad0db834001c38f1ee", + "parentId": "668014ea2b680c65290bbdd5", + "slotId": "mod_magazine" + }, + { + "_id": "668014ea2b680c65290bbdd7", + "_tpl": "5bfeb32b0db834001a6694d9", + "parentId": "668014ea2b680c65290bbdd5", + "slotId": "mod_stock" + }, + { + "_id": "668014ea2b680c65290bbdd8", + "_tpl": "5bfebc320db8340019668d79", + "parentId": "668014ea2b680c65290bbdd5", + "slotId": "mod_barrel" + }, + { + "_id": "668014ea2b680c65290bbdd9", + "_tpl": "5bfea6e90db834001b7347f3", + "upd": { + "FireMode": { + "FireMode": "single" + }, + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbdda", + "_tpl": "5bfea7ad0db834001c38f1ee", + "parentId": "668014ea2b680c65290bbdd9", + "slotId": "mod_magazine" + }, + { + "_id": "668014ea2b680c65290bbddb", + "_tpl": "5bfeb32b0db834001a6694d9", + "parentId": "668014ea2b680c65290bbdd9", + "slotId": "mod_stock" + }, + { + "_id": "668014ea2b680c65290bbddc", + "_tpl": "5bfebc320db8340019668d79", + "parentId": "668014ea2b680c65290bbdd9", + "slotId": "mod_barrel" + }, + { + "_id": "668014ea2b680c65290bbddd", + "_tpl": "5bfea6e90db834001b7347f3", + "upd": { + "FireMode": { + "FireMode": "single" + }, + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbdde", + "_tpl": "5bfea7ad0db834001c38f1ee", + "parentId": "668014ea2b680c65290bbddd", + "slotId": "mod_magazine" + }, + { + "_id": "668014ea2b680c65290bbddf", + "_tpl": "5bfeb32b0db834001a6694d9", + "parentId": "668014ea2b680c65290bbddd", + "slotId": "mod_stock" + }, + { + "_id": "668014ea2b680c65290bbde0", + "_tpl": "5bfebc320db8340019668d79", + "parentId": "668014ea2b680c65290bbddd", + "slotId": "mod_barrel" + }, + { + "_id": "668014ea2b680c65290bbde1", + "_tpl": "5bfea6e90db834001b7347f3", + "upd": { + "FireMode": { + "FireMode": "single" + }, + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbde2", + "_tpl": "5bfea7ad0db834001c38f1ee", + "parentId": "668014ea2b680c65290bbde1", + "slotId": "mod_magazine" + }, + { + "_id": "668014ea2b680c65290bbde3", + "_tpl": "5bfeb32b0db834001a6694d9", + "parentId": "668014ea2b680c65290bbde1", + "slotId": "mod_stock" + }, + { + "_id": "668014ea2b680c65290bbde4", + "_tpl": "5bfebc320db8340019668d79", + "parentId": "668014ea2b680c65290bbde1", + "slotId": "mod_barrel" + }, + { + "_id": "668014ea2b680c65290bbde5", + "_tpl": "5bfea6e90db834001b7347f3", + "upd": { + "FireMode": { + "FireMode": "single" + }, + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbde6", + "_tpl": "5bfea7ad0db834001c38f1ee", + "parentId": "668014ea2b680c65290bbde5", + "slotId": "mod_magazine" + }, + { + "_id": "668014ea2b680c65290bbde7", + "_tpl": "5bfeb32b0db834001a6694d9", + "parentId": "668014ea2b680c65290bbde5", + "slotId": "mod_stock" + }, + { + "_id": "668014ea2b680c65290bbde8", + "_tpl": "5bfebc320db8340019668d79", + "parentId": "668014ea2b680c65290bbde5", + "slotId": "mod_barrel" + }, + { + "_id": "668014ea2b680c65290bbde9", + "_tpl": "5bfea6e90db834001b7347f3", + "upd": { + "FireMode": { + "FireMode": "single" + }, + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbdea", + "_tpl": "5bfea7ad0db834001c38f1ee", + "parentId": "668014ea2b680c65290bbde9", + "slotId": "mod_magazine" + }, + { + "_id": "668014ea2b680c65290bbdeb", + "_tpl": "5bfeb32b0db834001a6694d9", + "parentId": "668014ea2b680c65290bbde9", + "slotId": "mod_stock" + }, + { + "_id": "668014ea2b680c65290bbdec", + "_tpl": "5bfebc320db8340019668d79", + "parentId": "668014ea2b680c65290bbde9", + "slotId": "mod_barrel" + }, + { + "_id": "668014ea2b680c65290bbded", + "_tpl": "5bfea6e90db834001b7347f3", + "upd": { + "FireMode": { + "FireMode": "single" + }, + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbdee", + "_tpl": "5bfea7ad0db834001c38f1ee", + "parentId": "668014ea2b680c65290bbded", + "slotId": "mod_magazine" + }, + { + "_id": "668014ea2b680c65290bbdef", + "_tpl": "5bfeb32b0db834001a6694d9", + "parentId": "668014ea2b680c65290bbded", + "slotId": "mod_stock" + }, + { + "_id": "668014ea2b680c65290bbdf0", + "_tpl": "5bfebc320db8340019668d79", + "parentId": "668014ea2b680c65290bbded", + "slotId": "mod_barrel" + }, + { + "_id": "668014ea2b680c65290bbdf1", + "_tpl": "5bfea6e90db834001b7347f3", + "upd": { + "FireMode": { + "FireMode": "single" + }, + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbdf2", + "_tpl": "5bfea7ad0db834001c38f1ee", + "parentId": "668014ea2b680c65290bbdf1", + "slotId": "mod_magazine" + }, + { + "_id": "668014ea2b680c65290bbdf3", + "_tpl": "5bfeb32b0db834001a6694d9", + "parentId": "668014ea2b680c65290bbdf1", + "slotId": "mod_stock" + }, + { + "_id": "668014ea2b680c65290bbdf4", + "_tpl": "5bfebc320db8340019668d79", + "parentId": "668014ea2b680c65290bbdf1", + "slotId": "mod_barrel" + }, + { + "_id": "668014ea2b680c65290bbdf5", + "_tpl": "5bfea6e90db834001b7347f3", + "upd": { + "FireMode": { + "FireMode": "single" + }, + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbdf6", + "_tpl": "5bfea7ad0db834001c38f1ee", + "parentId": "668014ea2b680c65290bbdf5", + "slotId": "mod_magazine" + }, + { + "_id": "668014ea2b680c65290bbdf7", + "_tpl": "5bfeb32b0db834001a6694d9", + "parentId": "668014ea2b680c65290bbdf5", + "slotId": "mod_stock" + }, + { + "_id": "668014ea2b680c65290bbdf8", + "_tpl": "5bfebc320db8340019668d79", + "parentId": "668014ea2b680c65290bbdf5", + "slotId": "mod_barrel" + }, + { + "_id": "668014ea2b680c65290bbdfa", + "_tpl": "5a608bf24f39f98ffc77720e", + "upd": { + "StackObjectsCount": 40 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbdfb", + "_tpl": "5a608bf24f39f98ffc77720e", + "upd": { + "StackObjectsCount": 40 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbdfc", + "_tpl": "5a608bf24f39f98ffc77720e", + "upd": { + "StackObjectsCount": 40 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbdfd", + "_tpl": "5a608bf24f39f98ffc77720e", + "upd": { + "StackObjectsCount": 40 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbdfe", + "_tpl": "5a608bf24f39f98ffc77720e", + "upd": { + "StackObjectsCount": 40 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbdff", + "_tpl": "5a608bf24f39f98ffc77720e", + "upd": { + "StackObjectsCount": 40 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbe00", + "_tpl": "5a608bf24f39f98ffc77720e", + "upd": { + "StackObjectsCount": 40 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbe01", + "_tpl": "5a608bf24f39f98ffc77720e", + "upd": { + "StackObjectsCount": 40 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbe02", + "_tpl": "5a608bf24f39f98ffc77720e", + "upd": { + "StackObjectsCount": 40 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbe03", + "_tpl": "5a608bf24f39f98ffc77720e", + "upd": { + "StackObjectsCount": 40 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbe05", + "_tpl": "58dd3ad986f77403051cba8f", + "upd": { + "StackObjectsCount": 40 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbe06", + "_tpl": "58dd3ad986f77403051cba8f", + "upd": { + "StackObjectsCount": 40 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbe07", + "_tpl": "58dd3ad986f77403051cba8f", + "upd": { + "StackObjectsCount": 40 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbe08", + "_tpl": "58dd3ad986f77403051cba8f", + "upd": { + "StackObjectsCount": 40 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbe09", + "_tpl": "58dd3ad986f77403051cba8f", + "upd": { + "StackObjectsCount": 40 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbe0a", + "_tpl": "58dd3ad986f77403051cba8f", + "upd": { + "StackObjectsCount": 40 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbe0b", + "_tpl": "58dd3ad986f77403051cba8f", + "upd": { + "StackObjectsCount": 40 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbe0c", + "_tpl": "58dd3ad986f77403051cba8f", + "upd": { + "StackObjectsCount": 40 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbe0d", + "_tpl": "58dd3ad986f77403051cba8f", + "upd": { + "StackObjectsCount": 40 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbe0e", + "_tpl": "58dd3ad986f77403051cba8f", + "upd": { + "StackObjectsCount": 40 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbe10", + "_tpl": "5c0a840b86f7742ffa4f2482", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbe12", + "_tpl": "5b6d9ce188a4501afc1b2b25", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbe14", + "_tpl": "5aafbcd986f7745e590fff23", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbe16", + "_tpl": "5c093db286f7740a1b2617e3", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbe18", + "_tpl": "5c127c4486f7745625356c13", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbe1a", + "_tpl": "5c093e3486f77430cb02e593", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + }, + { + "_id": "668014ea2b680c65290bbe1c", + "_tpl": "619cbf7d23893217ec30b689", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "668014ea2b680c65290bbd08", + "slotId": "main" + } + ], + "sender": "System", "messageText": "Tourney gift", "collectionTimeHours": 128, "associatedEvent": "Promo", - "profileChangeEvents": [{ - "_id": "668014ea2b680c65290bbe1d", - "Type": "TraderSalesSum", - "value": 2500000, - "entity": "5ac3b934156ae10c4430e83c" - }, { - "_id": "668014ea2b680c65290bbe1e", - "Type": "TraderStanding", - "value": 0.6, - "entity": "5ac3b934156ae10c4430e83c" - }, { - "_id": "668014ea2b680c65290bbe1f", - "Type": "TraderSalesSum", - "value": 2600000, - "entity": "58330581ace78e27b8b10cee" - }, { - "_id": "668014ea2b680c65290bbe20", - "Type": "TraderStanding", - "value": 0.75, - "entity": "58330581ace78e27b8b10cee" - }, { - "_id": "668014ea2b680c65290bbe21", - "Type": "TraderSalesSum", - "value": 1725000, - "entity": "5c0647fdd443bc2504c2d371" - }, { - "_id": "668014ea2b680c65290bbe22", - "Type": "TraderStanding", - "value": 0.5, - "entity": "5c0647fdd443bc2504c2d371" - }, { - "_id": "668014ea2b680c65290bbe23", - "Type": "TraderSalesSum", - "value": 2500000, - "entity": "5a7c2eca46aef81a7ca2145d" - }, { - "_id": "668014ea2b680c65290bbe24", - "Type": "TraderStanding", - "value": 0.6, - "entity": "5a7c2eca46aef81a7ca2145d" - }, { - "_id": "668014ea2b680c65290bbe25", - "Type": "TraderSalesSum", - "value": 32000, - "entity": "5935c25fb3acc3127c3d8cd9" - }, { - "_id": "668014ea2b680c65290bbe26", - "Type": "TraderStanding", - "value": 0.6, - "entity": "5935c25fb3acc3127c3d8cd9" - }, { - "_id": "668014ea2b680c65290bbe27", - "Type": "TraderSalesSum", - "value": 2300000, - "entity": "54cb50c76803fa8b248b4571" - }, { - "_id": "668014ea2b680c65290bbe28", - "Type": "TraderStanding", - "value": 0.5, - "entity": "54cb50c76803fa8b248b4571" - }, { - "_id": "668014ea2b680c65290bbe29", - "Type": "TraderSalesSum", - "value": 900000, - "entity": "54cb57776803fa99248b456e" - }, { - "_id": "668014ea2b680c65290bbe2a", - "Type": "TraderStanding", - "value": 0.6, - "entity": "54cb57776803fa99248b456e" - }, { - "_id": "668014ea2b680c65290bbe2b", - "Type": "ProfileLevel", - "value": 2901143, - "entity": null - }, { - "_id": "668014ea2b680c65290bbe2c", - "Type": "SkillPoints", - "value": 2500, - "entity": "Endurance" - }, { - "_id": "668014ea2b680c65290bbe2d", - "Type": "SkillPoints", - "value": 2500, - "entity": "Strength" - }, { - "_id": "668014ea2b680c65290bbe2e", - "Type": "SkillPoints", - "value": 2500, - "entity": "Vitality" - }, { - "_id": "668014ea2b680c65290bbe2f", - "Type": "SkillPoints", - "value": 2500, - "entity": "Health" - }, { - "_id": "668014ea2b680c65290bbe30", - "Type": "SkillPoints", - "value": 2500, - "entity": "Metabolism" - }, { - "_id": "668014ea2b680c65290bbe31", - "Type": "SkillPoints", - "value": 2500, - "entity": "StressResistance" - }, { - "_id": "668014ea2b680c65290bbe32", - "Type": "SkillPoints", - "value": 2500, - "entity": "Immunity" - }, { - "_id": "668014ea2b680c65290bbe33", - "Type": "SkillPoints", - "value": 2500, - "entity": "Throwing" - }, { - "_id": "668014ea2b680c65290bbe34", - "Type": "SkillPoints", - "value": 2500, - "entity": "RecoilControl" - }, { - "_id": "668014ea2b680c65290bbe35", - "Type": "SkillPoints", - "value": 2500, - "entity": "Pistol" - }, { - "_id": "668014ea2b680c65290bbe36", - "Type": "SkillPoints", - "value": 2500, - "entity": "Revolver" - }, { - "_id": "668014ea2b680c65290bbe37", - "Type": "SkillPoints", - "value": 2500, - "entity": "SMG" - }, { - "_id": "668014ea2b680c65290bbe38", - "Type": "SkillPoints", - "value": 2500, - "entity": "Assault" - }, { - "_id": "668014ea2b680c65290bbe39", - "Type": "SkillPoints", - "value": 2500, - "entity": "Shotgun" - }, { - "_id": "668014ea2b680c65290bbe3a", - "Type": "SkillPoints", - "value": 2500, - "entity": "Sniper" - }, { - "_id": "668014ea2b680c65290bbe3b", - "Type": "SkillPoints", - "value": 2500, - "entity": "LMG" - }, { - "_id": "668014ea2b680c65290bbe3c", - "Type": "SkillPoints", - "value": 2500, - "entity": "HMG" - }, { - "_id": "668014ea2b680c65290bbe3d", - "Type": "SkillPoints", - "value": 2500, - "entity": "Launcher" - }, { - "_id": "668014ea2b680c65290bbe3e", - "Type": "SkillPoints", - "value": 2500, - "entity": "AttachedLauncher" - }, { - "_id": "668014ea2b680c65290bbe3f", - "Type": "SkillPoints", - "value": 2500, - "entity": "Melee" - }, { - "_id": "668014ea2b680c65290bbe40", - "Type": "SkillPoints", - "value": 2500, - "entity": "DMR" - }, { - "_id": "668014ea2b680c65290bbe41", - "Type": "SkillPoints", - "value": 2500, - "entity": "CovertMovement" - }, { - "_id": "668014ea2b680c65290bbe42", - "Type": "SkillPoints", - "value": 2500, - "entity": "Search" - }, { - "_id": "668014ea2b680c65290bbe43", - "Type": "SkillPoints", - "value": 2500, - "entity": "MagDrills" - }, { - "_id": "668014ea2b680c65290bbe44", - "Type": "SkillPoints", - "value": 2500, - "entity": "Perception" - }, { - "_id": "668014ea2b680c65290bbe45", - "Type": "SkillPoints", - "value": 2500, - "entity": "Intellect" - }, { - "_id": "668014ea2b680c65290bbe46", - "Type": "SkillPoints", - "value": 2500, - "entity": "Charisma" - }, { - "_id": "668014ea2b680c65290bbe47", - "Type": "SkillPoints", - "value": 2500, - "entity": "Memory" - }, { - "_id": "668014ea2b680c65290bbe48", - "Type": "SkillPoints", - "value": 2500, - "entity": "Surgery" - }, { - "_id": "668014ea2b680c65290bbe49", - "Type": "SkillPoints", - "value": 2500, - "entity": "AimDrills" - }, { - "_id": "668014ea2b680c65290bbe4a", - "Type": "SkillPoints", - "value": 2500, - "entity": "HideoutManagement" - }, { - "_id": "668014ea2b680c65290bbe4b", - "Type": "SkillPoints", - "value": 2500, - "entity": "Crafting" - }, { - "_id": "668014ea2b680c65290bbe4c", - "Type": "SkillPoints", - "value": 2500, - "entity": "Attention" - }, { - "_id": "668014ea2b680c65290bbe4d", - "Type": "SkillPoints", - "value": 2500, - "entity": "63" - }, { - "_id": "668014ea2b680c65290bbe4e", - "Type": "SkillPoints", - "value": 2500, - "entity": "39" - }, { - "_id": "668014ea2b680c65290bbe4f", - "Type": "SkillPoints", - "value": 2500, - "entity": "38" - }, { - "_id": "668014ea2b680c65290bbe50", - "Type": "SkillPoints", - "value": 2500, - "entity": "45" - }, { - "_id": "668014ea2b680c65290bbe51", - "Type": "ExamineAllItems" - }, { - "_id": "668014ea2b680c65290bbe52", - "Type": "UnlockTrader", - "value": 1, - "entity": "5c0647fdd443bc2504c2d371" - }, { - "_id": "668014ea2b680c65290bbe53", - "Type": "HideoutAreaLevel", - "value": 1, - "entity": "Workbench" - }, { - "_id": "668014ea2b680c65290bbe54", - "Type": "AssortmentUnlockRule", - "entity": "584149ad2459775a7726350e", - "data": "584149ad2459775a7726350e" - }, { - "_id": "668014ea2b680c65290bbe55", - "Type": "AssortmentUnlockRule", - "entity": "544fb45d4bdc2dee738b4568", - "data": "544fb45d4bdc2dee738b4568" - }, { - "_id": "668014ea2b680c65290bbe56", - "Type": "AssortmentUnlockRule", - "entity": "590c661e86f7741e566b646a", - "data": "590c661e86f7741e566b646a" - }, { - "_id": "668014ea2b680c65290bbe57", - "Type": "AssortmentUnlockRule", - "entity": "5a13df5286f774032f5454a0", - "data": "5a13df5286f774032f5454a0" - }, { - "_id": "668014ea2b680c65290bbe58", - "Type": "AssortmentUnlockRule", - "entity": "544fb3f34bdc2d03748b456a", - "data": "544fb3f34bdc2d03748b456a" - }, { - "_id": "668014ea2b680c65290bbe59", - "Type": "AssortmentUnlockRule", - "entity": "58d2912286f7744e27117493", - "data": "58d2912286f7744e27117493" - }, { - "_id": "668014ea2b680c65290bbe5a", - "Type": "AssortmentUnlockRule", - "entity": "57372140245977611f70ee91", - "data": "57372140245977611f70ee91" - }, { - "_id": "668014ea2b680c65290bbe5b", - "Type": "AssortmentUnlockRule", - "entity": "5ac8d6885acfc400180ae7b0", - "data": "5ac8d6885acfc400180ae7b0" - }, { - "_id": "668014ea2b680c65290bbe5c", - "Type": "AssortmentUnlockRule", - "entity": "5aa7e276e5b5b000171d0647", - "data": "5aa7e276e5b5b000171d0647" - }, { - "_id": "668014ea2b680c65290bbe5d", - "Type": "AssortmentUnlockRule", - "entity": "59eb7ebe86f7740b373438ce", - "data": "59eb7ebe86f7740b373438ce" - }, { - "_id": "668014ea2b680c65290bbe5e", - "Type": "AssortmentUnlockRule", - "entity": "5656d7c34bdc2d9d198b4587", - "data": "5656d7c34bdc2d9d198b4587" - }, { - "_id": "668014ea2b680c65290bbe5f", - "Type": "AssortmentUnlockRule", - "entity": "55d482194bdc2d1d4e8b456b", - "data": "55d482194bdc2d1d4e8b456b" - }, { - "_id": "668014ea2b680c65290bbe60", - "Type": "AssortmentUnlockRule", - "entity": "58dffc5d86f77407c744a847", - "data": "58dffc5d86f77407c744a847" - }, { - "_id": "668014ea2b680c65290bbe61", - "Type": "AssortmentUnlockRule", - "entity": "57da93632459771cb65bf83f", - "data": "57da93632459771cb65bf83f" - }, { - "_id": "668014ea2b680c65290bbe62", - "Type": "AssortmentUnlockRule", - "entity": "56dff0bed2720bb0668b4567", - "data": "56dff0bed2720bb0668b4567" - }, { - "_id": "668014ea2b680c65290bbe63", - "Type": "AssortmentUnlockRule", - "entity": "59bfe68886f7746004266202", - "data": "59bfe68886f7746004266202" - }, { - "_id": "668014ea2b680c65290bbe64", - "Type": "AssortmentUnlockRule", - "entity": "59e77a2386f7742ee578960a", - "data": "59e77a2386f7742ee578960a" - }, { - "_id": "668014ea2b680c65290bbe65", - "Type": "AssortmentUnlockRule", - "entity": "5a269f97c4a282000b151807", - "data": "5a269f97c4a282000b151807" - }, { - "_id": "668014ea2b680c65290bbe66", - "Type": "AssortmentUnlockRule", - "entity": "58d3db5386f77426186285a0", - "data": "58d3db5386f77426186285a0" - }, { - "_id": "668014ea2b680c65290bbe67", - "Type": "AssortmentUnlockRule", - "entity": "5a3a85af86f774745637d46c", - "data": "5a3a85af86f774745637d46c" - }, { - "_id": "668014ea2b680c65290bbe68", - "Type": "AssortmentUnlockRule", - "entity": "5a33e75ac4a2826c6e06d759", - "data": "5a33e75ac4a2826c6e06d759" - }, { - "_id": "668014ea2b680c65290bbe69", - "Type": "AssortmentUnlockRule", - "entity": "545cdb794bdc2d3a198b456a", - "data": "545cdb794bdc2d3a198b456a" - }, { - "_id": "668014ea2b680c65290bbe6a", - "Type": "AssortmentUnlockRule", - "entity": "545cdae64bdc2d39198b4568", - "data": "545cdae64bdc2d39198b4568" - }, { - "_id": "668014ea2b680c65290bbe6b", - "Type": "AssortmentUnlockRule", - "entity": "5649ae4a4bdc2d1b2b8b4588", - "data": "5649ae4a4bdc2d1b2b8b4588" - }, { - "_id": "668014ea2b680c65290bbe6c", - "Type": "AssortmentUnlockRule", - "entity": "58dffd4586f77408a27629b2", - "data": "58dffd4586f77408a27629b2" - }, { - "_id": "668014ea2b680c65290bbe6d", - "Type": "AssortmentUnlockRule", - "entity": "5751a25924597722c463c472", - "data": "5751a25924597722c463c472" - }, { - "_id": "668014ea2b680c65290bbe6e", - "Type": "AssortmentUnlockRule", - "entity": "59c1383d86f774290a37e0ca", - "data": "59c1383d86f774290a37e0ca" - }, { - "_id": "668014ea2b680c65290bbe6f", - "Type": "AssortmentUnlockRule", - "entity": "5a0c59791526d8dba737bba7", - "data": "5a0c59791526d8dba737bba7" - }, { - "_id": "668014ea2b680c65290bbe70", - "Type": "AssortmentUnlockRule", - "entity": "576fd4ec2459777f0b518431", - "data": "576fd4ec2459777f0b518431" - }, { - "_id": "668014ea2b680c65290bbe71", - "Type": "AssortmentUnlockRule", - "entity": "57a0e5022459774d1673f889", - "data": "57a0e5022459774d1673f889" - }, { - "_id": "668014ea2b680c65290bbe72", - "Type": "AssortmentUnlockRule", - "entity": "584984812459776a704a82a6", - "data": "584984812459776a704a82a6" - }, { - "_id": "668014ea2b680c65290bbe73", - "Type": "AssortmentUnlockRule", - "entity": "59c0ec5b86f77435b128bfca", - "data": "59c0ec5b86f77435b128bfca" - }, { - "_id": "668014ea2b680c65290bbe74", - "Type": "AssortmentUnlockRule", - "entity": "57ffb0e42459777d047111c5", - "data": "57ffb0e42459777d047111c5" - }, { - "_id": "668014ea2b680c65290bbe75", - "Type": "AssortmentUnlockRule", - "entity": "58dd3ad986f77403051cba8f", - "data": "58dd3ad986f77403051cba8f" - }, { - "_id": "668014ea2b680c65290bbe76", - "Type": "AssortmentUnlockRule", - "entity": "5a16b7e1fcdbcb00165aa6c9", - "data": "5a16b7e1fcdbcb00165aa6c9" - }, { - "_id": "668014ea2b680c65290bbe77", - "Type": "AssortmentUnlockRule", - "entity": "56eabf3bd2720b75698b4569", - "data": "56eabf3bd2720b75698b4569" - }, { - "_id": "668014ea2b680c65290bbe78", - "Type": "AssortmentUnlockRule", - "entity": "588226ef24597767af46e39c", - "data": "588226ef24597767af46e39c" - }, { - "_id": "668014ea2b680c65290bbe79", - "Type": "AssortmentUnlockRule", - "entity": "59411abb86f77478f702b5d2", - "data": "59411abb86f77478f702b5d2" - }, { - "_id": "668014ea2b680c65290bbe7a", - "Type": "AssortmentUnlockRule", - "entity": "58414a16245977599247970a", - "data": "58414a16245977599247970a" - }, { - "_id": "668014ea2b680c65290bbe7b", - "Type": "AssortmentUnlockRule", - "entity": "590c678286f77426c9660122", - "data": "590c678286f77426c9660122" - }, { - "_id": "668014ea2b680c65290bbe7c", - "Type": "AssortmentUnlockRule", - "entity": "584147982459775a6c55e931", - "data": "584147982459775a6c55e931" - }, { - "_id": "668014ea2b680c65290bbe7d", - "Type": "AssortmentUnlockRule", - "entity": "5a8ae65f86f774377a23ed55", - "data": "5a8ae65f86f774377a23ed55" - }, { - "_id": "668014ea2b680c65290bbe7e", - "Type": "AssortmentUnlockRule", - "entity": "5af08cc686f77424a61595f2", - "data": "5af08cc686f77424a61595f2" - }, { - "_id": "668014ea2b680c65290bbe7f", - "Type": "AssortmentUnlockRule", - "entity": "5b07dd285acfc4001754240d", - "data": "5b07dd285acfc4001754240d" - }, { - "_id": "668014ea2b680c65290bbe80", - "Type": "AssortmentUnlockRule", - "entity": "5b4391a586f7745321235ab2", - "data": "5b4391a586f7745321235ab2" - }, { - "_id": "668014ea2b680c65290bbe81", - "Type": "AssortmentUnlockRule", - "entity": "5c1127d0d174af29be75cf68", - "data": "5c1127d0d174af29be75cf68" - }, { - "_id": "668014ea2b680c65290bbe82", - "Type": "AssortmentUnlockRule", - "entity": "5c0e722886f7740458316a57", - "data": "5c0e722886f7740458316a57" - }, { - "_id": "668014ea2b680c65290bbe83", - "Type": "AssortmentUnlockRule", - "entity": "5bbde409d4351e003562b036", - "data": "5bbde409d4351e003562b036" - }, { - "_id": "668014ea2b680c65290bbe84", - "Type": "AssortmentUnlockRule", - "entity": "5b4329f05acfc47a86086aa1", - "data": "5b4329f05acfc47a86086aa1" - }, { - "_id": "668014ea2b680c65290bbe85", - "Type": "AssortmentUnlockRule", - "entity": "5ba2678ad4351e44f824b344", - "data": "5ba2678ad4351e44f824b344" - }, { - "_id": "668014ea2b680c65290bbe86", - "Type": "AssortmentUnlockRule", - "entity": "56ea8d2fd2720b7c698b4570", - "data": "56ea8d2fd2720b7c698b4570" - }, { - "_id": "668014ea2b680c65290bbe87", - "Type": "AssortmentUnlockRule", - "entity": "5bc5a372d4351e44f824d17f", - "data": "5bc5a372d4351e44f824d17f" - }, { - "_id": "668014ea2b680c65290bbe88", - "Type": "AssortmentUnlockRule", - "entity": "5bbde41ed4351e003562b038", - "data": "5bbde41ed4351e003562b038" - }, { - "_id": "668014ea2b680c65290bbe89", - "Type": "AssortmentUnlockRule", - "entity": "5bc5a35cd4351e450201232f", - "data": "5bc5a35cd4351e450201232f" - }, { - "_id": "668014ea2b680c65290bbe8a", - "Type": "AssortmentUnlockRule", - "entity": "5cc80f8fe4a949033b0224a2", - "data": "5cc80f8fe4a949033b0224a2" - }, { - "_id": "668014ea2b680c65290bbe8b", - "Type": "AssortmentUnlockRule", - "entity": "5a966f51a2750c00156aacf6", - "data": "5a966f51a2750c00156aacf6" - }, { - "_id": "668014ea2b680c65290bbe8c", - "Type": "AssortmentUnlockRule", - "entity": "5ac78a9b86f7741cca0bbd8d", - "data": "5ac78a9b86f7741cca0bbd8d" - }, { - "_id": "668014ea2b680c65290bbe8d", - "Type": "AssortmentUnlockRule", - "entity": "5b44cf1486f77431723e3d05", - "data": "5b44cf1486f77431723e3d05" - }, { - "_id": "668014ea2b680c65290bbe8e", - "Type": "AssortmentUnlockRule", - "entity": "5aafbde786f774389d0cbc0f", - "data": "5aafbde786f774389d0cbc0f" - }, { - "_id": "668014ea2b680c65290bbe8f", - "Type": "AssortmentUnlockRule", - "entity": "59fb137a86f7740adb646af1", - "data": "59fb137a86f7740adb646af1" - }, { - "_id": "668014ea2b680c65290bbe90", - "Type": "AssortmentUnlockRule", - "entity": "5bae13ded4351e44f824bf38", - "data": "5bae13ded4351e44f824bf38" - }, { - "_id": "668014ea2b680c65290bbe91", - "Type": "AssortmentUnlockRule", - "entity": "5bbdb870d4351e00367fb67d", - "data": "5bbdb870d4351e00367fb67d" - }, { - "_id": "668014ea2b680c65290bbe92", - "Type": "AssortmentUnlockRule", - "entity": "5b3116595acfc40019476364", - "data": "5b3116595acfc40019476364" - }, { - "_id": "668014ea2b680c65290bbe93", - "Type": "AssortmentUnlockRule", - "entity": "5b83f22086f77464e15a1d5f", - "data": "5b83f22086f77464e15a1d5f" - }, { - "_id": "668014ea2b680c65290bbe94", - "Type": "AssortmentUnlockRule", - "entity": "5bbdb83fd4351e44f824c44b", - "data": "5bbdb83fd4351e44f824c44b" - }, { - "_id": "668014ea2b680c65290bbe95", - "Type": "AssortmentUnlockRule", - "entity": "5c0a2cec0db834001b7ce47d", - "data": "5c0a2cec0db834001b7ce47d" - }, { - "_id": "668014ea2b680c65290bbe96", - "Type": "AssortmentUnlockRule", - "entity": "5ac4ad3686f774181345c3da", - "data": "5ac4ad3686f774181345c3da" - }, { - "_id": "668014ea2b680c65290bbe97", - "Type": "AssortmentUnlockRule", - "entity": "58d2912286f7744e27117493", - "data": "58d2912286f7744e27117493" - }, { - "_id": "668014ea2b680c65290bbe98", - "Type": "AssortmentUnlockRule", - "entity": "56eabcd4d2720b66698b4574", - "data": "56eabcd4d2720b66698b4574" - }, { - "_id": "668014ea2b680c65290bbe99", - "Type": "AssortmentUnlockRule", - "entity": "5bbdb811d4351e45020113c7", - "data": "5bbdb811d4351e45020113c7" - }, { - "_id": "668014ea2b680c65290bbe9a", - "Type": "AssortmentUnlockRule", - "entity": "5bc5a351d4351e003477a414", - "data": "5bc5a351d4351e003477a414" - }, { - "_id": "668014ea2b680c65290bbe9b", - "Type": "AssortmentUnlockRule", - "entity": "5c1260dc86f7746b106e8748", - "data": "5c1260dc86f7746b106e8748" - }, { - "_id": "668014ea2b680c65290bbe9c", - "Type": "AssortmentUnlockRule", - "entity": "5b44d0de86f774503d30cba8", - "data": "5b44d0de86f774503d30cba8" - }, { - "_id": "668014ea2b680c65290bbe9d", - "Type": "AssortmentUnlockRule", - "entity": "5a8c436686f7740f394d10b5", - "data": "5a8c436686f7740f394d10b5" - }, { - "_id": "668014ea2b680c65290bbe9e", - "Type": "AssortmentUnlockRule", - "entity": "5b07db875acfc40dc528a5f6", - "data": "5b07db875acfc40dc528a5f6" - }, { - "_id": "668014ea2b680c65290bbe9f", - "Type": "AssortmentUnlockRule", - "entity": "5b057b4f5acfc4771e1bd3e9", - "data": "5b057b4f5acfc4771e1bd3e9" - }, { - "_id": "668014ea2b680c65290bbea0", - "Type": "AssortmentUnlockRule", - "entity": "5c10c8fd86f7743d7d706df3", - "data": "5c10c8fd86f7743d7d706df3" - }, { - "_id": "668014ea2b680c65290bbea1", - "Type": "AssortmentUnlockRule", - "entity": "5b44cd8b86f774503d30cba2", - "data": "5b44cd8b86f774503d30cba2" - }, { - "_id": "668014ea2b680c65290bbea2", - "Type": "AssortmentUnlockRule", - "entity": "5c0e3eb886f7742015526062", - "data": "5c0e3eb886f7742015526062" - }, { - "_id": "668014ea2b680c65290bbea3", - "Type": "AssortmentUnlockRule", - "entity": "5ca21c6986f77479963115a7", - "data": "5ca21c6986f77479963115a7" - }, { - "_id": "668014ea2b680c65290bbea4", - "Type": "AssortmentUnlockRule", - "entity": "5bae13bad4351e00320204af", - "data": "5bae13bad4351e00320204af" - }, { - "_id": "668014ea2b680c65290bbea5", - "Type": "AssortmentUnlockRule", - "entity": "593d493f86f7745e6b2ceb22", - "data": "593d493f86f7745e6b2ceb22" - }, { - "_id": "668014ea2b680c65290bbea6", - "Type": "AssortmentUnlockRule", - "entity": "5b40e2bc5acfc40016388216", - "data": "5b40e2bc5acfc40016388216" - }, { - "_id": "668014ea2b680c65290bbea7", - "Type": "AssortmentUnlockRule", - "entity": "5c0e774286f77468413cc5b2", - "data": "5c0e774286f77468413cc5b2" - }, { - "_id": "668014ea2b680c65290bbea8", - "Type": "AssortmentUnlockRule", - "entity": "5c0e51be86f774598e797894", - "data": "5c0e51be86f774598e797894" - }, { - "_id": "668014ea2b680c65290bbea9", - "Type": "AssortmentUnlockRule", - "entity": "5bffdd7e0db834001b734a1a", - "data": "5bffdd7e0db834001b734a1a" - }, { - "_id": "668014ea2b680c65290bbeaa", - "Type": "AssortmentUnlockRule", - "entity": "5bffe7930db834001b734a39", - "data": "5bffe7930db834001b734a39" - }, { - "_id": "668014ea2b680c65290bbeab", - "Type": "AssortmentUnlockRule", - "entity": "5c0d1e9386f77440120288b7", - "data": "5c0d1e9386f77440120288b7" - }, { - "_id": "668014ea2b680c65290bbeac", - "Type": "AssortmentUnlockRule", - "entity": "5c127c4486f7745625356c13", - "data": "5c127c4486f7745625356c13" - }, { - "_id": "668014ea2b680c65290bbead", - "Type": "AssortmentUnlockRule", - "entity": "5aafbde786f774389d0cbc0f", - "data": "5aafbde786f774389d0cbc0f" - }, { - "_id": "668014ea2b680c65290bbeae", - "Type": "AssortmentUnlockRule", - "entity": "5ac4ad7586f7747d14551da3", - "data": "5ac4ad7586f7747d14551da3" - }, { - "_id": "668014ea2b680c65290bbeaf", - "Type": "AssortmentUnlockRule", - "entity": "590c657e86f77412b013051d", - "data": "590c657e86f77412b013051d" - }, { - "_id": "668014ea2b680c65290bbeb0", - "Type": "AssortmentUnlockRule", - "entity": "5b6d9ce188a4501afc1b2b25", - "data": "5b6d9ce188a4501afc1b2b25" - }, { - "_id": "668014ea2b680c65290bbeb1", - "Type": "AssortmentUnlockRule", - "entity": "5c0e66e2d174af02a96252f4", - "data": "5c0e66e2d174af02a96252f4" - }, { - "_id": "668014ea2b680c65290bbeb2", - "Type": "AssortmentUnlockRule", - "entity": "5cc86832d7f00c000d3a6e6c", - "data": "5cc86832d7f00c000d3a6e6c" - }, { - "_id": "668014ea2b680c65290bbeb3", - "Type": "AssortmentUnlockRule", - "entity": "5c17a7ed2e2216152142459c", - "data": "5c17a7ed2e2216152142459c" - }, { - "_id": "668014ea2b680c65290bbeb4", - "Type": "AssortmentUnlockRule", - "entity": "584148f2245977598f1ad387", - "data": "584148f2245977598f1ad387" - }, { - "_id": "668014ea2b680c65290bbeb5", - "Type": "AssortmentUnlockRule", - "entity": "5d5e7d28a4b936645d161203", - "data": "5d5e7d28a4b936645d161203" - }, { - "_id": "668014ea2b680c65290bbeb6", - "Type": "AssortmentUnlockRule", - "entity": "5c1cd46f2e22164bef5cfedb", - "data": "5c1cd46f2e22164bef5cfedb" - }, { - "_id": "668014ea2b680c65290bbeb7", - "Type": "AssortmentUnlockRule", - "entity": "5d02797c86f774203f38e30a", - "data": "5d02797c86f774203f38e30a" - }, { - "_id": "668014ea2b680c65290bbeb8", - "Type": "AssortmentUnlockRule", - "entity": "5d23467086f77443f37fc602", - "data": "5d23467086f77443f37fc602" - }, { - "_id": "668014ea2b680c65290bbeb9", - "Type": "AssortmentUnlockRule", - "entity": "5d4d617f86f77449c463d107", - "data": "5d4d617f86f77449c463d107" - }, { - "_id": "668014ea2b680c65290bbeba", - "Type": "AssortmentUnlockRule", - "entity": "5aa7d193e5b5b000171d063f", - "data": "5aa7d193e5b5b000171d063f" - }, { - "_id": "668014ea2b680c65290bbebb", - "Type": "AssortmentUnlockRule", - "entity": "5a1eaa87fcdbcb001865f75e", - "data": "5a1eaa87fcdbcb001865f75e" - }, { - "_id": "668014ea2b680c65290bbebc", - "Type": "AssortmentUnlockRule", - "entity": "5af0454c86f7746bf20992e8", - "data": "5af0454c86f7746bf20992e8" - }, { - "_id": "668014ea2b680c65290bbebd", - "Type": "AssortmentUnlockRule", - "entity": "5ea2a8e200685063ec28c05a", - "data": "5ea2a8e200685063ec28c05a" - }, { - "_id": "668014ea2b680c65290bbebe", - "Type": "AssortmentUnlockRule", - "entity": "5d44069ca4b9361ebd26fc37", - "data": "5d44069ca4b9361ebd26fc37" - }, { - "_id": "668014ea2b680c65290bbebf", - "Type": "AssortmentUnlockRule", - "entity": "5cbda392ae92155f3c17c39f", - "data": "5cbda392ae92155f3c17c39f" - }, { - "_id": "668014ea2b680c65290bbec0", - "Type": "AssortmentUnlockRule", - "entity": "5dd800bde492226366631317", - "data": "5dd800bde492226366631317" - }, { - "_id": "668014ea2b680c65290bbec1", - "Type": "AssortmentUnlockRule", - "entity": "5e00c1ad86f774747333222c", - "data": "5e00c1ad86f774747333222c" - }, { - "_id": "668014ea2b680c65290bbec2", - "Type": "AssortmentUnlockRule", - "entity": "5dfa3d2b0dee1b22f862eade", - "data": "5dfa3d2b0dee1b22f862eade" - }, { - "_id": "668014ea2b680c65290bbec3", - "Type": "AssortmentUnlockRule", - "entity": "5f60c74e3b85f6263c145586", - "data": "5f60c74e3b85f6263c145586" - }, { - "_id": "668014ea2b680c65290bbec4", - "Type": "AssortmentUnlockRule", - "entity": "5df8a4d786f77412672a1e3b", - "data": "5df8a4d786f77412672a1e3b" - }, { - "_id": "668014ea2b680c65290bbec5", - "Type": "AssortmentUnlockRule", - "entity": "5d383f5d86f7742a15793872", - "data": "5d383f5d86f7742a15793872" - }, { - "_id": "668014ea2b680c65290bbec6", - "Type": "AssortmentUnlockRule", - "entity": "5dd800eae49222636663133b", - "data": "5dd800eae49222636663133b" - }, { - "_id": "668014ea2b680c65290bbec7", - "Type": "AssortmentUnlockRule", - "entity": "5c793fb92e221644f31bfb64", - "data": "5c793fb92e221644f31bfb64" - }, { - "_id": "668014ea2b680c65290bbec8", - "Type": "AssortmentUnlockRule", - "entity": "5d025cc1d7ad1a53845279ef", - "data": "5d025cc1d7ad1a53845279ef" - }, { - "_id": "668014ea2b680c65290bbec9", - "Type": "AssortmentUnlockRule", - "entity": "5cbdc23eae9215001136a407", - "data": "5cbdc23eae9215001136a407" - }, { - "_id": "668014ea2b680c65290bbeca", - "Type": "AssortmentUnlockRule", - "entity": "5d7b845786f7743c1e531da7", - "data": "5d7b845786f7743c1e531da7" - }, { - "_id": "668014ea2b680c65290bbecb", - "Type": "AssortmentUnlockRule", - "entity": "5d383e1a86f7742a1468ce63", - "data": "5d383e1a86f7742a1468ce63" - }, { - "_id": "668014ea2b680c65290bbecc", - "Type": "AssortmentUnlockRule", - "entity": "5e0354f786f77425b53eb6c5", - "data": "5e0354f786f77425b53eb6c5" - }, { - "_id": "668014ea2b680c65290bbecd", - "Type": "AssortmentUnlockRule", - "entity": "5e0340ab86f7745bb7339235", - "data": "5e0340ab86f7745bb7339235" - }, { - "_id": "668014ea2b680c65290bbece", - "Type": "AssortmentUnlockRule", - "entity": "5d38517786f7742a1468cf6a", - "data": "5d38517786f7742a1468cf6a" - }, { - "_id": "668014ea2b680c65290bbecf", - "Type": "AssortmentUnlockRule", - "entity": "5c0e446786f7742013381639", - "data": "5c0e446786f7742013381639" - }, { - "_id": "668014ea2b680c65290bbed0", - "Type": "AssortmentUnlockRule", - "entity": "5d383ee786f7742a15793860", - "data": "5d383ee786f7742a15793860" - }, { - "_id": "668014ea2b680c65290bbed1", - "Type": "AssortmentUnlockRule", - "entity": "609e8540d5c319764c2bc2e9", - "data": "609e8540d5c319764c2bc2e9" - }, { - "_id": "668014ea2b680c65290bbed2", - "Type": "AssortmentUnlockRule", - "entity": "64abd93857958b4249003418", - "data": "64abd93857958b4249003418" - }, { - "_id": "668014ea2b680c65290bbed3", - "Type": "AssortmentUnlockRule", - "entity": "6065878ac9cf8012264142fd", - "data": "6065878ac9cf8012264142fd" - }, { - "_id": "668014ea2b680c65290bbed4", - "Type": "AssortmentUnlockRule", - "entity": "618ba27d9008e4636a67f61d", - "data": "618ba27d9008e4636a67f61d" - }, { - "_id": "668014ea2b680c65290bbed5", - "Type": "AssortmentUnlockRule", - "entity": "59e6920f86f77411d82aa167", - "data": "59e6920f86f77411d82aa167" - }, { - "_id": "668014ea2b680c65290bbed6", - "Type": "AssortmentUnlockRule", - "entity": "624d7ae691f0160c7324c402", - "data": "624d7ae691f0160c7324c402" - }, { - "_id": "668014ea2b680c65290bbed7", - "Type": "AssortmentUnlockRule", - "entity": "628cd624459354321c4b7fa2", - "data": "628cd624459354321c4b7fa2" - }, { - "_id": "668014ea2b680c65290bbed8", - "Type": "AssortmentUnlockRule", - "entity": "5fd251c90d9c95034825edb5", - "data": "5fd251c90d9c95034825edb5" - }, { - "_id": "668014ea2b680c65290bbed9", - "Type": "AssortmentUnlockRule", - "entity": "5fd25119dd870108a754a163", - "data": "5fd25119dd870108a754a163" - }, { - "_id": "668014ea2b680c65290bbeda", - "Type": "AssortmentUnlockRule", - "entity": "619d26ccc7791e3af27ae3cd", - "data": "619d26ccc7791e3af27ae3cd" - }, { - "_id": "668014ea2b680c65290bbedb", - "Type": "AssortmentUnlockRule", - "entity": "6130c43c67085e45ef1405a1", - "data": "6130c43c67085e45ef1405a1" - }, { - "_id": "668014ea2b680c65290bbedc", - "Type": "AssortmentUnlockRule", - "entity": "60a283193cb70855c43a381d", - "data": "60a283193cb70855c43a381d" - }, { - "_id": "668014ea2b680c65290bbedd", - "Type": "AssortmentUnlockRule", - "entity": "619b69037b9de8162902673e", - "data": "619b69037b9de8162902673e" - }, { - "_id": "668014ea2b680c65290bbede", - "Type": "AssortmentUnlockRule", - "entity": "5656eb674bdc2d35148b457c", - "data": "5656eb674bdc2d35148b457c" - }, { - "_id": "668014ea2b680c65290bbedf", - "Type": "AssortmentUnlockRule", - "entity": "60a3c70cde5f453f634816a3", - "data": "60a3c70cde5f453f634816a3" - }, { - "_id": "668014ea2b680c65290bbee0", - "Type": "AssortmentUnlockRule", - "entity": "6193e590069d61205d490dd8", - "data": "6193e590069d61205d490dd8" - }, { - "_id": "668014ea2b680c65290bbee1", - "Type": "AssortmentUnlockRule", - "entity": "60098ad7c2240c0fe85c570a", - "data": "60098ad7c2240c0fe85c570a" - }, { - "_id": "668014ea2b680c65290bbee2", - "Type": "AssortmentUnlockRule", - "entity": "5ca2151486f774244a3b8d30", - "data": "5ca2151486f774244a3b8d30" - }, { - "_id": "668014ea2b680c65290bbee3", - "Type": "AssortmentUnlockRule", - "entity": "6193e108c1982475fa2a7f16", - "data": "6193e108c1982475fa2a7f16" - }, { - "_id": "668014ea2b680c65290bbee4", - "Type": "AssortmentUnlockRule", - "entity": "60479fb29c15b12b9a480fb0", - "data": "60479fb29c15b12b9a480fb0" - }, { - "_id": "668014ea2b680c65290bbee5", - "Type": "AssortmentUnlockRule", - "entity": "5ede475b549eed7c6d5c18fb", - "data": "5ede475b549eed7c6d5c18fb" - }, { - "_id": "668014ea2b680c65290bbee6", - "Type": "AssortmentUnlockRule", - "entity": "5e035eb586f774756048ec12", - "data": "5e035eb586f774756048ec12" - }, { - "_id": "668014ea2b680c65290bbee7", - "Type": "AssortmentUnlockRule", - "entity": "5e85a9f4add9fe03027d9bf1", - "data": "5e85a9f4add9fe03027d9bf1" - }, { - "_id": "668014ea2b680c65290bbee8", - "Type": "AssortmentUnlockRule", - "entity": "6038d614d10cbf667352dd44", - "data": "6038d614d10cbf667352dd44" - }, { - "_id": "668014ea2b680c65290bbee9", - "Type": "AssortmentUnlockRule", - "entity": "64be79e2bf8412471d0d9bcc", - "data": "64be79e2bf8412471d0d9bcc" - }, { - "_id": "668014ea2b680c65290bbeea", - "Type": "AssortmentUnlockRule", - "entity": "5d02797c86f774203f38e30a", - "data": "5d02797c86f774203f38e30a" - }, { - "_id": "668014ea2b680c65290bbeeb", - "Type": "AssortmentUnlockRule", - "entity": "618ab04934aa2e47480fba2b", - "data": "618ab04934aa2e47480fba2b" - }, { - "_id": "668014ea2b680c65290bbeec", - "Type": "AssortmentUnlockRule", - "entity": "615d8e9867085e45ef1409c6", - "data": "615d8e9867085e45ef1409c6" - }, { - "_id": "668014ea2b680c65290bbeed", - "Type": "AssortmentUnlockRule", - "entity": "5c0e655586f774045612eeb2", - "data": "5c0e655586f774045612eeb2" - }, { - "_id": "668014ea2b680c65290bbeee", - "Type": "AssortmentUnlockRule", - "entity": "5ef1ba28c64c5d0dfc0571a5", - "data": "5ef1ba28c64c5d0dfc0571a5" - }, { - "_id": "668014ea2b680c65290bbeef", - "Type": "AssortmentUnlockRule", - "entity": "5fd251ee16cac650092f5d02", - "data": "5fd251ee16cac650092f5d02" - }, { - "_id": "668014ea2b680c65290bbef0", - "Type": "AssortmentUnlockRule", - "entity": "64b8f7b5389d7ffd620ccba2", - "data": "64b8f7b5389d7ffd620ccba2" - }, { - "_id": "668014ea2b680c65290bbef1", - "Type": "AssortmentUnlockRule", - "entity": "606f2696f2cb2e02a42aceb1", - "data": "606f2696f2cb2e02a42aceb1" - }, { - "_id": "668014ea2b680c65290bbef2", - "Type": "AssortmentUnlockRule", - "entity": "60926df0132d4d12c81fd9df", - "data": "60926df0132d4d12c81fd9df" - }, { - "_id": "668014ea2b680c65290bbef3", - "Type": "AssortmentUnlockRule", - "entity": "5c0d5ae286f7741e46554302", - "data": "5c0d5ae286f7741e46554302" - }, { - "_id": "668014ea2b680c65290bbef4", - "Type": "AssortmentUnlockRule", - "entity": "5e21ca18e4d47f0da15e77dd", - "data": "5e21ca18e4d47f0da15e77dd" - }, { - "_id": "668014ea2b680c65290bbef5", - "Type": "AssortmentUnlockRule", - "entity": "61962b617c6c7b169525f168", - "data": "61962b617c6c7b169525f168" - }, { - "_id": "668014ea2b680c65290bbef6", - "Type": "AssortmentUnlockRule", - "entity": "60b7d76e2a3c79100f1979de", - "data": "60b7d76e2a3c79100f1979de" - }, { - "_id": "668014ea2b680c65290bbef7", - "Type": "AssortmentUnlockRule", - "entity": "5f60b34a41e30a4ab12a6947", - "data": "5f60b34a41e30a4ab12a6947" - }, { - "_id": "668014ea2b680c65290bbef8", - "Type": "AssortmentUnlockRule", - "entity": "5f06d6e1475d472556679d16", - "data": "5f06d6e1475d472556679d16" - }, { - "_id": "668014ea2b680c65290bbef9", - "Type": "AssortmentUnlockRule", - "entity": "5d5d646386f7742797261fd9", - "data": "5d5d646386f7742797261fd9" - }, { - "_id": "668014ea2b680c65290bbefa", - "Type": "AssortmentUnlockRule", - "entity": "5c1d0f4986f7744bb01837fa", - "data": "5c1d0f4986f7744bb01837fa" - }, { - "_id": "668014ea2b680c65290bbefb", - "Type": "AssortmentUnlockRule", - "entity": "6087e663132d4d12c81fd96b", - "data": "6087e663132d4d12c81fd96b" - }, { - "_id": "668014ea2b680c65290bbefc", - "Type": "AssortmentUnlockRule", - "entity": "619e61e70459e93c12392ba7", - "data": "619e61e70459e93c12392ba7" - }, { - "_id": "668014ea2b680c65290bbefd", - "Type": "AssortmentUnlockRule", - "entity": "6130ca3fd92c473c77020dbd", - "data": "6130ca3fd92c473c77020dbd" - }, { - "_id": "668014ea2b680c65290bbefe", - "Type": "AssortmentUnlockRule", - "entity": "62e7e7bbe6da9612f743f1e0", - "data": "62e7e7bbe6da9612f743f1e0" - }, { - "_id": "668014ea2b680c65290bbeff", - "Type": "AssortmentUnlockRule", - "entity": "5656eb674bdc2d35148b457c", - "data": "5656eb674bdc2d35148b457c" - }, { - "_id": "668014ea2b680c65290bbf00", - "Type": "AssortmentUnlockRule", - "entity": "64b6620258b5637e2d71a636", - "data": "64b6620258b5637e2d71a636" - }, { - "_id": "668014ea2b680c65290bbf01", - "Type": "AssortmentUnlockRule", - "entity": "655df24fdf80b12750626d0a", - "data": "655df24fdf80b12750626d0a" - }, { - "_id": "668014ea2b680c65290bbf02", - "Type": "AssortmentUnlockRule", - "entity": "62975de85c32d414f8797433", - "data": "62975de85c32d414f8797433" - }, { - "_id": "668014ea2b680c65290bbf03", - "Type": "AssortmentUnlockRule", - "entity": "657eb3773271d8578610fe28", - "data": "657eb3773271d8578610fe28" - }, { - "_id": "668014ea2b680c65290bbf04", - "Type": "AssortmentUnlockRule", - "entity": "590c5d4b86f774784e1b9c45", - "data": "590c5d4b86f774784e1b9c45" - }, { - "_id": "668014ea2b680c65290bbf05", - "Type": "AssortmentUnlockRule", - "entity": "6389c7750ef44505c87f5996", - "data": "6389c7750ef44505c87f5996" - }, { - "_id": "668014ea2b680c65290bbf06", - "Type": "AssortmentUnlockRule", - "entity": "6357c98711fb55120211f7e1", - "data": "6357c98711fb55120211f7e1" - }, { - "_id": "668014ea2b680c65290bbf07", - "Type": "AssortmentUnlockRule", - "entity": "5c110624d174af029e69734c", - "data": "5c110624d174af029e69734c" - }, { - "_id": "668014ea2b680c65290bbf08", - "Type": "AssortmentUnlockRule", - "entity": "63920105a83e15700a00f168", - "data": "63920105a83e15700a00f168" - }, { - "_id": "668014ea2b680c65290bbf09", - "Type": "AssortmentUnlockRule", - "entity": "6357c98711fb55120211f7e1", - "data": "6357c98711fb55120211f7e1" - }, { - "_id": "668014ea2b680c65290bbf0a", - "Type": "AssortmentUnlockRule", - "entity": "656f664200d62bcd2e024077", - "data": "656f664200d62bcd2e024077" - }, { - "_id": "668014ea2b680c65290bbf0b", - "Type": "AssortmentUnlockRule", - "entity": "62973e474bb5ab23071c2a70", - "data": "62973e474bb5ab23071c2a70" - }, { - "_id": "668014ea2b680c65290bbf0c", - "Type": "AssortmentUnlockRule", - "entity": "655746010177119f4a097ff7", - "data": "655746010177119f4a097ff7" - }, { - "_id": "668014ea2b680c65290bbf0d", - "Type": "AssortmentUnlockRule", - "entity": "6570aead4d84f81fd002a033", - "data": "6570aead4d84f81fd002a033" - }, { - "_id": "668014ea2b680c65290bbf0e", - "Type": "AssortmentUnlockRule", - "entity": "62a0a043cf4a99369e2624a5", - "data": "62a0a043cf4a99369e2624a5" - }, { - "_id": "668014ea2b680c65290bbf0f", - "Type": "AssortmentUnlockRule", - "entity": "5e85a9f4add9fe03027d9bf1", - "data": "5e85a9f4add9fe03027d9bf1" - }, { - "_id": "668014ea2b680c65290bbf10", - "Type": "AssortmentUnlockRule", - "entity": "5c0a840b86f7742ffa4f2482", - "data": "5c0a840b86f7742ffa4f2482" - }, { - "_id": "668014ea2b680c65290bbf11", - "Type": "AssortmentUnlockRule", - "entity": "6389c7f115805221fb410466", - "data": "6389c7f115805221fb410466" - }, { - "_id": "668014ea2b680c65290bbf12", - "Type": "AssortmentUnlockRule", - "entity": "656f611f94b480b8a500c0db", - "data": "656f611f94b480b8a500c0db" - }, { - "_id": "668014ea2b680c65290bbf13", - "Type": "AssortmentUnlockRule", - "entity": "62e7e7bbe6da9612f743f1e0", - "data": "62e7e7bbe6da9612f743f1e0" - }, { - "_id": "668014ea2b680c65290bbf14", - "Type": "AssortmentUnlockRule", - "entity": "64c1525e3319a1cf380c4e09", - "data": "64c1525e3319a1cf380c4e09" - }, { - "_id": "668014ea2b680c65290bbf15", - "Type": "AssortmentUnlockRule", - "entity": "5a327f7c86f77475187e509a", - "data": "5a327f7c86f77475187e509a" - }, { - "_id": "668014ea2b680c65290bbf16", - "Type": "AssortmentUnlockRule", - "entity": "5c0e530286f7747fa1419862", - "data": "5c0e530286f7747fa1419862" - }, { - "_id": "668014ea2b680c65290bbf17", - "Type": "AssortmentUnlockRule", - "entity": "5ede475b549eed7c6d5c18fb", - "data": "5ede475b549eed7c6d5c18fb" - }, { - "_id": "668014ea2b680c65290bbf18", - "Type": "AssortmentUnlockRule", - "entity": "5b2388675acfc4771e1be0be", - "data": "5b2388675acfc4771e1be0be" - }, { - "_id": "668014ea2b680c65290bbf19", - "Type": "AssortmentUnlockRule", - "entity": "63fc44e2429a8a166c7f61e6", - "data": "63fc44e2429a8a166c7f61e6" - }, { - "_id": "668014ea2b680c65290bbf1a", - "Type": "AssortmentUnlockRule", - "entity": "601aa3d2b2bcb34913271e6d", - "data": "601aa3d2b2bcb34913271e6d" - }, { - "_id": "668014ea2b680c65290bbf1b", - "Type": "AssortmentUnlockRule", - "entity": "656fa8d700d62bcd2e024084", - "data": "656fa8d700d62bcd2e024084" - }, { - "_id": "668014ea2b680c65290bbf1c", - "Type": "AssortmentUnlockRule", - "entity": "618ba27d9008e4636a67f61d", - "data": "618ba27d9008e4636a67f61d" - }, { - "_id": "668014ea2b680c65290bbf1d", - "Type": "AssortmentUnlockRule", - "entity": "657089638db3adca1009f4ca", - "data": "657089638db3adca1009f4ca" - }, { - "_id": "668014ea2b680c65290bbf1e", - "Type": "AssortmentUnlockRule", - "entity": "5efb0da7a29a85116f6ea05f", - "data": "5efb0da7a29a85116f6ea05f" - }, { - "_id": "668014ea2b680c65290bbf1f", - "Type": "AssortmentUnlockRule", - "entity": "63986a9ab483a550805be5ee", - "data": "63986a9ab483a550805be5ee" - }, { - "_id": "668014ea2b680c65290bbf20", - "Type": "AssortmentUnlockRule", - "entity": "656fa25e94b480b8a500c0e0", - "data": "656fa25e94b480b8a500c0e0" - }, { - "_id": "668014ea2b680c65290bbf21", - "Type": "AssortmentUnlockRule", - "entity": "6389c85357baa773a825b356", - "data": "6389c85357baa773a825b356" - }, { - "_id": "668014ea2b680c65290bbf22", - "Type": "AssortmentUnlockRule", - "entity": "64f8c5c6c8626c7d46040335", - "data": "64f8c5c6c8626c7d46040335" - }, { - "_id": "668014ea2b680c65290bbf23", - "Type": "AssortmentUnlockRule", - "entity": "63fc44e2429a8a166c7f61e6", - "data": "63fc44e2429a8a166c7f61e6" - }, { - "_id": "668014ea2b680c65290bbf24", - "Type": "AssortmentUnlockRule", - "entity": "65573fa5655447403702a816", - "data": "65573fa5655447403702a816" - } - ], - "maxToSendPlayer": 1 - }, - "HIDEOUTCAT": { + "profileChangeEvents": [ + { + "_id": "668014ea2b680c65290bbe1d", + "Type": "TraderSalesSum", + "value": 2500000, + "entity": "5ac3b934156ae10c4430e83c" + }, + { + "_id": "668014ea2b680c65290bbe1e", + "Type": "TraderStanding", + "value": 0.6, + "entity": "5ac3b934156ae10c4430e83c" + }, + { + "_id": "668014ea2b680c65290bbe1f", + "Type": "TraderSalesSum", + "value": 2600000, + "entity": "58330581ace78e27b8b10cee" + }, + { + "_id": "668014ea2b680c65290bbe20", + "Type": "TraderStanding", + "value": 0.75, + "entity": "58330581ace78e27b8b10cee" + }, + { + "_id": "668014ea2b680c65290bbe21", + "Type": "TraderSalesSum", + "value": 1725000, + "entity": "5c0647fdd443bc2504c2d371" + }, + { + "_id": "668014ea2b680c65290bbe22", + "Type": "TraderStanding", + "value": 0.5, + "entity": "5c0647fdd443bc2504c2d371" + }, + { + "_id": "668014ea2b680c65290bbe23", + "Type": "TraderSalesSum", + "value": 2500000, + "entity": "5a7c2eca46aef81a7ca2145d" + }, + { + "_id": "668014ea2b680c65290bbe24", + "Type": "TraderStanding", + "value": 0.6, + "entity": "5a7c2eca46aef81a7ca2145d" + }, + { + "_id": "668014ea2b680c65290bbe25", + "Type": "TraderSalesSum", + "value": 32000, + "entity": "5935c25fb3acc3127c3d8cd9" + }, + { + "_id": "668014ea2b680c65290bbe26", + "Type": "TraderStanding", + "value": 0.6, + "entity": "5935c25fb3acc3127c3d8cd9" + }, + { + "_id": "668014ea2b680c65290bbe27", + "Type": "TraderSalesSum", + "value": 2300000, + "entity": "54cb50c76803fa8b248b4571" + }, + { + "_id": "668014ea2b680c65290bbe28", + "Type": "TraderStanding", + "value": 0.5, + "entity": "54cb50c76803fa8b248b4571" + }, + { + "_id": "668014ea2b680c65290bbe29", + "Type": "TraderSalesSum", + "value": 900000, + "entity": "54cb57776803fa99248b456e" + }, + { + "_id": "668014ea2b680c65290bbe2a", + "Type": "TraderStanding", + "value": 0.6, + "entity": "54cb57776803fa99248b456e" + }, + { + "_id": "668014ea2b680c65290bbe2b", + "Type": "ProfileLevel", + "value": 2901143, + "entity": null + }, + { + "_id": "668014ea2b680c65290bbe2c", + "Type": "SkillPoints", + "value": 2500, + "entity": "Endurance" + }, + { + "_id": "668014ea2b680c65290bbe2d", + "Type": "SkillPoints", + "value": 2500, + "entity": "Strength" + }, + { + "_id": "668014ea2b680c65290bbe2e", + "Type": "SkillPoints", + "value": 2500, + "entity": "Vitality" + }, + { + "_id": "668014ea2b680c65290bbe2f", + "Type": "SkillPoints", + "value": 2500, + "entity": "Health" + }, + { + "_id": "668014ea2b680c65290bbe30", + "Type": "SkillPoints", + "value": 2500, + "entity": "Metabolism" + }, + { + "_id": "668014ea2b680c65290bbe31", + "Type": "SkillPoints", + "value": 2500, + "entity": "StressResistance" + }, + { + "_id": "668014ea2b680c65290bbe32", + "Type": "SkillPoints", + "value": 2500, + "entity": "Immunity" + }, + { + "_id": "668014ea2b680c65290bbe33", + "Type": "SkillPoints", + "value": 2500, + "entity": "Throwing" + }, + { + "_id": "668014ea2b680c65290bbe34", + "Type": "SkillPoints", + "value": 2500, + "entity": "RecoilControl" + }, + { + "_id": "668014ea2b680c65290bbe35", + "Type": "SkillPoints", + "value": 2500, + "entity": "Pistol" + }, + { + "_id": "668014ea2b680c65290bbe36", + "Type": "SkillPoints", + "value": 2500, + "entity": "Revolver" + }, + { + "_id": "668014ea2b680c65290bbe37", + "Type": "SkillPoints", + "value": 2500, + "entity": "SMG" + }, + { + "_id": "668014ea2b680c65290bbe38", + "Type": "SkillPoints", + "value": 2500, + "entity": "Assault" + }, + { + "_id": "668014ea2b680c65290bbe39", + "Type": "SkillPoints", + "value": 2500, + "entity": "Shotgun" + }, + { + "_id": "668014ea2b680c65290bbe3a", + "Type": "SkillPoints", + "value": 2500, + "entity": "Sniper" + }, + { + "_id": "668014ea2b680c65290bbe3b", + "Type": "SkillPoints", + "value": 2500, + "entity": "LMG" + }, + { + "_id": "668014ea2b680c65290bbe3c", + "Type": "SkillPoints", + "value": 2500, + "entity": "HMG" + }, + { + "_id": "668014ea2b680c65290bbe3d", + "Type": "SkillPoints", + "value": 2500, + "entity": "Launcher" + }, + { + "_id": "668014ea2b680c65290bbe3e", + "Type": "SkillPoints", + "value": 2500, + "entity": "AttachedLauncher" + }, + { + "_id": "668014ea2b680c65290bbe3f", + "Type": "SkillPoints", + "value": 2500, + "entity": "Melee" + }, + { + "_id": "668014ea2b680c65290bbe40", + "Type": "SkillPoints", + "value": 2500, + "entity": "DMR" + }, + { + "_id": "668014ea2b680c65290bbe41", + "Type": "SkillPoints", + "value": 2500, + "entity": "CovertMovement" + }, + { + "_id": "668014ea2b680c65290bbe42", + "Type": "SkillPoints", + "value": 2500, + "entity": "Search" + }, + { + "_id": "668014ea2b680c65290bbe43", + "Type": "SkillPoints", + "value": 2500, + "entity": "MagDrills" + }, + { + "_id": "668014ea2b680c65290bbe44", + "Type": "SkillPoints", + "value": 2500, + "entity": "Perception" + }, + { + "_id": "668014ea2b680c65290bbe45", + "Type": "SkillPoints", + "value": 2500, + "entity": "Intellect" + }, + { + "_id": "668014ea2b680c65290bbe46", + "Type": "SkillPoints", + "value": 2500, + "entity": "Charisma" + }, + { + "_id": "668014ea2b680c65290bbe47", + "Type": "SkillPoints", + "value": 2500, + "entity": "Memory" + }, + { + "_id": "668014ea2b680c65290bbe48", + "Type": "SkillPoints", + "value": 2500, + "entity": "Surgery" + }, + { + "_id": "668014ea2b680c65290bbe49", + "Type": "SkillPoints", + "value": 2500, + "entity": "AimDrills" + }, + { + "_id": "668014ea2b680c65290bbe4a", + "Type": "SkillPoints", + "value": 2500, + "entity": "HideoutManagement" + }, + { + "_id": "668014ea2b680c65290bbe4b", + "Type": "SkillPoints", + "value": 2500, + "entity": "Crafting" + }, + { + "_id": "668014ea2b680c65290bbe4c", + "Type": "SkillPoints", + "value": 2500, + "entity": "Attention" + }, + { + "_id": "668014ea2b680c65290bbe4d", + "Type": "SkillPoints", + "value": 2500, + "entity": "63" + }, + { + "_id": "668014ea2b680c65290bbe4e", + "Type": "SkillPoints", + "value": 2500, + "entity": "39" + }, + { + "_id": "668014ea2b680c65290bbe4f", + "Type": "SkillPoints", + "value": 2500, + "entity": "38" + }, + { + "_id": "668014ea2b680c65290bbe50", + "Type": "SkillPoints", + "value": 2500, + "entity": "45" + }, + { + "_id": "668014ea2b680c65290bbe51", + "Type": "ExamineAllItems" + }, + { + "_id": "668014ea2b680c65290bbe52", + "Type": "UnlockTrader", + "value": 1, + "entity": "5c0647fdd443bc2504c2d371" + }, + { + "_id": "668014ea2b680c65290bbe53", + "Type": "HideoutAreaLevel", + "value": 1, + "entity": "Workbench" + }, + { + "_id": "668014ea2b680c65290bbe54", + "Type": "AssortmentUnlockRule", + "entity": "584149ad2459775a7726350e", + "data": "584149ad2459775a7726350e" + }, + { + "_id": "668014ea2b680c65290bbe55", + "Type": "AssortmentUnlockRule", + "entity": "544fb45d4bdc2dee738b4568", + "data": "544fb45d4bdc2dee738b4568" + }, + { + "_id": "668014ea2b680c65290bbe56", + "Type": "AssortmentUnlockRule", + "entity": "590c661e86f7741e566b646a", + "data": "590c661e86f7741e566b646a" + }, + { + "_id": "668014ea2b680c65290bbe57", + "Type": "AssortmentUnlockRule", + "entity": "5a13df5286f774032f5454a0", + "data": "5a13df5286f774032f5454a0" + }, + { + "_id": "668014ea2b680c65290bbe58", + "Type": "AssortmentUnlockRule", + "entity": "544fb3f34bdc2d03748b456a", + "data": "544fb3f34bdc2d03748b456a" + }, + { + "_id": "668014ea2b680c65290bbe59", + "Type": "AssortmentUnlockRule", + "entity": "58d2912286f7744e27117493", + "data": "58d2912286f7744e27117493" + }, + { + "_id": "668014ea2b680c65290bbe5a", + "Type": "AssortmentUnlockRule", + "entity": "57372140245977611f70ee91", + "data": "57372140245977611f70ee91" + }, + { + "_id": "668014ea2b680c65290bbe5b", + "Type": "AssortmentUnlockRule", + "entity": "5ac8d6885acfc400180ae7b0", + "data": "5ac8d6885acfc400180ae7b0" + }, + { + "_id": "668014ea2b680c65290bbe5c", + "Type": "AssortmentUnlockRule", + "entity": "5aa7e276e5b5b000171d0647", + "data": "5aa7e276e5b5b000171d0647" + }, + { + "_id": "668014ea2b680c65290bbe5d", + "Type": "AssortmentUnlockRule", + "entity": "59eb7ebe86f7740b373438ce", + "data": "59eb7ebe86f7740b373438ce" + }, + { + "_id": "668014ea2b680c65290bbe5e", + "Type": "AssortmentUnlockRule", + "entity": "5656d7c34bdc2d9d198b4587", + "data": "5656d7c34bdc2d9d198b4587" + }, + { + "_id": "668014ea2b680c65290bbe5f", + "Type": "AssortmentUnlockRule", + "entity": "55d482194bdc2d1d4e8b456b", + "data": "55d482194bdc2d1d4e8b456b" + }, + { + "_id": "668014ea2b680c65290bbe60", + "Type": "AssortmentUnlockRule", + "entity": "58dffc5d86f77407c744a847", + "data": "58dffc5d86f77407c744a847" + }, + { + "_id": "668014ea2b680c65290bbe61", + "Type": "AssortmentUnlockRule", + "entity": "57da93632459771cb65bf83f", + "data": "57da93632459771cb65bf83f" + }, + { + "_id": "668014ea2b680c65290bbe62", + "Type": "AssortmentUnlockRule", + "entity": "56dff0bed2720bb0668b4567", + "data": "56dff0bed2720bb0668b4567" + }, + { + "_id": "668014ea2b680c65290bbe63", + "Type": "AssortmentUnlockRule", + "entity": "59bfe68886f7746004266202", + "data": "59bfe68886f7746004266202" + }, + { + "_id": "668014ea2b680c65290bbe64", + "Type": "AssortmentUnlockRule", + "entity": "59e77a2386f7742ee578960a", + "data": "59e77a2386f7742ee578960a" + }, + { + "_id": "668014ea2b680c65290bbe65", + "Type": "AssortmentUnlockRule", + "entity": "5a269f97c4a282000b151807", + "data": "5a269f97c4a282000b151807" + }, + { + "_id": "668014ea2b680c65290bbe66", + "Type": "AssortmentUnlockRule", + "entity": "58d3db5386f77426186285a0", + "data": "58d3db5386f77426186285a0" + }, + { + "_id": "668014ea2b680c65290bbe67", + "Type": "AssortmentUnlockRule", + "entity": "5a3a85af86f774745637d46c", + "data": "5a3a85af86f774745637d46c" + }, + { + "_id": "668014ea2b680c65290bbe68", + "Type": "AssortmentUnlockRule", + "entity": "5a33e75ac4a2826c6e06d759", + "data": "5a33e75ac4a2826c6e06d759" + }, + { + "_id": "668014ea2b680c65290bbe69", + "Type": "AssortmentUnlockRule", + "entity": "545cdb794bdc2d3a198b456a", + "data": "545cdb794bdc2d3a198b456a" + }, + { + "_id": "668014ea2b680c65290bbe6a", + "Type": "AssortmentUnlockRule", + "entity": "545cdae64bdc2d39198b4568", + "data": "545cdae64bdc2d39198b4568" + }, + { + "_id": "668014ea2b680c65290bbe6b", + "Type": "AssortmentUnlockRule", + "entity": "5649ae4a4bdc2d1b2b8b4588", + "data": "5649ae4a4bdc2d1b2b8b4588" + }, + { + "_id": "668014ea2b680c65290bbe6c", + "Type": "AssortmentUnlockRule", + "entity": "58dffd4586f77408a27629b2", + "data": "58dffd4586f77408a27629b2" + }, + { + "_id": "668014ea2b680c65290bbe6d", + "Type": "AssortmentUnlockRule", + "entity": "5751a25924597722c463c472", + "data": "5751a25924597722c463c472" + }, + { + "_id": "668014ea2b680c65290bbe6e", + "Type": "AssortmentUnlockRule", + "entity": "59c1383d86f774290a37e0ca", + "data": "59c1383d86f774290a37e0ca" + }, + { + "_id": "668014ea2b680c65290bbe6f", + "Type": "AssortmentUnlockRule", + "entity": "5a0c59791526d8dba737bba7", + "data": "5a0c59791526d8dba737bba7" + }, + { + "_id": "668014ea2b680c65290bbe70", + "Type": "AssortmentUnlockRule", + "entity": "576fd4ec2459777f0b518431", + "data": "576fd4ec2459777f0b518431" + }, + { + "_id": "668014ea2b680c65290bbe71", + "Type": "AssortmentUnlockRule", + "entity": "57a0e5022459774d1673f889", + "data": "57a0e5022459774d1673f889" + }, + { + "_id": "668014ea2b680c65290bbe72", + "Type": "AssortmentUnlockRule", + "entity": "584984812459776a704a82a6", + "data": "584984812459776a704a82a6" + }, + { + "_id": "668014ea2b680c65290bbe73", + "Type": "AssortmentUnlockRule", + "entity": "59c0ec5b86f77435b128bfca", + "data": "59c0ec5b86f77435b128bfca" + }, + { + "_id": "668014ea2b680c65290bbe74", + "Type": "AssortmentUnlockRule", + "entity": "57ffb0e42459777d047111c5", + "data": "57ffb0e42459777d047111c5" + }, + { + "_id": "668014ea2b680c65290bbe75", + "Type": "AssortmentUnlockRule", + "entity": "58dd3ad986f77403051cba8f", + "data": "58dd3ad986f77403051cba8f" + }, + { + "_id": "668014ea2b680c65290bbe76", + "Type": "AssortmentUnlockRule", + "entity": "5a16b7e1fcdbcb00165aa6c9", + "data": "5a16b7e1fcdbcb00165aa6c9" + }, + { + "_id": "668014ea2b680c65290bbe77", + "Type": "AssortmentUnlockRule", + "entity": "56eabf3bd2720b75698b4569", + "data": "56eabf3bd2720b75698b4569" + }, + { + "_id": "668014ea2b680c65290bbe78", + "Type": "AssortmentUnlockRule", + "entity": "588226ef24597767af46e39c", + "data": "588226ef24597767af46e39c" + }, + { + "_id": "668014ea2b680c65290bbe79", + "Type": "AssortmentUnlockRule", + "entity": "59411abb86f77478f702b5d2", + "data": "59411abb86f77478f702b5d2" + }, + { + "_id": "668014ea2b680c65290bbe7a", + "Type": "AssortmentUnlockRule", + "entity": "58414a16245977599247970a", + "data": "58414a16245977599247970a" + }, + { + "_id": "668014ea2b680c65290bbe7b", + "Type": "AssortmentUnlockRule", + "entity": "590c678286f77426c9660122", + "data": "590c678286f77426c9660122" + }, + { + "_id": "668014ea2b680c65290bbe7c", + "Type": "AssortmentUnlockRule", + "entity": "584147982459775a6c55e931", + "data": "584147982459775a6c55e931" + }, + { + "_id": "668014ea2b680c65290bbe7d", + "Type": "AssortmentUnlockRule", + "entity": "5a8ae65f86f774377a23ed55", + "data": "5a8ae65f86f774377a23ed55" + }, + { + "_id": "668014ea2b680c65290bbe7e", + "Type": "AssortmentUnlockRule", + "entity": "5af08cc686f77424a61595f2", + "data": "5af08cc686f77424a61595f2" + }, + { + "_id": "668014ea2b680c65290bbe7f", + "Type": "AssortmentUnlockRule", + "entity": "5b07dd285acfc4001754240d", + "data": "5b07dd285acfc4001754240d" + }, + { + "_id": "668014ea2b680c65290bbe80", + "Type": "AssortmentUnlockRule", + "entity": "5b4391a586f7745321235ab2", + "data": "5b4391a586f7745321235ab2" + }, + { + "_id": "668014ea2b680c65290bbe81", + "Type": "AssortmentUnlockRule", + "entity": "5c1127d0d174af29be75cf68", + "data": "5c1127d0d174af29be75cf68" + }, + { + "_id": "668014ea2b680c65290bbe82", + "Type": "AssortmentUnlockRule", + "entity": "5c0e722886f7740458316a57", + "data": "5c0e722886f7740458316a57" + }, + { + "_id": "668014ea2b680c65290bbe83", + "Type": "AssortmentUnlockRule", + "entity": "5bbde409d4351e003562b036", + "data": "5bbde409d4351e003562b036" + }, + { + "_id": "668014ea2b680c65290bbe84", + "Type": "AssortmentUnlockRule", + "entity": "5b4329f05acfc47a86086aa1", + "data": "5b4329f05acfc47a86086aa1" + }, + { + "_id": "668014ea2b680c65290bbe85", + "Type": "AssortmentUnlockRule", + "entity": "5ba2678ad4351e44f824b344", + "data": "5ba2678ad4351e44f824b344" + }, + { + "_id": "668014ea2b680c65290bbe86", + "Type": "AssortmentUnlockRule", + "entity": "56ea8d2fd2720b7c698b4570", + "data": "56ea8d2fd2720b7c698b4570" + }, + { + "_id": "668014ea2b680c65290bbe87", + "Type": "AssortmentUnlockRule", + "entity": "5bc5a372d4351e44f824d17f", + "data": "5bc5a372d4351e44f824d17f" + }, + { + "_id": "668014ea2b680c65290bbe88", + "Type": "AssortmentUnlockRule", + "entity": "5bbde41ed4351e003562b038", + "data": "5bbde41ed4351e003562b038" + }, + { + "_id": "668014ea2b680c65290bbe89", + "Type": "AssortmentUnlockRule", + "entity": "5bc5a35cd4351e450201232f", + "data": "5bc5a35cd4351e450201232f" + }, + { + "_id": "668014ea2b680c65290bbe8a", + "Type": "AssortmentUnlockRule", + "entity": "5cc80f8fe4a949033b0224a2", + "data": "5cc80f8fe4a949033b0224a2" + }, + { + "_id": "668014ea2b680c65290bbe8b", + "Type": "AssortmentUnlockRule", + "entity": "5a966f51a2750c00156aacf6", + "data": "5a966f51a2750c00156aacf6" + }, + { + "_id": "668014ea2b680c65290bbe8c", + "Type": "AssortmentUnlockRule", + "entity": "5ac78a9b86f7741cca0bbd8d", + "data": "5ac78a9b86f7741cca0bbd8d" + }, + { + "_id": "668014ea2b680c65290bbe8d", + "Type": "AssortmentUnlockRule", + "entity": "5b44cf1486f77431723e3d05", + "data": "5b44cf1486f77431723e3d05" + }, + { + "_id": "668014ea2b680c65290bbe8e", + "Type": "AssortmentUnlockRule", + "entity": "5aafbde786f774389d0cbc0f", + "data": "5aafbde786f774389d0cbc0f" + }, + { + "_id": "668014ea2b680c65290bbe8f", + "Type": "AssortmentUnlockRule", + "entity": "59fb137a86f7740adb646af1", + "data": "59fb137a86f7740adb646af1" + }, + { + "_id": "668014ea2b680c65290bbe90", + "Type": "AssortmentUnlockRule", + "entity": "5bae13ded4351e44f824bf38", + "data": "5bae13ded4351e44f824bf38" + }, + { + "_id": "668014ea2b680c65290bbe91", + "Type": "AssortmentUnlockRule", + "entity": "5bbdb870d4351e00367fb67d", + "data": "5bbdb870d4351e00367fb67d" + }, + { + "_id": "668014ea2b680c65290bbe92", + "Type": "AssortmentUnlockRule", + "entity": "5b3116595acfc40019476364", + "data": "5b3116595acfc40019476364" + }, + { + "_id": "668014ea2b680c65290bbe93", + "Type": "AssortmentUnlockRule", + "entity": "5b83f22086f77464e15a1d5f", + "data": "5b83f22086f77464e15a1d5f" + }, + { + "_id": "668014ea2b680c65290bbe94", + "Type": "AssortmentUnlockRule", + "entity": "5bbdb83fd4351e44f824c44b", + "data": "5bbdb83fd4351e44f824c44b" + }, + { + "_id": "668014ea2b680c65290bbe95", + "Type": "AssortmentUnlockRule", + "entity": "5c0a2cec0db834001b7ce47d", + "data": "5c0a2cec0db834001b7ce47d" + }, + { + "_id": "668014ea2b680c65290bbe96", + "Type": "AssortmentUnlockRule", + "entity": "5ac4ad3686f774181345c3da", + "data": "5ac4ad3686f774181345c3da" + }, + { + "_id": "668014ea2b680c65290bbe97", + "Type": "AssortmentUnlockRule", + "entity": "58d2912286f7744e27117493", + "data": "58d2912286f7744e27117493" + }, + { + "_id": "668014ea2b680c65290bbe98", + "Type": "AssortmentUnlockRule", + "entity": "56eabcd4d2720b66698b4574", + "data": "56eabcd4d2720b66698b4574" + }, + { + "_id": "668014ea2b680c65290bbe99", + "Type": "AssortmentUnlockRule", + "entity": "5bbdb811d4351e45020113c7", + "data": "5bbdb811d4351e45020113c7" + }, + { + "_id": "668014ea2b680c65290bbe9a", + "Type": "AssortmentUnlockRule", + "entity": "5bc5a351d4351e003477a414", + "data": "5bc5a351d4351e003477a414" + }, + { + "_id": "668014ea2b680c65290bbe9b", + "Type": "AssortmentUnlockRule", + "entity": "5c1260dc86f7746b106e8748", + "data": "5c1260dc86f7746b106e8748" + }, + { + "_id": "668014ea2b680c65290bbe9c", + "Type": "AssortmentUnlockRule", + "entity": "5b44d0de86f774503d30cba8", + "data": "5b44d0de86f774503d30cba8" + }, + { + "_id": "668014ea2b680c65290bbe9d", + "Type": "AssortmentUnlockRule", + "entity": "5a8c436686f7740f394d10b5", + "data": "5a8c436686f7740f394d10b5" + }, + { + "_id": "668014ea2b680c65290bbe9e", + "Type": "AssortmentUnlockRule", + "entity": "5b07db875acfc40dc528a5f6", + "data": "5b07db875acfc40dc528a5f6" + }, + { + "_id": "668014ea2b680c65290bbe9f", + "Type": "AssortmentUnlockRule", + "entity": "5b057b4f5acfc4771e1bd3e9", + "data": "5b057b4f5acfc4771e1bd3e9" + }, + { + "_id": "668014ea2b680c65290bbea0", + "Type": "AssortmentUnlockRule", + "entity": "5c10c8fd86f7743d7d706df3", + "data": "5c10c8fd86f7743d7d706df3" + }, + { + "_id": "668014ea2b680c65290bbea1", + "Type": "AssortmentUnlockRule", + "entity": "5b44cd8b86f774503d30cba2", + "data": "5b44cd8b86f774503d30cba2" + }, + { + "_id": "668014ea2b680c65290bbea2", + "Type": "AssortmentUnlockRule", + "entity": "5c0e3eb886f7742015526062", + "data": "5c0e3eb886f7742015526062" + }, + { + "_id": "668014ea2b680c65290bbea3", + "Type": "AssortmentUnlockRule", + "entity": "5ca21c6986f77479963115a7", + "data": "5ca21c6986f77479963115a7" + }, + { + "_id": "668014ea2b680c65290bbea4", + "Type": "AssortmentUnlockRule", + "entity": "5bae13bad4351e00320204af", + "data": "5bae13bad4351e00320204af" + }, + { + "_id": "668014ea2b680c65290bbea5", + "Type": "AssortmentUnlockRule", + "entity": "593d493f86f7745e6b2ceb22", + "data": "593d493f86f7745e6b2ceb22" + }, + { + "_id": "668014ea2b680c65290bbea6", + "Type": "AssortmentUnlockRule", + "entity": "5b40e2bc5acfc40016388216", + "data": "5b40e2bc5acfc40016388216" + }, + { + "_id": "668014ea2b680c65290bbea7", + "Type": "AssortmentUnlockRule", + "entity": "5c0e774286f77468413cc5b2", + "data": "5c0e774286f77468413cc5b2" + }, + { + "_id": "668014ea2b680c65290bbea8", + "Type": "AssortmentUnlockRule", + "entity": "5c0e51be86f774598e797894", + "data": "5c0e51be86f774598e797894" + }, + { + "_id": "668014ea2b680c65290bbea9", + "Type": "AssortmentUnlockRule", + "entity": "5bffdd7e0db834001b734a1a", + "data": "5bffdd7e0db834001b734a1a" + }, + { + "_id": "668014ea2b680c65290bbeaa", + "Type": "AssortmentUnlockRule", + "entity": "5bffe7930db834001b734a39", + "data": "5bffe7930db834001b734a39" + }, + { + "_id": "668014ea2b680c65290bbeab", + "Type": "AssortmentUnlockRule", + "entity": "5c0d1e9386f77440120288b7", + "data": "5c0d1e9386f77440120288b7" + }, + { + "_id": "668014ea2b680c65290bbeac", + "Type": "AssortmentUnlockRule", + "entity": "5c127c4486f7745625356c13", + "data": "5c127c4486f7745625356c13" + }, + { + "_id": "668014ea2b680c65290bbead", + "Type": "AssortmentUnlockRule", + "entity": "5aafbde786f774389d0cbc0f", + "data": "5aafbde786f774389d0cbc0f" + }, + { + "_id": "668014ea2b680c65290bbeae", + "Type": "AssortmentUnlockRule", + "entity": "5ac4ad7586f7747d14551da3", + "data": "5ac4ad7586f7747d14551da3" + }, + { + "_id": "668014ea2b680c65290bbeaf", + "Type": "AssortmentUnlockRule", + "entity": "590c657e86f77412b013051d", + "data": "590c657e86f77412b013051d" + }, + { + "_id": "668014ea2b680c65290bbeb0", + "Type": "AssortmentUnlockRule", + "entity": "5b6d9ce188a4501afc1b2b25", + "data": "5b6d9ce188a4501afc1b2b25" + }, + { + "_id": "668014ea2b680c65290bbeb1", + "Type": "AssortmentUnlockRule", + "entity": "5c0e66e2d174af02a96252f4", + "data": "5c0e66e2d174af02a96252f4" + }, + { + "_id": "668014ea2b680c65290bbeb2", + "Type": "AssortmentUnlockRule", + "entity": "5cc86832d7f00c000d3a6e6c", + "data": "5cc86832d7f00c000d3a6e6c" + }, + { + "_id": "668014ea2b680c65290bbeb3", + "Type": "AssortmentUnlockRule", + "entity": "5c17a7ed2e2216152142459c", + "data": "5c17a7ed2e2216152142459c" + }, + { + "_id": "668014ea2b680c65290bbeb4", + "Type": "AssortmentUnlockRule", + "entity": "584148f2245977598f1ad387", + "data": "584148f2245977598f1ad387" + }, + { + "_id": "668014ea2b680c65290bbeb5", + "Type": "AssortmentUnlockRule", + "entity": "5d5e7d28a4b936645d161203", + "data": "5d5e7d28a4b936645d161203" + }, + { + "_id": "668014ea2b680c65290bbeb6", + "Type": "AssortmentUnlockRule", + "entity": "5c1cd46f2e22164bef5cfedb", + "data": "5c1cd46f2e22164bef5cfedb" + }, + { + "_id": "668014ea2b680c65290bbeb7", + "Type": "AssortmentUnlockRule", + "entity": "5d02797c86f774203f38e30a", + "data": "5d02797c86f774203f38e30a" + }, + { + "_id": "668014ea2b680c65290bbeb8", + "Type": "AssortmentUnlockRule", + "entity": "5d23467086f77443f37fc602", + "data": "5d23467086f77443f37fc602" + }, + { + "_id": "668014ea2b680c65290bbeb9", + "Type": "AssortmentUnlockRule", + "entity": "5d4d617f86f77449c463d107", + "data": "5d4d617f86f77449c463d107" + }, + { + "_id": "668014ea2b680c65290bbeba", + "Type": "AssortmentUnlockRule", + "entity": "5aa7d193e5b5b000171d063f", + "data": "5aa7d193e5b5b000171d063f" + }, + { + "_id": "668014ea2b680c65290bbebb", + "Type": "AssortmentUnlockRule", + "entity": "5a1eaa87fcdbcb001865f75e", + "data": "5a1eaa87fcdbcb001865f75e" + }, + { + "_id": "668014ea2b680c65290bbebc", + "Type": "AssortmentUnlockRule", + "entity": "5af0454c86f7746bf20992e8", + "data": "5af0454c86f7746bf20992e8" + }, + { + "_id": "668014ea2b680c65290bbebd", + "Type": "AssortmentUnlockRule", + "entity": "5ea2a8e200685063ec28c05a", + "data": "5ea2a8e200685063ec28c05a" + }, + { + "_id": "668014ea2b680c65290bbebe", + "Type": "AssortmentUnlockRule", + "entity": "5d44069ca4b9361ebd26fc37", + "data": "5d44069ca4b9361ebd26fc37" + }, + { + "_id": "668014ea2b680c65290bbebf", + "Type": "AssortmentUnlockRule", + "entity": "5cbda392ae92155f3c17c39f", + "data": "5cbda392ae92155f3c17c39f" + }, + { + "_id": "668014ea2b680c65290bbec0", + "Type": "AssortmentUnlockRule", + "entity": "5dd800bde492226366631317", + "data": "5dd800bde492226366631317" + }, + { + "_id": "668014ea2b680c65290bbec1", + "Type": "AssortmentUnlockRule", + "entity": "5e00c1ad86f774747333222c", + "data": "5e00c1ad86f774747333222c" + }, + { + "_id": "668014ea2b680c65290bbec2", + "Type": "AssortmentUnlockRule", + "entity": "5dfa3d2b0dee1b22f862eade", + "data": "5dfa3d2b0dee1b22f862eade" + }, + { + "_id": "668014ea2b680c65290bbec3", + "Type": "AssortmentUnlockRule", + "entity": "5f60c74e3b85f6263c145586", + "data": "5f60c74e3b85f6263c145586" + }, + { + "_id": "668014ea2b680c65290bbec4", + "Type": "AssortmentUnlockRule", + "entity": "5df8a4d786f77412672a1e3b", + "data": "5df8a4d786f77412672a1e3b" + }, + { + "_id": "668014ea2b680c65290bbec5", + "Type": "AssortmentUnlockRule", + "entity": "5d383f5d86f7742a15793872", + "data": "5d383f5d86f7742a15793872" + }, + { + "_id": "668014ea2b680c65290bbec6", + "Type": "AssortmentUnlockRule", + "entity": "5dd800eae49222636663133b", + "data": "5dd800eae49222636663133b" + }, + { + "_id": "668014ea2b680c65290bbec7", + "Type": "AssortmentUnlockRule", + "entity": "5c793fb92e221644f31bfb64", + "data": "5c793fb92e221644f31bfb64" + }, + { + "_id": "668014ea2b680c65290bbec8", + "Type": "AssortmentUnlockRule", + "entity": "5d025cc1d7ad1a53845279ef", + "data": "5d025cc1d7ad1a53845279ef" + }, + { + "_id": "668014ea2b680c65290bbec9", + "Type": "AssortmentUnlockRule", + "entity": "5cbdc23eae9215001136a407", + "data": "5cbdc23eae9215001136a407" + }, + { + "_id": "668014ea2b680c65290bbeca", + "Type": "AssortmentUnlockRule", + "entity": "5d7b845786f7743c1e531da7", + "data": "5d7b845786f7743c1e531da7" + }, + { + "_id": "668014ea2b680c65290bbecb", + "Type": "AssortmentUnlockRule", + "entity": "5d383e1a86f7742a1468ce63", + "data": "5d383e1a86f7742a1468ce63" + }, + { + "_id": "668014ea2b680c65290bbecc", + "Type": "AssortmentUnlockRule", + "entity": "5e0354f786f77425b53eb6c5", + "data": "5e0354f786f77425b53eb6c5" + }, + { + "_id": "668014ea2b680c65290bbecd", + "Type": "AssortmentUnlockRule", + "entity": "5e0340ab86f7745bb7339235", + "data": "5e0340ab86f7745bb7339235" + }, + { + "_id": "668014ea2b680c65290bbece", + "Type": "AssortmentUnlockRule", + "entity": "5d38517786f7742a1468cf6a", + "data": "5d38517786f7742a1468cf6a" + }, + { + "_id": "668014ea2b680c65290bbecf", + "Type": "AssortmentUnlockRule", + "entity": "5c0e446786f7742013381639", + "data": "5c0e446786f7742013381639" + }, + { + "_id": "668014ea2b680c65290bbed0", + "Type": "AssortmentUnlockRule", + "entity": "5d383ee786f7742a15793860", + "data": "5d383ee786f7742a15793860" + }, + { + "_id": "668014ea2b680c65290bbed1", + "Type": "AssortmentUnlockRule", + "entity": "609e8540d5c319764c2bc2e9", + "data": "609e8540d5c319764c2bc2e9" + }, + { + "_id": "668014ea2b680c65290bbed2", + "Type": "AssortmentUnlockRule", + "entity": "64abd93857958b4249003418", + "data": "64abd93857958b4249003418" + }, + { + "_id": "668014ea2b680c65290bbed3", + "Type": "AssortmentUnlockRule", + "entity": "6065878ac9cf8012264142fd", + "data": "6065878ac9cf8012264142fd" + }, + { + "_id": "668014ea2b680c65290bbed4", + "Type": "AssortmentUnlockRule", + "entity": "618ba27d9008e4636a67f61d", + "data": "618ba27d9008e4636a67f61d" + }, + { + "_id": "668014ea2b680c65290bbed5", + "Type": "AssortmentUnlockRule", + "entity": "59e6920f86f77411d82aa167", + "data": "59e6920f86f77411d82aa167" + }, + { + "_id": "668014ea2b680c65290bbed6", + "Type": "AssortmentUnlockRule", + "entity": "624d7ae691f0160c7324c402", + "data": "624d7ae691f0160c7324c402" + }, + { + "_id": "668014ea2b680c65290bbed7", + "Type": "AssortmentUnlockRule", + "entity": "628cd624459354321c4b7fa2", + "data": "628cd624459354321c4b7fa2" + }, + { + "_id": "668014ea2b680c65290bbed8", + "Type": "AssortmentUnlockRule", + "entity": "5fd251c90d9c95034825edb5", + "data": "5fd251c90d9c95034825edb5" + }, + { + "_id": "668014ea2b680c65290bbed9", + "Type": "AssortmentUnlockRule", + "entity": "5fd25119dd870108a754a163", + "data": "5fd25119dd870108a754a163" + }, + { + "_id": "668014ea2b680c65290bbeda", + "Type": "AssortmentUnlockRule", + "entity": "619d26ccc7791e3af27ae3cd", + "data": "619d26ccc7791e3af27ae3cd" + }, + { + "_id": "668014ea2b680c65290bbedb", + "Type": "AssortmentUnlockRule", + "entity": "6130c43c67085e45ef1405a1", + "data": "6130c43c67085e45ef1405a1" + }, + { + "_id": "668014ea2b680c65290bbedc", + "Type": "AssortmentUnlockRule", + "entity": "60a283193cb70855c43a381d", + "data": "60a283193cb70855c43a381d" + }, + { + "_id": "668014ea2b680c65290bbedd", + "Type": "AssortmentUnlockRule", + "entity": "619b69037b9de8162902673e", + "data": "619b69037b9de8162902673e" + }, + { + "_id": "668014ea2b680c65290bbede", + "Type": "AssortmentUnlockRule", + "entity": "5656eb674bdc2d35148b457c", + "data": "5656eb674bdc2d35148b457c" + }, + { + "_id": "668014ea2b680c65290bbedf", + "Type": "AssortmentUnlockRule", + "entity": "60a3c70cde5f453f634816a3", + "data": "60a3c70cde5f453f634816a3" + }, + { + "_id": "668014ea2b680c65290bbee0", + "Type": "AssortmentUnlockRule", + "entity": "6193e590069d61205d490dd8", + "data": "6193e590069d61205d490dd8" + }, + { + "_id": "668014ea2b680c65290bbee1", + "Type": "AssortmentUnlockRule", + "entity": "60098ad7c2240c0fe85c570a", + "data": "60098ad7c2240c0fe85c570a" + }, + { + "_id": "668014ea2b680c65290bbee2", + "Type": "AssortmentUnlockRule", + "entity": "5ca2151486f774244a3b8d30", + "data": "5ca2151486f774244a3b8d30" + }, + { + "_id": "668014ea2b680c65290bbee3", + "Type": "AssortmentUnlockRule", + "entity": "6193e108c1982475fa2a7f16", + "data": "6193e108c1982475fa2a7f16" + }, + { + "_id": "668014ea2b680c65290bbee4", + "Type": "AssortmentUnlockRule", + "entity": "60479fb29c15b12b9a480fb0", + "data": "60479fb29c15b12b9a480fb0" + }, + { + "_id": "668014ea2b680c65290bbee5", + "Type": "AssortmentUnlockRule", + "entity": "5ede475b549eed7c6d5c18fb", + "data": "5ede475b549eed7c6d5c18fb" + }, + { + "_id": "668014ea2b680c65290bbee6", + "Type": "AssortmentUnlockRule", + "entity": "5e035eb586f774756048ec12", + "data": "5e035eb586f774756048ec12" + }, + { + "_id": "668014ea2b680c65290bbee7", + "Type": "AssortmentUnlockRule", + "entity": "5e85a9f4add9fe03027d9bf1", + "data": "5e85a9f4add9fe03027d9bf1" + }, + { + "_id": "668014ea2b680c65290bbee8", + "Type": "AssortmentUnlockRule", + "entity": "6038d614d10cbf667352dd44", + "data": "6038d614d10cbf667352dd44" + }, + { + "_id": "668014ea2b680c65290bbee9", + "Type": "AssortmentUnlockRule", + "entity": "64be79e2bf8412471d0d9bcc", + "data": "64be79e2bf8412471d0d9bcc" + }, + { + "_id": "668014ea2b680c65290bbeea", + "Type": "AssortmentUnlockRule", + "entity": "5d02797c86f774203f38e30a", + "data": "5d02797c86f774203f38e30a" + }, + { + "_id": "668014ea2b680c65290bbeeb", + "Type": "AssortmentUnlockRule", + "entity": "618ab04934aa2e47480fba2b", + "data": "618ab04934aa2e47480fba2b" + }, + { + "_id": "668014ea2b680c65290bbeec", + "Type": "AssortmentUnlockRule", + "entity": "615d8e9867085e45ef1409c6", + "data": "615d8e9867085e45ef1409c6" + }, + { + "_id": "668014ea2b680c65290bbeed", + "Type": "AssortmentUnlockRule", + "entity": "5c0e655586f774045612eeb2", + "data": "5c0e655586f774045612eeb2" + }, + { + "_id": "668014ea2b680c65290bbeee", + "Type": "AssortmentUnlockRule", + "entity": "5ef1ba28c64c5d0dfc0571a5", + "data": "5ef1ba28c64c5d0dfc0571a5" + }, + { + "_id": "668014ea2b680c65290bbeef", + "Type": "AssortmentUnlockRule", + "entity": "5fd251ee16cac650092f5d02", + "data": "5fd251ee16cac650092f5d02" + }, + { + "_id": "668014ea2b680c65290bbef0", + "Type": "AssortmentUnlockRule", + "entity": "64b8f7b5389d7ffd620ccba2", + "data": "64b8f7b5389d7ffd620ccba2" + }, + { + "_id": "668014ea2b680c65290bbef1", + "Type": "AssortmentUnlockRule", + "entity": "606f2696f2cb2e02a42aceb1", + "data": "606f2696f2cb2e02a42aceb1" + }, + { + "_id": "668014ea2b680c65290bbef2", + "Type": "AssortmentUnlockRule", + "entity": "60926df0132d4d12c81fd9df", + "data": "60926df0132d4d12c81fd9df" + }, + { + "_id": "668014ea2b680c65290bbef3", + "Type": "AssortmentUnlockRule", + "entity": "5c0d5ae286f7741e46554302", + "data": "5c0d5ae286f7741e46554302" + }, + { + "_id": "668014ea2b680c65290bbef4", + "Type": "AssortmentUnlockRule", + "entity": "5e21ca18e4d47f0da15e77dd", + "data": "5e21ca18e4d47f0da15e77dd" + }, + { + "_id": "668014ea2b680c65290bbef5", + "Type": "AssortmentUnlockRule", + "entity": "61962b617c6c7b169525f168", + "data": "61962b617c6c7b169525f168" + }, + { + "_id": "668014ea2b680c65290bbef6", + "Type": "AssortmentUnlockRule", + "entity": "60b7d76e2a3c79100f1979de", + "data": "60b7d76e2a3c79100f1979de" + }, + { + "_id": "668014ea2b680c65290bbef7", + "Type": "AssortmentUnlockRule", + "entity": "5f60b34a41e30a4ab12a6947", + "data": "5f60b34a41e30a4ab12a6947" + }, + { + "_id": "668014ea2b680c65290bbef8", + "Type": "AssortmentUnlockRule", + "entity": "5f06d6e1475d472556679d16", + "data": "5f06d6e1475d472556679d16" + }, + { + "_id": "668014ea2b680c65290bbef9", + "Type": "AssortmentUnlockRule", + "entity": "5d5d646386f7742797261fd9", + "data": "5d5d646386f7742797261fd9" + }, + { + "_id": "668014ea2b680c65290bbefa", + "Type": "AssortmentUnlockRule", + "entity": "5c1d0f4986f7744bb01837fa", + "data": "5c1d0f4986f7744bb01837fa" + }, + { + "_id": "668014ea2b680c65290bbefb", + "Type": "AssortmentUnlockRule", + "entity": "6087e663132d4d12c81fd96b", + "data": "6087e663132d4d12c81fd96b" + }, + { + "_id": "668014ea2b680c65290bbefc", + "Type": "AssortmentUnlockRule", + "entity": "619e61e70459e93c12392ba7", + "data": "619e61e70459e93c12392ba7" + }, + { + "_id": "668014ea2b680c65290bbefd", + "Type": "AssortmentUnlockRule", + "entity": "6130ca3fd92c473c77020dbd", + "data": "6130ca3fd92c473c77020dbd" + }, + { + "_id": "668014ea2b680c65290bbefe", + "Type": "AssortmentUnlockRule", + "entity": "62e7e7bbe6da9612f743f1e0", + "data": "62e7e7bbe6da9612f743f1e0" + }, + { + "_id": "668014ea2b680c65290bbeff", + "Type": "AssortmentUnlockRule", + "entity": "5656eb674bdc2d35148b457c", + "data": "5656eb674bdc2d35148b457c" + }, + { + "_id": "668014ea2b680c65290bbf00", + "Type": "AssortmentUnlockRule", + "entity": "64b6620258b5637e2d71a636", + "data": "64b6620258b5637e2d71a636" + }, + { + "_id": "668014ea2b680c65290bbf01", + "Type": "AssortmentUnlockRule", + "entity": "655df24fdf80b12750626d0a", + "data": "655df24fdf80b12750626d0a" + }, + { + "_id": "668014ea2b680c65290bbf02", + "Type": "AssortmentUnlockRule", + "entity": "62975de85c32d414f8797433", + "data": "62975de85c32d414f8797433" + }, + { + "_id": "668014ea2b680c65290bbf03", + "Type": "AssortmentUnlockRule", + "entity": "657eb3773271d8578610fe28", + "data": "657eb3773271d8578610fe28" + }, + { + "_id": "668014ea2b680c65290bbf04", + "Type": "AssortmentUnlockRule", + "entity": "590c5d4b86f774784e1b9c45", + "data": "590c5d4b86f774784e1b9c45" + }, + { + "_id": "668014ea2b680c65290bbf05", + "Type": "AssortmentUnlockRule", + "entity": "6389c7750ef44505c87f5996", + "data": "6389c7750ef44505c87f5996" + }, + { + "_id": "668014ea2b680c65290bbf06", + "Type": "AssortmentUnlockRule", + "entity": "6357c98711fb55120211f7e1", + "data": "6357c98711fb55120211f7e1" + }, + { + "_id": "668014ea2b680c65290bbf07", + "Type": "AssortmentUnlockRule", + "entity": "5c110624d174af029e69734c", + "data": "5c110624d174af029e69734c" + }, + { + "_id": "668014ea2b680c65290bbf08", + "Type": "AssortmentUnlockRule", + "entity": "63920105a83e15700a00f168", + "data": "63920105a83e15700a00f168" + }, + { + "_id": "668014ea2b680c65290bbf09", + "Type": "AssortmentUnlockRule", + "entity": "6357c98711fb55120211f7e1", + "data": "6357c98711fb55120211f7e1" + }, + { + "_id": "668014ea2b680c65290bbf0a", + "Type": "AssortmentUnlockRule", + "entity": "656f664200d62bcd2e024077", + "data": "656f664200d62bcd2e024077" + }, + { + "_id": "668014ea2b680c65290bbf0b", + "Type": "AssortmentUnlockRule", + "entity": "62973e474bb5ab23071c2a70", + "data": "62973e474bb5ab23071c2a70" + }, + { + "_id": "668014ea2b680c65290bbf0c", + "Type": "AssortmentUnlockRule", + "entity": "655746010177119f4a097ff7", + "data": "655746010177119f4a097ff7" + }, + { + "_id": "668014ea2b680c65290bbf0d", + "Type": "AssortmentUnlockRule", + "entity": "6570aead4d84f81fd002a033", + "data": "6570aead4d84f81fd002a033" + }, + { + "_id": "668014ea2b680c65290bbf0e", + "Type": "AssortmentUnlockRule", + "entity": "62a0a043cf4a99369e2624a5", + "data": "62a0a043cf4a99369e2624a5" + }, + { + "_id": "668014ea2b680c65290bbf0f", + "Type": "AssortmentUnlockRule", + "entity": "5e85a9f4add9fe03027d9bf1", + "data": "5e85a9f4add9fe03027d9bf1" + }, + { + "_id": "668014ea2b680c65290bbf10", + "Type": "AssortmentUnlockRule", + "entity": "5c0a840b86f7742ffa4f2482", + "data": "5c0a840b86f7742ffa4f2482" + }, + { + "_id": "668014ea2b680c65290bbf11", + "Type": "AssortmentUnlockRule", + "entity": "6389c7f115805221fb410466", + "data": "6389c7f115805221fb410466" + }, + { + "_id": "668014ea2b680c65290bbf12", + "Type": "AssortmentUnlockRule", + "entity": "656f611f94b480b8a500c0db", + "data": "656f611f94b480b8a500c0db" + }, + { + "_id": "668014ea2b680c65290bbf13", + "Type": "AssortmentUnlockRule", + "entity": "62e7e7bbe6da9612f743f1e0", + "data": "62e7e7bbe6da9612f743f1e0" + }, + { + "_id": "668014ea2b680c65290bbf14", + "Type": "AssortmentUnlockRule", + "entity": "64c1525e3319a1cf380c4e09", + "data": "64c1525e3319a1cf380c4e09" + }, + { + "_id": "668014ea2b680c65290bbf15", + "Type": "AssortmentUnlockRule", + "entity": "5a327f7c86f77475187e509a", + "data": "5a327f7c86f77475187e509a" + }, + { + "_id": "668014ea2b680c65290bbf16", + "Type": "AssortmentUnlockRule", + "entity": "5c0e530286f7747fa1419862", + "data": "5c0e530286f7747fa1419862" + }, + { + "_id": "668014ea2b680c65290bbf17", + "Type": "AssortmentUnlockRule", + "entity": "5ede475b549eed7c6d5c18fb", + "data": "5ede475b549eed7c6d5c18fb" + }, + { + "_id": "668014ea2b680c65290bbf18", + "Type": "AssortmentUnlockRule", + "entity": "5b2388675acfc4771e1be0be", + "data": "5b2388675acfc4771e1be0be" + }, + { + "_id": "668014ea2b680c65290bbf19", + "Type": "AssortmentUnlockRule", + "entity": "63fc44e2429a8a166c7f61e6", + "data": "63fc44e2429a8a166c7f61e6" + }, + { + "_id": "668014ea2b680c65290bbf1a", + "Type": "AssortmentUnlockRule", + "entity": "601aa3d2b2bcb34913271e6d", + "data": "601aa3d2b2bcb34913271e6d" + }, + { + "_id": "668014ea2b680c65290bbf1b", + "Type": "AssortmentUnlockRule", + "entity": "656fa8d700d62bcd2e024084", + "data": "656fa8d700d62bcd2e024084" + }, + { + "_id": "668014ea2b680c65290bbf1c", + "Type": "AssortmentUnlockRule", + "entity": "618ba27d9008e4636a67f61d", + "data": "618ba27d9008e4636a67f61d" + }, + { + "_id": "668014ea2b680c65290bbf1d", + "Type": "AssortmentUnlockRule", + "entity": "657089638db3adca1009f4ca", + "data": "657089638db3adca1009f4ca" + }, + { + "_id": "668014ea2b680c65290bbf1e", + "Type": "AssortmentUnlockRule", + "entity": "5efb0da7a29a85116f6ea05f", + "data": "5efb0da7a29a85116f6ea05f" + }, + { + "_id": "668014ea2b680c65290bbf1f", + "Type": "AssortmentUnlockRule", + "entity": "63986a9ab483a550805be5ee", + "data": "63986a9ab483a550805be5ee" + }, + { + "_id": "668014ea2b680c65290bbf20", + "Type": "AssortmentUnlockRule", + "entity": "656fa25e94b480b8a500c0e0", + "data": "656fa25e94b480b8a500c0e0" + }, + { + "_id": "668014ea2b680c65290bbf21", + "Type": "AssortmentUnlockRule", + "entity": "6389c85357baa773a825b356", + "data": "6389c85357baa773a825b356" + }, + { + "_id": "668014ea2b680c65290bbf22", + "Type": "AssortmentUnlockRule", + "entity": "64f8c5c6c8626c7d46040335", + "data": "64f8c5c6c8626c7d46040335" + }, + { + "_id": "668014ea2b680c65290bbf23", + "Type": "AssortmentUnlockRule", + "entity": "63fc44e2429a8a166c7f61e6", + "data": "63fc44e2429a8a166c7f61e6" + }, + { + "_id": "668014ea2b680c65290bbf24", + "Type": "AssortmentUnlockRule", + "entity": "65573fa5655447403702a816", + "data": "65573fa5655447403702a816" + } + ], + "maxToSendPlayer": 1 + }, + "HIDEOUTCAT": { "items": [ { "_id": "64b93751523fc8b45103fa54", @@ -6982,691 +7492,801 @@ "associatedEvent": "Promo", "collectionTimeHours": 72, "messageText": "Hideout cat.", - "maxToSendPlayer": 1 + "maxToSendPlayer": 1 }, - "KILLA": { - "items": [{ - "_id": "6659f82b5fddd28cb40363d1", - "_tpl": "619cbf7d23893217ec30b689", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "6659f82b5fddd28cb40363cf", - "slotId": "main" - }, { - "_id": "6659f82b5fddd28cb40363d3", - "_tpl": "57347ca924597744596b4e71", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "6659f82b5fddd28cb40363cf", - "slotId": "main" - } - ], + "KILLA": { + "items": [ + { + "_id": "6659f82b5fddd28cb40363d1", + "_tpl": "619cbf7d23893217ec30b689", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "6659f82b5fddd28cb40363cf", + "slotId": "main" + }, + { + "_id": "6659f82b5fddd28cb40363d3", + "_tpl": "57347ca924597744596b4e71", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "6659f82b5fddd28cb40363cf", + "slotId": "main" + } + ], "sender": "System", "messageText": "TarkovTV May 2024 gift", "collectionTimeHours": 48, "associatedEvent": "Promo", - "maxToSendPlayer": 1 + "maxToSendPlayer": 1 }, - "BITCOIN": { - "items": [{ - "_id": "6659fc6a77accffa490c0d3f", - "_tpl": "65290f395ae2ae97b80fdf2d", - "upd": { - "Repairable": { - "MaxDurability": 100, - "Durability": 100 - }, - "FireMode": { - "FireMode": "single" - } - }, - "parentId": "6659fc6a77accffa490c0d3e", - "slotId": "main" - }, { - "_id": "6659fc6a77accffa490c0d40", - "_tpl": "652911675ae2ae97b80fdf3c", - "parentId": "6659fc6a77accffa490c0d3f", - "slotId": "mod_pistol_grip" - }, { - "_id": "6659fc6a77accffa490c0d41", - "_tpl": "65293c38fc460e50a509cb25", - "parentId": "6659fc6a77accffa490c0d3f", - "slotId": "mod_magazine" - }, { - "_id": "6659fc6a77accffa490c0d42", - "_tpl": "6529119424cbe3c74a05e5bb", - "parentId": "6659fc6a77accffa490c0d3f", - "slotId": "mod_reciever" - }, { - "_id": "6659fc6a77accffa490c0d43", - "_tpl": "6567e751a715f85433025998", - "parentId": "6659fc6a77accffa490c0d42", - "slotId": "mod_scope" - }, { - "_id": "6659fc6a77accffa490c0d44", - "_tpl": "6567e7681265c8a131069b0f", - "parentId": "6659fc6a77accffa490c0d43", - "slotId": "mod_scope" - }, { - "_id": "6659fc6a77accffa490c0d45", - "_tpl": "652910565ae2ae97b80fdf35", - "parentId": "6659fc6a77accffa490c0d42", - "slotId": "mod_barrel" - }, { - "_id": "6659fc6a77accffa490c0d46", - "_tpl": "6529113b5ae2ae97b80fdf39", - "parentId": "6659fc6a77accffa490c0d45", - "slotId": "mod_muzzle" - }, { - "_id": "6659fc6a77accffa490c0d47", - "_tpl": "652911e650dc782999054b9d", - "parentId": "6659fc6a77accffa490c0d46", - "slotId": "mod_muzzle" - }, { - "_id": "6659fc6a77accffa490c0d48", - "_tpl": "652910bc24cbe3c74a05e5b9", - "parentId": "6659fc6a77accffa490c0d45", - "slotId": "mod_gas_block" - }, { - "_id": "6659fc6a77accffa490c0d49", - "_tpl": "652910ef50dc782999054b97", - "parentId": "6659fc6a77accffa490c0d42", - "slotId": "mod_handguard" - }, { - "_id": "6659fc6a77accffa490c0d4a", - "_tpl": "6529348224cbe3c74a05e5c4", - "parentId": "6659fc6a77accffa490c0d3f", - "slotId": "mod_stock_000" - }, { - "_id": "6659fc6a77accffa490c0d4b", - "_tpl": "6529366450dc782999054ba0", - "parentId": "6659fc6a77accffa490c0d4a", - "slotId": "mod_stock" - }, { - "_id": "6659fc6a77accffa490c0d4c", - "_tpl": "6529370c405a5f51dd023db8", - "parentId": "6659fc6a77accffa490c0d4b", - "slotId": "mod_stock_000" - }, { - "_id": "6659fc6a77accffa490c0d4d", - "_tpl": "6529109524cbe3c74a05e5b7", - "parentId": "6659fc6a77accffa490c0d3f", - "slotId": "mod_charge" - }, { - "_id": "6659fc6a77accffa490c0d4e", - "_tpl": "5c0e655586f774045612eeb2", - "parentId": "6659fc6a77accffa490c0d3e", - "slotId": "main" - }, { - "_id": "6659fc6a77accffa490c0d4f", - "_tpl": "6570e025615f54368b04fcb0", - "parentId": "6659fc6a77accffa490c0d4e", - "slotId": "Soft_armor_front" - }, { - "_id": "6659fc6a77accffa490c0d50", - "_tpl": "6570e0610b57c03ec90b96ef", - "parentId": "6659fc6a77accffa490c0d4e", - "slotId": "Soft_armor_back" - }, { - "_id": "6659fc6a77accffa490c0d51", - "_tpl": "656fad8c498d1b7e3e071da0", - "parentId": "6659fc6a77accffa490c0d4e", - "slotId": "Front_plate" - }, { - "_id": "6659fc6a77accffa490c0d52", - "_tpl": "656fad8c498d1b7e3e071da0", - "parentId": "6659fc6a77accffa490c0d4e", - "slotId": "Back_plate" - }, { - "_id": "6659fc6a77accffa490c0d54", - "_tpl": "628e4e576d783146b124c64d", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "6659fc6a77accffa490c0d3e", - "slotId": "main" - }, { - "_id": "6659fc6a77accffa490c0d56", - "_tpl": "628e4e576d783146b124c64d", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "6659fc6a77accffa490c0d3e", - "slotId": "main" - }, { - "_id": "6659fc6a77accffa490c0d57", - "_tpl": "5447a9cd4bdc2dbd208b4567", - "upd": { - "FireMode": { - "FireMode": "single" - } - }, - "parentId": "6659fc6a77accffa490c0d3e", - "slotId": "main" - }, { - "_id": "6659fc6a77accffa490c0d58", - "_tpl": "5cc9bcaed7f00c011c04e179", - "parentId": "6659fc6a77accffa490c0d57", - "slotId": "mod_pistol_grip" - }, { - "_id": "6659fc6a77accffa490c0d59", - "_tpl": "59c1383d86f774290a37e0ca", - "parentId": "6659fc6a77accffa490c0d57", - "slotId": "mod_magazine" - }, { - "_id": "6659fc6a77accffa490c0d5a", - "_tpl": "5d4405aaa4b9361e6a4e6bd3", - "parentId": "6659fc6a77accffa490c0d57", - "slotId": "mod_reciever" - }, { - "_id": "6659fc6a77accffa490c0d5b", - "_tpl": "59f9d81586f7744c7506ee62", - "parentId": "6659fc6a77accffa490c0d5a", - "slotId": "mod_scope" - }, { - "_id": "6659fc6a77accffa490c0d5c", - "_tpl": "55d35ee94bdc2d61338b4568", - "parentId": "6659fc6a77accffa490c0d5a", - "slotId": "mod_barrel" - }, { - "_id": "6659fc6a77accffa490c0d5d", - "_tpl": "5cff9e5ed7ad1a09407397d4", - "parentId": "6659fc6a77accffa490c0d5c", - "slotId": "mod_muzzle" - }, { - "_id": "6659fc6a77accffa490c0d5e", - "_tpl": "5d00ec68d7ad1a04a067e5be", - "parentId": "6659fc6a77accffa490c0d5c", - "slotId": "mod_gas_block" - }, { - "_id": "6659fc6a77accffa490c0d5f", - "_tpl": "5c78f2612e221600114c9f0d", - "parentId": "6659fc6a77accffa490c0d5a", - "slotId": "mod_handguard" - }, { - "_id": "6659fc6a77accffa490c0d60", - "_tpl": "5b7be4895acfc400170e2dd5", - "parentId": "6659fc6a77accffa490c0d5f", - "slotId": "mod_foregrip" - }, { - "_id": "6659fc6a77accffa490c0d61", - "_tpl": "588226d124597767ad33f787", - "parentId": "6659fc6a77accffa490c0d60", - "slotId": "mod_foregrip" - }, { - "_id": "6659fc6a77accffa490c0d62", - "_tpl": "5ba26b01d4351e0085325a51", - "parentId": "6659fc6a77accffa490c0d5f", - "slotId": "mod_sight_front" - }, { - "_id": "6659fc6a77accffa490c0d63", - "_tpl": "5c78f2882e22165df16b832e", - "parentId": "6659fc6a77accffa490c0d5f", - "slotId": "mod_muzzle" - }, { - "_id": "6659fc6a77accffa490c0d64", - "_tpl": "5b07dd285acfc4001754240d", - "parentId": "6659fc6a77accffa490c0d5f", - "slotId": "mod_tactical_002" - }, { - "_id": "6659fc6a77accffa490c0d65", - "_tpl": "5ba26b17d4351e00367f9bdd", - "parentId": "6659fc6a77accffa490c0d5a", - "slotId": "mod_sight_rear" - }, { - "_id": "6659fc6a77accffa490c0d66", - "_tpl": "5d120a10d7ad1a4e1026ba85", - "parentId": "6659fc6a77accffa490c0d57", - "slotId": "mod_stock" - }, { - "_id": "6659fc6a77accffa490c0d67", - "_tpl": "5d120a28d7ad1a1c8962e295", - "parentId": "6659fc6a77accffa490c0d66", - "slotId": "mod_stock" - }, { - "_id": "6659fc6a77accffa490c0d68", - "_tpl": "5d44334ba4b9362b346d1948", - "parentId": "6659fc6a77accffa490c0d57", - "slotId": "mod_charge" + "BITCOIN": { + "items": [ + { + "_id": "6659fc6a77accffa490c0d3f", + "_tpl": "65290f395ae2ae97b80fdf2d", + "upd": { + "Repairable": { + "MaxDurability": 100, + "Durability": 100 + }, + "FireMode": { + "FireMode": "single" } - ], + }, + "parentId": "6659fc6a77accffa490c0d3e", + "slotId": "main" + }, + { + "_id": "6659fc6a77accffa490c0d40", + "_tpl": "652911675ae2ae97b80fdf3c", + "parentId": "6659fc6a77accffa490c0d3f", + "slotId": "mod_pistol_grip" + }, + { + "_id": "6659fc6a77accffa490c0d41", + "_tpl": "65293c38fc460e50a509cb25", + "parentId": "6659fc6a77accffa490c0d3f", + "slotId": "mod_magazine" + }, + { + "_id": "6659fc6a77accffa490c0d42", + "_tpl": "6529119424cbe3c74a05e5bb", + "parentId": "6659fc6a77accffa490c0d3f", + "slotId": "mod_reciever" + }, + { + "_id": "6659fc6a77accffa490c0d43", + "_tpl": "6567e751a715f85433025998", + "parentId": "6659fc6a77accffa490c0d42", + "slotId": "mod_scope" + }, + { + "_id": "6659fc6a77accffa490c0d44", + "_tpl": "6567e7681265c8a131069b0f", + "parentId": "6659fc6a77accffa490c0d43", + "slotId": "mod_scope" + }, + { + "_id": "6659fc6a77accffa490c0d45", + "_tpl": "652910565ae2ae97b80fdf35", + "parentId": "6659fc6a77accffa490c0d42", + "slotId": "mod_barrel" + }, + { + "_id": "6659fc6a77accffa490c0d46", + "_tpl": "6529113b5ae2ae97b80fdf39", + "parentId": "6659fc6a77accffa490c0d45", + "slotId": "mod_muzzle" + }, + { + "_id": "6659fc6a77accffa490c0d47", + "_tpl": "652911e650dc782999054b9d", + "parentId": "6659fc6a77accffa490c0d46", + "slotId": "mod_muzzle" + }, + { + "_id": "6659fc6a77accffa490c0d48", + "_tpl": "652910bc24cbe3c74a05e5b9", + "parentId": "6659fc6a77accffa490c0d45", + "slotId": "mod_gas_block" + }, + { + "_id": "6659fc6a77accffa490c0d49", + "_tpl": "652910ef50dc782999054b97", + "parentId": "6659fc6a77accffa490c0d42", + "slotId": "mod_handguard" + }, + { + "_id": "6659fc6a77accffa490c0d4a", + "_tpl": "6529348224cbe3c74a05e5c4", + "parentId": "6659fc6a77accffa490c0d3f", + "slotId": "mod_stock_000" + }, + { + "_id": "6659fc6a77accffa490c0d4b", + "_tpl": "6529366450dc782999054ba0", + "parentId": "6659fc6a77accffa490c0d4a", + "slotId": "mod_stock" + }, + { + "_id": "6659fc6a77accffa490c0d4c", + "_tpl": "6529370c405a5f51dd023db8", + "parentId": "6659fc6a77accffa490c0d4b", + "slotId": "mod_stock_000" + }, + { + "_id": "6659fc6a77accffa490c0d4d", + "_tpl": "6529109524cbe3c74a05e5b7", + "parentId": "6659fc6a77accffa490c0d3f", + "slotId": "mod_charge" + }, + { + "_id": "6659fc6a77accffa490c0d4e", + "_tpl": "5c0e655586f774045612eeb2", + "parentId": "6659fc6a77accffa490c0d3e", + "slotId": "main" + }, + { + "_id": "6659fc6a77accffa490c0d4f", + "_tpl": "6570e025615f54368b04fcb0", + "parentId": "6659fc6a77accffa490c0d4e", + "slotId": "Soft_armor_front" + }, + { + "_id": "6659fc6a77accffa490c0d50", + "_tpl": "6570e0610b57c03ec90b96ef", + "parentId": "6659fc6a77accffa490c0d4e", + "slotId": "Soft_armor_back" + }, + { + "_id": "6659fc6a77accffa490c0d51", + "_tpl": "656fad8c498d1b7e3e071da0", + "parentId": "6659fc6a77accffa490c0d4e", + "slotId": "Front_plate" + }, + { + "_id": "6659fc6a77accffa490c0d52", + "_tpl": "656fad8c498d1b7e3e071da0", + "parentId": "6659fc6a77accffa490c0d4e", + "slotId": "Back_plate" + }, + { + "_id": "6659fc6a77accffa490c0d54", + "_tpl": "628e4e576d783146b124c64d", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "6659fc6a77accffa490c0d3e", + "slotId": "main" + }, + { + "_id": "6659fc6a77accffa490c0d56", + "_tpl": "628e4e576d783146b124c64d", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "6659fc6a77accffa490c0d3e", + "slotId": "main" + }, + { + "_id": "6659fc6a77accffa490c0d57", + "_tpl": "5447a9cd4bdc2dbd208b4567", + "upd": { + "FireMode": { + "FireMode": "single" + } + }, + "parentId": "6659fc6a77accffa490c0d3e", + "slotId": "main" + }, + { + "_id": "6659fc6a77accffa490c0d58", + "_tpl": "5cc9bcaed7f00c011c04e179", + "parentId": "6659fc6a77accffa490c0d57", + "slotId": "mod_pistol_grip" + }, + { + "_id": "6659fc6a77accffa490c0d59", + "_tpl": "59c1383d86f774290a37e0ca", + "parentId": "6659fc6a77accffa490c0d57", + "slotId": "mod_magazine" + }, + { + "_id": "6659fc6a77accffa490c0d5a", + "_tpl": "5d4405aaa4b9361e6a4e6bd3", + "parentId": "6659fc6a77accffa490c0d57", + "slotId": "mod_reciever" + }, + { + "_id": "6659fc6a77accffa490c0d5b", + "_tpl": "59f9d81586f7744c7506ee62", + "parentId": "6659fc6a77accffa490c0d5a", + "slotId": "mod_scope" + }, + { + "_id": "6659fc6a77accffa490c0d5c", + "_tpl": "55d35ee94bdc2d61338b4568", + "parentId": "6659fc6a77accffa490c0d5a", + "slotId": "mod_barrel" + }, + { + "_id": "6659fc6a77accffa490c0d5d", + "_tpl": "5cff9e5ed7ad1a09407397d4", + "parentId": "6659fc6a77accffa490c0d5c", + "slotId": "mod_muzzle" + }, + { + "_id": "6659fc6a77accffa490c0d5e", + "_tpl": "5d00ec68d7ad1a04a067e5be", + "parentId": "6659fc6a77accffa490c0d5c", + "slotId": "mod_gas_block" + }, + { + "_id": "6659fc6a77accffa490c0d5f", + "_tpl": "5c78f2612e221600114c9f0d", + "parentId": "6659fc6a77accffa490c0d5a", + "slotId": "mod_handguard" + }, + { + "_id": "6659fc6a77accffa490c0d60", + "_tpl": "5b7be4895acfc400170e2dd5", + "parentId": "6659fc6a77accffa490c0d5f", + "slotId": "mod_foregrip" + }, + { + "_id": "6659fc6a77accffa490c0d61", + "_tpl": "588226d124597767ad33f787", + "parentId": "6659fc6a77accffa490c0d60", + "slotId": "mod_foregrip" + }, + { + "_id": "6659fc6a77accffa490c0d62", + "_tpl": "5ba26b01d4351e0085325a51", + "parentId": "6659fc6a77accffa490c0d5f", + "slotId": "mod_sight_front" + }, + { + "_id": "6659fc6a77accffa490c0d63", + "_tpl": "5c78f2882e22165df16b832e", + "parentId": "6659fc6a77accffa490c0d5f", + "slotId": "mod_muzzle" + }, + { + "_id": "6659fc6a77accffa490c0d64", + "_tpl": "5b07dd285acfc4001754240d", + "parentId": "6659fc6a77accffa490c0d5f", + "slotId": "mod_tactical_002" + }, + { + "_id": "6659fc6a77accffa490c0d65", + "_tpl": "5ba26b17d4351e00367f9bdd", + "parentId": "6659fc6a77accffa490c0d5a", + "slotId": "mod_sight_rear" + }, + { + "_id": "6659fc6a77accffa490c0d66", + "_tpl": "5d120a10d7ad1a4e1026ba85", + "parentId": "6659fc6a77accffa490c0d57", + "slotId": "mod_stock" + }, + { + "_id": "6659fc6a77accffa490c0d67", + "_tpl": "5d120a28d7ad1a1c8962e295", + "parentId": "6659fc6a77accffa490c0d66", + "slotId": "mod_stock" + }, + { + "_id": "6659fc6a77accffa490c0d68", + "_tpl": "5d44334ba4b9362b346d1948", + "parentId": "6659fc6a77accffa490c0d57", + "slotId": "mod_charge" + } + ], "sender": "System", "messageText": "TarkovTV May 2024 gift", "collectionTimeHours": 48, "associatedEvent": "Promo", - "maxToSendPlayer": 1 + "maxToSendPlayer": 1 }, - "GROUNDZERO2": { - "items": [{ - "_id": "6659fef6c7faaa6180043384", - "_tpl": "5ab8e79e86f7742d8b372e78", - "parentId": "6659fef6c7faaa6180043383", - "slotId": "main" - }, { - "_id": "6659fef6c7faaa6180043385", - "_tpl": "65732688d9d89ff7ac0d9c4c", - "parentId": "6659fef6c7faaa6180043384", - "slotId": "Soft_armor_front" - }, { - "_id": "6659fef6c7faaa6180043386", - "_tpl": "657326978c1cc6dcd9098b56", - "parentId": "6659fef6c7faaa6180043384", - "slotId": "Soft_armor_back" - }, { - "_id": "6659fef6c7faaa6180043387", - "_tpl": "657326a28c1cc6dcd9098b5a", - "parentId": "6659fef6c7faaa6180043384", - "slotId": "Soft_armor_left" - }, { - "_id": "6659fef6c7faaa6180043388", - "_tpl": "657326b08c1cc6dcd9098b5e", - "parentId": "6659fef6c7faaa6180043384", - "slotId": "soft_armor_right" - }, { - "_id": "6659fef6c7faaa6180043389", - "_tpl": "657326bc5d3a3129fb05f36b", - "parentId": "6659fef6c7faaa6180043384", - "slotId": "Collar" - }, { - "_id": "6659fef6c7faaa618004338a", - "_tpl": "656f611f94b480b8a500c0db", - "parentId": "6659fef6c7faaa6180043384", - "slotId": "Front_plate" - }, { - "_id": "6659fef6c7faaa618004338b", - "_tpl": "65573fa5655447403702a816", - "parentId": "6659fef6c7faaa6180043384", - "slotId": "Back_plate" - }, { - "_id": "6659fef6c7faaa618004338c", - "_tpl": "60a3c68c37ea821725773ef5", - "parentId": "6659fef6c7faaa6180043383", - "slotId": "main" - }, { - "_id": "6659fef6c7faaa618004338d", - "_tpl": "65733312ca0ca984940a2d53", - "parentId": "6659fef6c7faaa618004338c", - "slotId": "Soft_armor_front" - }, { - "_id": "6659fef6c7faaa618004338e", - "_tpl": "657333232cc8dfad2c0a3d97", - "parentId": "6659fef6c7faaa618004338c", - "slotId": "Soft_armor_back" - }, { - "_id": "6659fef6c7faaa618004338f", - "_tpl": "657333302cc8dfad2c0a3d9b", - "parentId": "6659fef6c7faaa618004338c", - "slotId": "Soft_armor_left" - }, { - "_id": "6659fef6c7faaa6180043390", - "_tpl": "6573333eca0ca984940a2d57", - "parentId": "6659fef6c7faaa618004338c", - "slotId": "soft_armor_right" - }, { - "_id": "6659fef6c7faaa6180043391", - "_tpl": "6573334aca0ca984940a2d5b", - "parentId": "6659fef6c7faaa618004338c", - "slotId": "Collar" - }, { - "_id": "6659fef6c7faaa6180043392", - "_tpl": "65733375b7a8d286530e3dd7", - "parentId": "6659fef6c7faaa618004338c", - "slotId": "Shoulder_l" - }, { - "_id": "6659fef6c7faaa6180043393", - "_tpl": "6573337f2cc8dfad2c0a3da7", - "parentId": "6659fef6c7faaa618004338c", - "slotId": "Shoulder_r" - }, { - "_id": "6659fef6c7faaa6180043394", - "_tpl": "656fa53d94b480b8a500c0e4", - "parentId": "6659fef6c7faaa618004338c", - "slotId": "Front_plate" - }, { - "_id": "6659fef6c7faaa6180043395", - "_tpl": "656fa53d94b480b8a500c0e4", - "parentId": "6659fef6c7faaa618004338c", - "slotId": "Back_plate" - }, { - "_id": "6659fef6c7faaa6180043396", - "_tpl": "6557458f83942d705f0c4962", - "parentId": "6659fef6c7faaa618004338c", - "slotId": "Left_side_plate" - }, { - "_id": "6659fef6c7faaa6180043397", - "_tpl": "6557458f83942d705f0c4962", - "parentId": "6659fef6c7faaa618004338c", - "slotId": "Right_side_plate" - }, { - "_id": "6659fef6c7faaa6180043398", - "_tpl": "5b40e2bc5acfc40016388216", - "parentId": "6659fef6c7faaa6180043383", - "slotId": "main" - }, { - "_id": "6659fef6c7faaa6180043399", - "_tpl": "657112234269e9a568089eac", - "parentId": "6659fef6c7faaa6180043398", - "slotId": "Helmet_top" - }, { - "_id": "6659fef6c7faaa618004339a", - "_tpl": "657112a4818110db4600aa66", - "parentId": "6659fef6c7faaa6180043398", - "slotId": "Helmet_back" - }, { - "_id": "6659fef6c7faaa618004339b", - "_tpl": "657112ce22996eaf110881fb", - "parentId": "6659fef6c7faaa6180043398", - "slotId": "Helmet_ears" - }, { - "_id": "6659fef6c7faaa618004339d", - "_tpl": "5e2af55f86f7746d4159f07c", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "6659fef6c7faaa6180043383", - "slotId": "main" - }, { - "_id": "6659fef6c7faaa618004339e", - "_tpl": "5b40e2bc5acfc40016388216", - "parentId": "6659fef6c7faaa6180043383", - "slotId": "main" - }, { - "_id": "6659fef6c7faaa618004339f", - "_tpl": "657112234269e9a568089eac", - "parentId": "6659fef6c7faaa618004339e", - "slotId": "Helmet_top" - }, { - "_id": "6659fef6c7faaa61800433a0", - "_tpl": "657112a4818110db4600aa66", - "parentId": "6659fef6c7faaa618004339e", - "slotId": "Helmet_back" - }, { - "_id": "6659fef6c7faaa61800433a1", - "_tpl": "657112ce22996eaf110881fb", - "parentId": "6659fef6c7faaa618004339e", - "slotId": "Helmet_ears" - } - ], + "GROUNDZERO2": { + "items": [ + { + "_id": "6659fef6c7faaa6180043384", + "_tpl": "5ab8e79e86f7742d8b372e78", + "parentId": "6659fef6c7faaa6180043383", + "slotId": "main" + }, + { + "_id": "6659fef6c7faaa6180043385", + "_tpl": "65732688d9d89ff7ac0d9c4c", + "parentId": "6659fef6c7faaa6180043384", + "slotId": "Soft_armor_front" + }, + { + "_id": "6659fef6c7faaa6180043386", + "_tpl": "657326978c1cc6dcd9098b56", + "parentId": "6659fef6c7faaa6180043384", + "slotId": "Soft_armor_back" + }, + { + "_id": "6659fef6c7faaa6180043387", + "_tpl": "657326a28c1cc6dcd9098b5a", + "parentId": "6659fef6c7faaa6180043384", + "slotId": "Soft_armor_left" + }, + { + "_id": "6659fef6c7faaa6180043388", + "_tpl": "657326b08c1cc6dcd9098b5e", + "parentId": "6659fef6c7faaa6180043384", + "slotId": "soft_armor_right" + }, + { + "_id": "6659fef6c7faaa6180043389", + "_tpl": "657326bc5d3a3129fb05f36b", + "parentId": "6659fef6c7faaa6180043384", + "slotId": "Collar" + }, + { + "_id": "6659fef6c7faaa618004338a", + "_tpl": "656f611f94b480b8a500c0db", + "parentId": "6659fef6c7faaa6180043384", + "slotId": "Front_plate" + }, + { + "_id": "6659fef6c7faaa618004338b", + "_tpl": "65573fa5655447403702a816", + "parentId": "6659fef6c7faaa6180043384", + "slotId": "Back_plate" + }, + { + "_id": "6659fef6c7faaa618004338c", + "_tpl": "60a3c68c37ea821725773ef5", + "parentId": "6659fef6c7faaa6180043383", + "slotId": "main" + }, + { + "_id": "6659fef6c7faaa618004338d", + "_tpl": "65733312ca0ca984940a2d53", + "parentId": "6659fef6c7faaa618004338c", + "slotId": "Soft_armor_front" + }, + { + "_id": "6659fef6c7faaa618004338e", + "_tpl": "657333232cc8dfad2c0a3d97", + "parentId": "6659fef6c7faaa618004338c", + "slotId": "Soft_armor_back" + }, + { + "_id": "6659fef6c7faaa618004338f", + "_tpl": "657333302cc8dfad2c0a3d9b", + "parentId": "6659fef6c7faaa618004338c", + "slotId": "Soft_armor_left" + }, + { + "_id": "6659fef6c7faaa6180043390", + "_tpl": "6573333eca0ca984940a2d57", + "parentId": "6659fef6c7faaa618004338c", + "slotId": "soft_armor_right" + }, + { + "_id": "6659fef6c7faaa6180043391", + "_tpl": "6573334aca0ca984940a2d5b", + "parentId": "6659fef6c7faaa618004338c", + "slotId": "Collar" + }, + { + "_id": "6659fef6c7faaa6180043392", + "_tpl": "65733375b7a8d286530e3dd7", + "parentId": "6659fef6c7faaa618004338c", + "slotId": "Shoulder_l" + }, + { + "_id": "6659fef6c7faaa6180043393", + "_tpl": "6573337f2cc8dfad2c0a3da7", + "parentId": "6659fef6c7faaa618004338c", + "slotId": "Shoulder_r" + }, + { + "_id": "6659fef6c7faaa6180043394", + "_tpl": "656fa53d94b480b8a500c0e4", + "parentId": "6659fef6c7faaa618004338c", + "slotId": "Front_plate" + }, + { + "_id": "6659fef6c7faaa6180043395", + "_tpl": "656fa53d94b480b8a500c0e4", + "parentId": "6659fef6c7faaa618004338c", + "slotId": "Back_plate" + }, + { + "_id": "6659fef6c7faaa6180043396", + "_tpl": "6557458f83942d705f0c4962", + "parentId": "6659fef6c7faaa618004338c", + "slotId": "Left_side_plate" + }, + { + "_id": "6659fef6c7faaa6180043397", + "_tpl": "6557458f83942d705f0c4962", + "parentId": "6659fef6c7faaa618004338c", + "slotId": "Right_side_plate" + }, + { + "_id": "6659fef6c7faaa6180043398", + "_tpl": "5b40e2bc5acfc40016388216", + "parentId": "6659fef6c7faaa6180043383", + "slotId": "main" + }, + { + "_id": "6659fef6c7faaa6180043399", + "_tpl": "657112234269e9a568089eac", + "parentId": "6659fef6c7faaa6180043398", + "slotId": "Helmet_top" + }, + { + "_id": "6659fef6c7faaa618004339a", + "_tpl": "657112a4818110db4600aa66", + "parentId": "6659fef6c7faaa6180043398", + "slotId": "Helmet_back" + }, + { + "_id": "6659fef6c7faaa618004339b", + "_tpl": "657112ce22996eaf110881fb", + "parentId": "6659fef6c7faaa6180043398", + "slotId": "Helmet_ears" + }, + { + "_id": "6659fef6c7faaa618004339d", + "_tpl": "5e2af55f86f7746d4159f07c", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "6659fef6c7faaa6180043383", + "slotId": "main" + }, + { + "_id": "6659fef6c7faaa618004339e", + "_tpl": "5b40e2bc5acfc40016388216", + "parentId": "6659fef6c7faaa6180043383", + "slotId": "main" + }, + { + "_id": "6659fef6c7faaa618004339f", + "_tpl": "657112234269e9a568089eac", + "parentId": "6659fef6c7faaa618004339e", + "slotId": "Helmet_top" + }, + { + "_id": "6659fef6c7faaa61800433a0", + "_tpl": "657112a4818110db4600aa66", + "parentId": "6659fef6c7faaa618004339e", + "slotId": "Helmet_back" + }, + { + "_id": "6659fef6c7faaa61800433a1", + "_tpl": "657112ce22996eaf110881fb", + "parentId": "6659fef6c7faaa618004339e", + "slotId": "Helmet_ears" + } + ], "sender": "System", "messageText": "TarkovTV May 2024 gift", "collectionTimeHours": 48, "associatedEvent": "Promo", - "maxToSendPlayer": 1 + "maxToSendPlayer": 1 }, - "OBDOLBOS": { - "items": [{ - "_id": "665a02824c1d50c3810a27f5", - "_tpl": "5c0e530286f7747fa1419862", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "665a02824c1d50c3810a27f3", - "slotId": "main" - }, { - "_id": "665a02824c1d50c3810a27f7", - "_tpl": "5c0e530286f7747fa1419862", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "665a02824c1d50c3810a27f3", - "slotId": "main" - }, { - "_id": "665a02824c1d50c3810a27f9", - "_tpl": "5c0e533786f7747fa23f4d47", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "665a02824c1d50c3810a27f3", - "slotId": "main" - }, { - "_id": "665a02824c1d50c3810a27fb", - "_tpl": "5c0e533786f7747fa23f4d47", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "665a02824c1d50c3810a27f3", - "slotId": "main" - }, { - "_id": "665a02824c1d50c3810a27fd", - "_tpl": "5ed5160a87bb8443d10680b5", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "665a02824c1d50c3810a27f3", - "slotId": "main" - }, { - "_id": "665a02824c1d50c3810a27ff", - "_tpl": "5ed5160a87bb8443d10680b5", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "665a02824c1d50c3810a27f3", - "slotId": "main" - }, { - "_id": "665a02824c1d50c3810a2801", - "_tpl": "637b620db7afa97bfc3d7009", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "665a02824c1d50c3810a27f3", - "slotId": "main" - }, { - "_id": "665a02824c1d50c3810a2803", - "_tpl": "637b620db7afa97bfc3d7009", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "665a02824c1d50c3810a27f3", - "slotId": "main" - }, { - "_id": "665a02824c1d50c3810a2805", - "_tpl": "5c0e534186f7747fa1419867", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "665a02824c1d50c3810a27f3", - "slotId": "main" - }, { - "_id": "665a02824c1d50c3810a2807", - "_tpl": "5c0e534186f7747fa1419867", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "665a02824c1d50c3810a27f3", - "slotId": "main" - }, { - "_id": "665a02824c1d50c3810a2809", - "_tpl": "637b6251104668754b72f8f9", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "665a02824c1d50c3810a27f3", - "slotId": "main" - }, { - "_id": "665a02824c1d50c3810a280b", - "_tpl": "637b6251104668754b72f8f9", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "665a02824c1d50c3810a27f3", - "slotId": "main" - }, { - "_id": "665a02824c1d50c3810a280d", - "_tpl": "5751a89d24597722aa0e8db0", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "665a02824c1d50c3810a27f3", - "slotId": "main" - }, { - "_id": "665a02824c1d50c3810a280f", - "_tpl": "5751a89d24597722aa0e8db0", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "665a02824c1d50c3810a27f3", - "slotId": "main" - }, { - "_id": "665a02824c1d50c3810a2811", - "_tpl": "5ed51652f6c34d2cc26336a1", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "665a02824c1d50c3810a27f3", - "slotId": "main" - }, { - "_id": "665a02824c1d50c3810a2813", - "_tpl": "5ed51652f6c34d2cc26336a1", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "665a02824c1d50c3810a27f3", - "slotId": "main" - } - ], + "OBDOLBOS": { + "items": [ + { + "_id": "665a02824c1d50c3810a27f5", + "_tpl": "5c0e530286f7747fa1419862", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "665a02824c1d50c3810a27f3", + "slotId": "main" + }, + { + "_id": "665a02824c1d50c3810a27f7", + "_tpl": "5c0e530286f7747fa1419862", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "665a02824c1d50c3810a27f3", + "slotId": "main" + }, + { + "_id": "665a02824c1d50c3810a27f9", + "_tpl": "5c0e533786f7747fa23f4d47", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "665a02824c1d50c3810a27f3", + "slotId": "main" + }, + { + "_id": "665a02824c1d50c3810a27fb", + "_tpl": "5c0e533786f7747fa23f4d47", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "665a02824c1d50c3810a27f3", + "slotId": "main" + }, + { + "_id": "665a02824c1d50c3810a27fd", + "_tpl": "5ed5160a87bb8443d10680b5", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "665a02824c1d50c3810a27f3", + "slotId": "main" + }, + { + "_id": "665a02824c1d50c3810a27ff", + "_tpl": "5ed5160a87bb8443d10680b5", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "665a02824c1d50c3810a27f3", + "slotId": "main" + }, + { + "_id": "665a02824c1d50c3810a2801", + "_tpl": "637b620db7afa97bfc3d7009", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "665a02824c1d50c3810a27f3", + "slotId": "main" + }, + { + "_id": "665a02824c1d50c3810a2803", + "_tpl": "637b620db7afa97bfc3d7009", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "665a02824c1d50c3810a27f3", + "slotId": "main" + }, + { + "_id": "665a02824c1d50c3810a2805", + "_tpl": "5c0e534186f7747fa1419867", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "665a02824c1d50c3810a27f3", + "slotId": "main" + }, + { + "_id": "665a02824c1d50c3810a2807", + "_tpl": "5c0e534186f7747fa1419867", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "665a02824c1d50c3810a27f3", + "slotId": "main" + }, + { + "_id": "665a02824c1d50c3810a2809", + "_tpl": "637b6251104668754b72f8f9", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "665a02824c1d50c3810a27f3", + "slotId": "main" + }, + { + "_id": "665a02824c1d50c3810a280b", + "_tpl": "637b6251104668754b72f8f9", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "665a02824c1d50c3810a27f3", + "slotId": "main" + }, + { + "_id": "665a02824c1d50c3810a280d", + "_tpl": "5751a89d24597722aa0e8db0", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "665a02824c1d50c3810a27f3", + "slotId": "main" + }, + { + "_id": "665a02824c1d50c3810a280f", + "_tpl": "5751a89d24597722aa0e8db0", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "665a02824c1d50c3810a27f3", + "slotId": "main" + }, + { + "_id": "665a02824c1d50c3810a2811", + "_tpl": "5ed51652f6c34d2cc26336a1", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "665a02824c1d50c3810a27f3", + "slotId": "main" + }, + { + "_id": "665a02824c1d50c3810a2813", + "_tpl": "5ed51652f6c34d2cc26336a1", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "665a02824c1d50c3810a27f3", + "slotId": "main" + } + ], "sender": "System", "messageText": "TarkovTV May 2024 gift", "collectionTimeHours": 48, "associatedEvent": "Promo", - "maxToSendPlayer": 1 + "maxToSendPlayer": 1 }, - "THICC": { - "items": [{ - "_id": "665a06ac85c6ab387e0afba5", - "_tpl": "5c12613b86f7743bbe2c3f76", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "665a06ac85c6ab387e0afba3", - "slotId": "main" - }, { - "_id": "665a06ac85c6ab387e0afba7", - "_tpl": "59faff1d86f7746c51718c9c", - "upd": { - "StackObjectsCount": 1 - }, - "parentId": "665a06ac85c6ab387e0afba3", - "slotId": "main" - }, { - "_id": "665a06ac85c6ab387e0afba8", - "_tpl": "64637076203536ad5600c990", - "upd": { - "Repairable": { - "Durability": 100, - "MaxDurability": 100 - } - }, - "parentId": "665a06ac85c6ab387e0afba3", - "slotId": "main" - }, { - "_id": "665a06ac85c6ab387e0afba9", - "_tpl": "646371779f5f0ea59a04c204", - "parentId": "665a06ac85c6ab387e0afba8", - "slotId": "mod_pistolgrip" - }, { - "_id": "665a06ac85c6ab387e0afbaa", - "_tpl": "646371faf2404ab67905c8e9", - "parentId": "665a06ac85c6ab387e0afba8", - "slotId": "mod_barrel" - }, { - "_id": "665a06ac85c6ab387e0afbab", - "_tpl": "6492efb8cfcf7c89e701abf3", - "parentId": "665a06ac85c6ab387e0afbaa", - "slotId": "mod_muzzle" - }, { - "_id": "665a06ac85c6ab387e0afbac", - "_tpl": "646372518610c40fc20204e8", - "parentId": "665a06ac85c6ab387e0afba8", - "slotId": "mod_magazine" - }, { - "_id": "665a06ac85c6ab387e0afbad", - "_tpl": "646371a9f2404ab67905c8e6", - "parentId": "665a06ac85c6ab387e0afba8", - "slotId": "mod_stock" - }, { - "_id": "665a06ac85c6ab387e0afbae", - "_tpl": "6464d870bb2c580352070cc4", - "parentId": "665a06ac85c6ab387e0afba8", - "slotId": "mod_bipod" - }, { - "_id": "665a06ac85c6ab387e0afbaf", - "_tpl": "6492fb8253acae0af00a29b6", - "parentId": "665a06ac85c6ab387e0afba8", - "slotId": "mod_sight_rear" - }, { - "_id": "665a06ac85c6ab387e0afbb0", - "_tpl": "60a283193cb70855c43a381d", - "parentId": "665a06ac85c6ab387e0afba3", - "slotId": "main" - }, { - "_id": "665a06ac85c6ab387e0afbb1", - "_tpl": "6575d561b15fef3dd4051670", - "parentId": "665a06ac85c6ab387e0afbb0", - "slotId": "Soft_armor_front" - }, { - "_id": "665a06ac85c6ab387e0afbb2", - "_tpl": "6575d56b16c2762fba005818", - "parentId": "665a06ac85c6ab387e0afbb0", - "slotId": "Soft_armor_back" - }, { - "_id": "665a06ac85c6ab387e0afbb3", - "_tpl": "6575d57a16c2762fba00581c", - "parentId": "665a06ac85c6ab387e0afbb0", - "slotId": "Soft_armor_left" - }, { - "_id": "665a06ac85c6ab387e0afbb4", - "_tpl": "6575d589b15fef3dd4051674", - "parentId": "665a06ac85c6ab387e0afbb0", - "slotId": "soft_armor_right" - }, { - "_id": "665a06ac85c6ab387e0afbb5", - "_tpl": "6575d598b15fef3dd4051678", - "parentId": "665a06ac85c6ab387e0afbb0", - "slotId": "Collar" - }, { - "_id": "665a06ac85c6ab387e0afbb6", - "_tpl": "6575d5b316c2762fba005824", - "parentId": "665a06ac85c6ab387e0afbb0", - "slotId": "Shoulder_l" - }, { - "_id": "665a06ac85c6ab387e0afbb7", - "_tpl": "6575d5bd16c2762fba005828", - "parentId": "665a06ac85c6ab387e0afbb0", - "slotId": "Shoulder_r" - }, { - "_id": "665a06ac85c6ab387e0afbb8", - "_tpl": "6575d5a616c2762fba005820", - "parentId": "665a06ac85c6ab387e0afbb0", - "slotId": "Groin" - }, { - "_id": "665a06ac85c6ab387e0afbb9", - "_tpl": "656fa61e94b480b8a500c0e8", - "parentId": "665a06ac85c6ab387e0afbb0", - "slotId": "Front_plate" - }, { - "_id": "665a06ac85c6ab387e0afbba", - "_tpl": "656fa61e94b480b8a500c0e8", - "parentId": "665a06ac85c6ab387e0afbb0", - "slotId": "Back_plate" - }, { - "_id": "665a06ac85c6ab387e0afbbb", - "_tpl": "64afdb577bb3bfe8fe03fd1d", - "parentId": "665a06ac85c6ab387e0afbb0", - "slotId": "Left_side_plate" - }, { - "_id": "665a06ac85c6ab387e0afbbc", - "_tpl": "64afdb577bb3bfe8fe03fd1d", - "parentId": "665a06ac85c6ab387e0afbb0", - "slotId": "Right_side_plate" + "THICC": { + "items": [ + { + "_id": "665a06ac85c6ab387e0afba5", + "_tpl": "5c12613b86f7743bbe2c3f76", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "665a06ac85c6ab387e0afba3", + "slotId": "main" + }, + { + "_id": "665a06ac85c6ab387e0afba7", + "_tpl": "59faff1d86f7746c51718c9c", + "upd": { + "StackObjectsCount": 1 + }, + "parentId": "665a06ac85c6ab387e0afba3", + "slotId": "main" + }, + { + "_id": "665a06ac85c6ab387e0afba8", + "_tpl": "64637076203536ad5600c990", + "upd": { + "Repairable": { + "Durability": 100, + "MaxDurability": 100 } - ], + }, + "parentId": "665a06ac85c6ab387e0afba3", + "slotId": "main" + }, + { + "_id": "665a06ac85c6ab387e0afba9", + "_tpl": "646371779f5f0ea59a04c204", + "parentId": "665a06ac85c6ab387e0afba8", + "slotId": "mod_pistolgrip" + }, + { + "_id": "665a06ac85c6ab387e0afbaa", + "_tpl": "646371faf2404ab67905c8e9", + "parentId": "665a06ac85c6ab387e0afba8", + "slotId": "mod_barrel" + }, + { + "_id": "665a06ac85c6ab387e0afbab", + "_tpl": "6492efb8cfcf7c89e701abf3", + "parentId": "665a06ac85c6ab387e0afbaa", + "slotId": "mod_muzzle" + }, + { + "_id": "665a06ac85c6ab387e0afbac", + "_tpl": "646372518610c40fc20204e8", + "parentId": "665a06ac85c6ab387e0afba8", + "slotId": "mod_magazine" + }, + { + "_id": "665a06ac85c6ab387e0afbad", + "_tpl": "646371a9f2404ab67905c8e6", + "parentId": "665a06ac85c6ab387e0afba8", + "slotId": "mod_stock" + }, + { + "_id": "665a06ac85c6ab387e0afbae", + "_tpl": "6464d870bb2c580352070cc4", + "parentId": "665a06ac85c6ab387e0afba8", + "slotId": "mod_bipod" + }, + { + "_id": "665a06ac85c6ab387e0afbaf", + "_tpl": "6492fb8253acae0af00a29b6", + "parentId": "665a06ac85c6ab387e0afba8", + "slotId": "mod_sight_rear" + }, + { + "_id": "665a06ac85c6ab387e0afbb0", + "_tpl": "60a283193cb70855c43a381d", + "parentId": "665a06ac85c6ab387e0afba3", + "slotId": "main" + }, + { + "_id": "665a06ac85c6ab387e0afbb1", + "_tpl": "6575d561b15fef3dd4051670", + "parentId": "665a06ac85c6ab387e0afbb0", + "slotId": "Soft_armor_front" + }, + { + "_id": "665a06ac85c6ab387e0afbb2", + "_tpl": "6575d56b16c2762fba005818", + "parentId": "665a06ac85c6ab387e0afbb0", + "slotId": "Soft_armor_back" + }, + { + "_id": "665a06ac85c6ab387e0afbb3", + "_tpl": "6575d57a16c2762fba00581c", + "parentId": "665a06ac85c6ab387e0afbb0", + "slotId": "Soft_armor_left" + }, + { + "_id": "665a06ac85c6ab387e0afbb4", + "_tpl": "6575d589b15fef3dd4051674", + "parentId": "665a06ac85c6ab387e0afbb0", + "slotId": "soft_armor_right" + }, + { + "_id": "665a06ac85c6ab387e0afbb5", + "_tpl": "6575d598b15fef3dd4051678", + "parentId": "665a06ac85c6ab387e0afbb0", + "slotId": "Collar" + }, + { + "_id": "665a06ac85c6ab387e0afbb6", + "_tpl": "6575d5b316c2762fba005824", + "parentId": "665a06ac85c6ab387e0afbb0", + "slotId": "Shoulder_l" + }, + { + "_id": "665a06ac85c6ab387e0afbb7", + "_tpl": "6575d5bd16c2762fba005828", + "parentId": "665a06ac85c6ab387e0afbb0", + "slotId": "Shoulder_r" + }, + { + "_id": "665a06ac85c6ab387e0afbb8", + "_tpl": "6575d5a616c2762fba005820", + "parentId": "665a06ac85c6ab387e0afbb0", + "slotId": "Groin" + }, + { + "_id": "665a06ac85c6ab387e0afbb9", + "_tpl": "656fa61e94b480b8a500c0e8", + "parentId": "665a06ac85c6ab387e0afbb0", + "slotId": "Front_plate" + }, + { + "_id": "665a06ac85c6ab387e0afbba", + "_tpl": "656fa61e94b480b8a500c0e8", + "parentId": "665a06ac85c6ab387e0afbb0", + "slotId": "Back_plate" + }, + { + "_id": "665a06ac85c6ab387e0afbbb", + "_tpl": "64afdb577bb3bfe8fe03fd1d", + "parentId": "665a06ac85c6ab387e0afbb0", + "slotId": "Left_side_plate" + }, + { + "_id": "665a06ac85c6ab387e0afbbc", + "_tpl": "64afdb577bb3bfe8fe03fd1d", + "parentId": "665a06ac85c6ab387e0afbb0", + "slotId": "Right_side_plate" + } + ], "sender": "System", "messageText": "TarkovTV May 2024 gift", "collectionTimeHours": 48, "associatedEvent": "Promo", - "maxToSendPlayer": 1 + "maxToSendPlayer": 1 } } -} \ No newline at end of file +} diff --git a/project/assets/configs/health.json b/project/assets/configs/health.json index 6bfb7edb..75ae173e 100644 --- a/project/assets/configs/health.json +++ b/project/assets/configs/health.json @@ -7,4 +7,4 @@ "health": true, "effects": true } -} \ No newline at end of file +} diff --git a/project/assets/configs/hideout.json b/project/assets/configs/hideout.json index b28f446e..161ce9b3 100644 --- a/project/assets/configs/hideout.json +++ b/project/assets/configs/hideout.json @@ -8,5 +8,5 @@ "expCraftAmount": 10, "overrideCraftTimeSeconds": -1, "overrideBuildTimeSeconds": -1, - "updateProfileHideoutWhenActiveWithinMinutes": 90 -} \ No newline at end of file + "updateProfileHideoutWhenActiveWithinMinutes": 90 +} diff --git a/project/assets/configs/http.json b/project/assets/configs/http.json index a6defa80..633a5247 100644 --- a/project/assets/configs/http.json +++ b/project/assets/configs/http.json @@ -1,9 +1,9 @@ { "ip": "127.0.0.1", "port": 6969, - "backendIp": "127.0.0.1", - "backendPort": 6969, + "backendIp": "127.0.0.1", + "backendPort": 6969, "webSocketPingDelayMs": 90000, "logRequests": true, "serverImagePathOverride": {} -} \ No newline at end of file +} diff --git a/project/assets/configs/inraid.json b/project/assets/configs/inraid.json index 97085b3d..6feb35b4 100644 --- a/project/assets/configs/inraid.json +++ b/project/assets/configs/inraid.json @@ -13,15 +13,7 @@ "save": { "loot": true }, - "carExtracts": [ - "Dorms V-Ex", - "PP Exfil", - "V-Ex_light", - "South V-Ex", - "E7_car", - "Sandbox_VExit", - "Shorl_V-Ex" - ], + "carExtracts": ["Dorms V-Ex", "PP Exfil", "V-Ex_light", "South V-Ex", "E7_car", "Sandbox_VExit", "Shorl_V-Ex"], "coopExtracts": [ "Interchange Cooperation", "tunnel_shared", @@ -37,4 +29,4 @@ "pmcKillProbabilityForScavGain": 0.2, "keepFiRSecureContainerOnDeath": false, "playerScavHostileChancePercent": 15 -} \ No newline at end of file +} diff --git a/project/assets/configs/insurance.json b/project/assets/configs/insurance.json index 863009c9..757668ac 100644 --- a/project/assets/configs/insurance.json +++ b/project/assets/configs/insurance.json @@ -3,17 +3,10 @@ "54cb50c76803fa8b248b4571": 75, "54cb57776803fa99248b456e": 85 }, - "blacklistedEquipment": [ - "SpecialSlot1", - "SpecialSlot2", - "SpecialSlot3" - ], - "slotIdsToAlwaysRemove": [ - "cartridges", - "patron_in_weapon" - ], + "blacklistedEquipment": ["SpecialSlot1", "SpecialSlot2", "SpecialSlot3"], + "slotIdsToAlwaysRemove": ["cartridges", "patron_in_weapon"], "returnTimeOverrideSeconds": 0, "runIntervalSeconds": 600, "minAttachmentRoublePriceToBeTaken": 2000, "chanceNoAttachmentsTakenPercent": 10 -} \ No newline at end of file +} diff --git a/project/assets/configs/item.json b/project/assets/configs/item.json index d5bee79c..304ba3b0 100644 --- a/project/assets/configs/item.json +++ b/project/assets/configs/item.json @@ -49,10 +49,7 @@ "6241c2c2117ad530666a5108", "5580239d4bdc2de7118b4583" ], - "lootableItemBlacklist": [ - "660bbc47c38b837877075e47", - "660bc341c38b837877075e4c" - ], + "lootableItemBlacklist": ["660bbc47c38b837877075e47", "660bc341c38b837877075e4c"], "rewardItemBlacklist": [ "58ac60eb86f77401897560ff", "5e997f0b86f7741ac73993e2", @@ -101,7 +98,7 @@ "6662e9f37fa79a6d83730fa0", "6662ea05f6259762c56f3189", "6638a5474e92f038531e210e", - "65ddcc9cfa85b9f17d0dfb07" + "65ddcc9cfa85b9f17d0dfb07" ], "bossItems": [ "6275303a9f372d6ea97f9ec7", @@ -148,4 +145,4 @@ "63a898a328e385334e0640a5": 5000, "63a897c6b1ff6e29734fcc95": 10000 } -} \ No newline at end of file +} diff --git a/project/assets/configs/locale.json b/project/assets/configs/locale.json index 2ddddbd6..30e0d4da 100644 --- a/project/assets/configs/locale.json +++ b/project/assets/configs/locale.json @@ -35,4 +35,4 @@ "zh-*": "zh-cn", "es-*": "es-es" } -} \ No newline at end of file +} diff --git a/project/assets/configs/location.json b/project/assets/configs/location.json index e2a42bf1..232e5a34 100644 --- a/project/assets/configs/location.json +++ b/project/assets/configs/location.json @@ -16,7 +16,7 @@ "tarkovstreets": 3, "terminal": 1, "sandbox": 2.8, - "sandbox_high": 2.8, + "sandbox_high": 2.8, "town": 0 }, "staticLootMultiplier": { @@ -36,7 +36,7 @@ "tarkovstreets": 1, "terminal": 1, "sandbox": 1, - "sandbox_high": 1, + "sandbox_high": 1, "town": 1 }, "customWaves": { @@ -56,9 +56,7 @@ "Supports": [ { "BossEscortType": "pmcBEAR", - "BossEscortDifficult": [ - "normal" - ], + "BossEscortDifficult": ["normal"], "BossEscortAmount": "1" } ], @@ -79,9 +77,7 @@ "Supports": [ { "BossEscortType": "pmcUSEC", - "BossEscortDifficult": [ - "normal" - ], + "BossEscortDifficult": ["normal"], "BossEscortAmount": "1" } ], @@ -104,9 +100,7 @@ "Supports": [ { "BossEscortType": "pmcBEAR", - "BossEscortDifficult": [ - "normal" - ], + "BossEscortDifficult": ["normal"], "BossEscortAmount": "2" } ], @@ -127,9 +121,7 @@ "Supports": [ { "BossEscortType": "pmcUSEC", - "BossEscortDifficult": [ - "normal" - ], + "BossEscortDifficult": ["normal"], "BossEscortAmount": "2" } ], @@ -152,9 +144,7 @@ "Supports": [ { "BossEscortType": "pmcBEAR", - "BossEscortDifficult": [ - "normal" - ], + "BossEscortDifficult": ["normal"], "BossEscortAmount": "2" } ], @@ -175,9 +165,7 @@ "Supports": [ { "BossEscortType": "pmcUSEC", - "BossEscortDifficult": [ - "normal" - ], + "BossEscortDifficult": ["normal"], "BossEscortAmount": "2" } ], @@ -198,9 +186,7 @@ "Supports": [ { "BossEscortType": "pmcBEAR", - "BossEscortDifficult": [ - "normal" - ], + "BossEscortDifficult": ["normal"], "BossEscortAmount": "2" } ], @@ -221,9 +207,7 @@ "Supports": [ { "BossEscortType": "pmcUSEC", - "BossEscortDifficult": [ - "normal" - ], + "BossEscortDifficult": ["normal"], "BossEscortAmount": "2" } ], @@ -244,9 +228,7 @@ "Supports": [ { "BossEscortType": "pmcBEAR", - "BossEscortDifficult": [ - "normal" - ], + "BossEscortDifficult": ["normal"], "BossEscortAmount": "2" } ], @@ -267,9 +249,7 @@ "Supports": [ { "BossEscortType": "pmcUSEC", - "BossEscortDifficult": [ - "normal" - ], + "BossEscortDifficult": ["normal"], "BossEscortAmount": "2" } ], @@ -292,9 +272,7 @@ "Supports": [ { "BossEscortType": "pmcBEAR", - "BossEscortDifficult": [ - "normal" - ], + "BossEscortDifficult": ["normal"], "BossEscortAmount": "1" } ], @@ -315,9 +293,7 @@ "Supports": [ { "BossEscortType": "pmcUSEC", - "BossEscortDifficult": [ - "normal" - ], + "BossEscortDifficult": ["normal"], "BossEscortAmount": "1" } ], @@ -338,9 +314,7 @@ "Supports": [ { "BossEscortType": "pmcUSEC", - "BossEscortDifficult": [ - "normal" - ], + "BossEscortDifficult": ["normal"], "BossEscortAmount": "1" } ], @@ -361,9 +335,7 @@ "Supports": [ { "BossEscortType": "pmcBEAR", - "BossEscortDifficult": [ - "normal" - ], + "BossEscortDifficult": ["normal"], "BossEscortAmount": "1" } ], @@ -384,9 +356,7 @@ "Supports": [ { "BossEscortType": "pmcUSEC", - "BossEscortDifficult": [ - "normal" - ], + "BossEscortDifficult": ["normal"], "BossEscortAmount": "1" } ], @@ -407,9 +377,7 @@ "Supports": [ { "BossEscortType": "pmcBEAR", - "BossEscortDifficult": [ - "normal" - ], + "BossEscortDifficult": ["normal"], "BossEscortAmount": "1" } ], @@ -432,9 +400,7 @@ "Supports": [ { "BossEscortType": "pmcBEAR", - "BossEscortDifficult": [ - "normal" - ], + "BossEscortDifficult": ["normal"], "BossEscortAmount": "1" } ], @@ -455,9 +421,7 @@ "Supports": [ { "BossEscortType": "pmcBEAR", - "BossEscortDifficult": [ - "normal" - ], + "BossEscortDifficult": ["normal"], "BossEscortAmount": "1" } ], @@ -478,9 +442,7 @@ "Supports": [ { "BossEscortType": "pmcBEAR", - "BossEscortDifficult": [ - "normal" - ], + "BossEscortDifficult": ["normal"], "BossEscortAmount": "0" } ], @@ -501,9 +463,7 @@ "Supports": [ { "BossEscortType": "pmcUSEC", - "BossEscortDifficult": [ - "normal" - ], + "BossEscortDifficult": ["normal"], "BossEscortAmount": "1" } ], @@ -524,9 +484,7 @@ "Supports": [ { "BossEscortType": "pmcUSEC", - "BossEscortDifficult": [ - "normal" - ], + "BossEscortDifficult": ["normal"], "BossEscortAmount": "1" } ], @@ -547,9 +505,7 @@ "Supports": [ { "BossEscortType": "pmcUSEC", - "BossEscortDifficult": [ - "normal" - ], + "BossEscortDifficult": ["normal"], "BossEscortAmount": "0" } ], @@ -572,9 +528,7 @@ "Supports": [ { "BossEscortType": "pmcBEAR", - "BossEscortDifficult": [ - "normal" - ], + "BossEscortDifficult": ["normal"], "BossEscortAmount": "1" } ], @@ -595,9 +549,7 @@ "Supports": [ { "BossEscortType": "pmcUSEC", - "BossEscortDifficult": [ - "normal" - ], + "BossEscortDifficult": ["normal"], "BossEscortAmount": "1" } ], @@ -620,9 +572,7 @@ "Supports": [ { "BossEscortType": "pmcBEAR", - "BossEscortDifficult": [ - "normal" - ], + "BossEscortDifficult": ["normal"], "BossEscortAmount": "1" } ], @@ -643,9 +593,7 @@ "Supports": [ { "BossEscortType": "pmcUSEC", - "BossEscortDifficult": [ - "normal" - ], + "BossEscortDifficult": ["normal"], "BossEscortAmount": "1" } ], @@ -668,9 +616,7 @@ "Supports": [ { "BossEscortType": "pmcBEAR", - "BossEscortDifficult": [ - "normal" - ], + "BossEscortDifficult": ["normal"], "BossEscortAmount": "1" } ], @@ -691,9 +637,7 @@ "Supports": [ { "BossEscortType": "pmcBEAR", - "BossEscortDifficult": [ - "normal" - ], + "BossEscortDifficult": ["normal"], "BossEscortAmount": "1" } ], @@ -714,9 +658,7 @@ "Supports": [ { "BossEscortType": "pmcUSEC", - "BossEscortDifficult": [ - "normal" - ], + "BossEscortDifficult": ["normal"], "BossEscortAmount": "1" } ], @@ -737,9 +679,7 @@ "Supports": [ { "BossEscortType": "pmcUSEC", - "BossEscortDifficult": [ - "normal" - ], + "BossEscortDifficult": ["normal"], "BossEscortAmount": "1" } ], @@ -762,9 +702,7 @@ "Supports": [ { "BossEscortType": "pmcBEAR", - "BossEscortDifficult": [ - "normal" - ], + "BossEscortDifficult": ["normal"], "BossEscortAmount": "2" } ], @@ -785,9 +723,7 @@ "Supports": [ { "BossEscortType": "pmcUSEC", - "BossEscortDifficult": [ - "normal" - ], + "BossEscortDifficult": ["normal"], "BossEscortAmount": "2" } ], @@ -795,7 +731,7 @@ "ChanceGroup": 0 } ], - "sandbox_high": [ + "sandbox_high": [ { "sptId": "pmcBEARSandboxNormalSpawn", "BossName": "pmcBEAR", @@ -810,9 +746,7 @@ "Supports": [ { "BossEscortType": "pmcBEAR", - "BossEscortDifficult": [ - "normal" - ], + "BossEscortDifficult": ["normal"], "BossEscortAmount": "2" } ], @@ -833,9 +767,7 @@ "Supports": [ { "BossEscortType": "pmcUSEC", - "BossEscortDifficult": [ - "normal" - ], + "BossEscortDifficult": ["normal"], "BossEscortAmount": "2" } ], @@ -1047,36 +979,29 @@ } }, "openZones": { - "bigmap": [ - "ZoneScavBase" - ] + "bigmap": ["ZoneScavBase"] }, "forcedLootSingleSpawnById": { "bigmap": [ "5ac620eb86f7743a8e6e0da0", "5939e5a786f77461f11c0098", "64e74a3d4d49d23b2c39d319", - "6614230055afee107f05e998" - ], - "interchange": [ - "64e74a5ac2b4f829615ec336" + "6614230055afee107f05e998" ], + "interchange": ["64e74a5ac2b4f829615ec336"], "lighthouse": [ "6331bb0d1aa9f42b804997a6", "6398a0861c712b1e1d4dadf1", "6399f54b0a36db13c823ad21", "64e74a64aac4cd0a7264ecdf", - "661666458c2aa9cb1602503b" - ], - "rezervbase": [ - "64e74a4baac4cd0a7264ecdd", - "6398a072e301557ae24cec92" + "661666458c2aa9cb1602503b" ], + "rezervbase": ["64e74a4baac4cd0a7264ecdd", "6398a072e301557ae24cec92"], "shoreline": [ "64e74a534d49d23b2c39d31b", - "661421c7c1f2f548c50ee649", - "6614217b6d9d5abcad0ff098", - "661423200d240a5f5d0f679b" + "661421c7c1f2f548c50ee649", + "6614217b6d9d5abcad0ff098", + "661423200d240a5f5d0f679b" ], "tarkovstreets": [ "638df4cc7b560b03794a18d2", @@ -1101,14 +1026,8 @@ "657acb2ac900be5902191ac9", "6582dbf0b8d7830efc45016f" ], - "laboratory": [ - "6398a4cfb5992f573c6562b3", - "64e74a44c2b4f829615ec334" - ], - "sandbox": [ - "6575a6ca8778e96ded05a802", - "6582bd252b50c61c565828e2" - ] + "laboratory": ["6398a4cfb5992f573c6562b3", "64e74a44c2b4f829615ec334"], + "sandbox": ["6575a6ca8778e96ded05a802", "6582bd252b50c61c565828e2"] }, "splitWaveIntoSingleSpawnsSettings": { "enabled": true, @@ -1131,15 +1050,7 @@ }, "fixEmptyBotWavesSettings": { "enabled": true, - "ignoreMaps": [ - "base", - "develop", - "hideout", - "privatearea", - "suburbs", - "terminal", - "town" - ] + "ignoreMaps": ["base", "develop", "hideout", "privatearea", "suburbs", "terminal", "town"] }, "fitLootIntoContainerAttempts": 3, "addOpenZonesToAllMaps": true, @@ -1201,7 +1112,7 @@ "minFillStaticMagazinePercent": 50, "allowDuplicateItemsInStaticContainers": true, "magazineLootHasAmmoChancePercent": 50, - "staticMagazineLootHasAmmoChancePercent": 0, + "staticMagazineLootHasAmmoChancePercent": 0, "looseLootBlacklist": {}, "scavRaidTimeSettings": { "settings": { @@ -1424,4 +1335,4 @@ "mod_equipment": 5 } } -} \ No newline at end of file +} diff --git a/project/assets/configs/loot.json b/project/assets/configs/loot.json index d0112974..00fa6b61 100644 --- a/project/assets/configs/loot.json +++ b/project/assets/configs/loot.json @@ -9,4 +9,4 @@ "rezervbase": {}, "tarkovstreets": {} } -} \ No newline at end of file +} diff --git a/project/assets/configs/lostondeath.json b/project/assets/configs/lostondeath.json index 733859d4..0531ce5b 100644 --- a/project/assets/configs/lostondeath.json +++ b/project/assets/configs/lostondeath.json @@ -18,4 +18,4 @@ }, "questItems": true, "specialSlotItems": false -} \ No newline at end of file +} diff --git a/project/assets/configs/match.json b/project/assets/configs/match.json index ba99cdc2..ab130d0a 100644 --- a/project/assets/configs/match.json +++ b/project/assets/configs/match.json @@ -12,4 +12,4 @@ "laboratory": false, "rezervbase": false } -} \ No newline at end of file +} diff --git a/project/assets/configs/playerscav.json b/project/assets/configs/playerscav.json index 1c47212d..e9c81b05 100644 --- a/project/assets/configs/playerscav.json +++ b/project/assets/configs/playerscav.json @@ -856,19 +856,10 @@ "botTypeForLoot": "assault", "equipmentBlacklist": { "Headwear": [], - "ArmorVest": [ - "5df8a2ca86f7740bfe6df777" - ], - "TacticalVest": [ - "572b7adb24597762ae139821" - ], - "Backpack": [ - "56e33634d2720bd8058b456b", - "5ab8ee7786f7742d8f33f0b9" - ], - "FirstPrimaryWeapon": [ - "5a38e6bac4a2826c6e06d79b" - ], + "ArmorVest": ["5df8a2ca86f7740bfe6df777"], + "TacticalVest": ["572b7adb24597762ae139821"], + "Backpack": ["56e33634d2720bd8058b456b", "5ab8ee7786f7742d8f33f0b9"], + "FirstPrimaryWeapon": ["5a38e6bac4a2826c6e06d79b"], "Holster": [], "Scabbard": [] }, @@ -955,22 +946,10 @@ "botTypeForLoot": "assault", "equipmentBlacklist": { "Headwear": [], - "ArmorVest": [ - "59e7635f86f7742cbf2c1095", - "5df8a2ca86f7740bfe6df777" - ], - "TacticalVest": [ - "5fd4c5477a8d854fa0105061", - "572b7adb24597762ae139821" - ], - "Backpack": [ - "56e33680d2720be2748b4576", - "56e33634d2720bd8058b456b", - "5ab8ee7786f7742d8f33f0b9" - ], - "FirstPrimaryWeapon": [ - "5a38e6bac4a2826c6e06d79b" - ], + "ArmorVest": ["59e7635f86f7742cbf2c1095", "5df8a2ca86f7740bfe6df777"], + "TacticalVest": ["5fd4c5477a8d854fa0105061", "572b7adb24597762ae139821"], + "Backpack": ["56e33680d2720be2748b4576", "56e33634d2720bd8058b456b", "5ab8ee7786f7742d8f33f0b9"], + "FirstPrimaryWeapon": ["5a38e6bac4a2826c6e06d79b"], "Holster": [], "Scabbard": [] }, @@ -1056,22 +1035,10 @@ "botTypeForLoot": "assault", "equipmentBlacklist": { "Headwear": [], - "ArmorVest": [ - "59e7635f86f7742cbf2c1095", - "5df8a2ca86f7740bfe6df777" - ], - "TacticalVest": [ - "5fd4c5477a8d854fa0105061", - "572b7adb24597762ae139821" - ], - "Backpack": [ - "56e33680d2720be2748b4576", - "56e33634d2720bd8058b456b", - "5ab8ee7786f7742d8f33f0b9" - ], - "FirstPrimaryWeapon": [ - "5a38e6bac4a2826c6e06d79b" - ], + "ArmorVest": ["59e7635f86f7742cbf2c1095", "5df8a2ca86f7740bfe6df777"], + "TacticalVest": ["5fd4c5477a8d854fa0105061", "572b7adb24597762ae139821"], + "Backpack": ["56e33680d2720be2748b4576", "56e33634d2720bd8058b456b", "5ab8ee7786f7742d8f33f0b9"], + "FirstPrimaryWeapon": ["5a38e6bac4a2826c6e06d79b"], "Holster": [], "Scabbard": [] }, @@ -1168,14 +1135,8 @@ "5f60e7788adaa7100c3adb49", "5aa2a7e8e5b5b00016327c16" ], - "ArmorVest": [ - "59e7635f86f7742cbf2c1095", - "5df8a2ca86f7740bfe6df777" - ], - "TacticalVest": [ - "5fd4c5477a8d854fa0105061", - "572b7adb24597762ae139821" - ], + "ArmorVest": ["59e7635f86f7742cbf2c1095", "5df8a2ca86f7740bfe6df777"], + "TacticalVest": ["5fd4c5477a8d854fa0105061", "572b7adb24597762ae139821"], "Backpack": [ "56e33680d2720be2748b4576", "56e33634d2720bd8058b456b", @@ -1183,14 +1144,8 @@ "5ab8f04f86f774585f4237d8", "5f5e45cc5021ce62144be7aa" ], - "FirstPrimaryWeapon": [ - "5a38e6bac4a2826c6e06d79b" - ], - "Holster": [ - "5448bd6b4bdc2dfc2f8b4569", - "579204f224597773d619e051", - "571a12c42459771f627b58a0" - ], + "FirstPrimaryWeapon": ["5a38e6bac4a2826c6e06d79b"], + "Holster": ["5448bd6b4bdc2dfc2f8b4569", "579204f224597773d619e051", "571a12c42459771f627b58a0"], "Scabbard": [] }, "modifiers": { @@ -1271,4 +1226,4 @@ } } } -} \ No newline at end of file +} diff --git a/project/assets/configs/pmc.json b/project/assets/configs/pmc.json index 0392e00d..f69b0c3b 100644 --- a/project/assets/configs/pmc.json +++ b/project/assets/configs/pmc.json @@ -66,7 +66,7 @@ "6391fcf5744e45201147080f", "614451b71e5874611e2c7ae5", "6540d2162ae6d96b540afcaf", - "65ca457b4aafb5d7fc0dcb5d" + "65ca457b4aafb5d7fc0dcb5d" ] }, "pocketLoot": { @@ -120,8 +120,8 @@ "57864c8c245977548867e7f1", "6087e570b998180e9f76dc24", "6391fcf5744e45201147080f", - "65ca457b4aafb5d7fc0dcb5d", - "660bbc98c38b837877075e4a" + "65ca457b4aafb5d7fc0dcb5d", + "660bbc98c38b837877075e4a" ] }, "backpackLoot": { @@ -179,8 +179,8 @@ "6391fcf5744e45201147080f", "614451b71e5874611e2c7ae5", "6540d2162ae6d96b540afcaf", - "65ca457b4aafb5d7fc0dcb5d", - "660bbc98c38b837877075e4a" + "65ca457b4aafb5d7fc0dcb5d", + "660bbc98c38b837877075e4a" ] }, "useDifficultyOverride": false, @@ -212,7 +212,7 @@ "arenaFighterEvent": 0, "crazyAssaultEvent": 3, "pmcBot": 5, - "pmcBEAR": 2 + "pmcBEAR": 2 }, "factory4_night": { "bossKilla": 2, @@ -233,7 +233,7 @@ "arenaFighterEvent": 0, "crazyAssaultEvent": 3, "pmcBot": 5, - "pmcBEAR": 2 + "pmcBEAR": 2 }, "bigmap": { "bossKilla": 2, @@ -254,7 +254,7 @@ "arenaFighterEvent": 0, "crazyAssaultEvent": 3, "pmcBot": 5, - "pmcBEAR": 2 + "pmcBEAR": 2 }, "laboratory": { "bossKilla": 2, @@ -275,7 +275,7 @@ "arenaFighterEvent": 0, "crazyAssaultEvent": 3, "pmcBot": 5, - "pmcBEAR": 2 + "pmcBEAR": 2 }, "woods": { "bossKilla": 2, @@ -297,7 +297,7 @@ "arenaFighterEvent": 0, "crazyAssaultEvent": 3, "pmcBot": 5, - "pmcBEAR": 2 + "pmcBEAR": 2 }, "interchange": { "bossKilla": 2, @@ -318,7 +318,7 @@ "arenaFighterEvent": 0, "crazyAssaultEvent": 3, "pmcBot": 5, - "pmcBEAR": 2 + "pmcBEAR": 2 }, "lighthouse": { "bossKilla": 2, @@ -339,7 +339,7 @@ "arenaFighterEvent": 0, "crazyAssaultEvent": 3, "pmcBot": 5, - "pmcBEAR": 2 + "pmcBEAR": 2 }, "rezervbase": { "bossKilla": 2, @@ -360,7 +360,7 @@ "arenaFighterEvent": 1, "crazyAssaultEvent": 3, "pmcBot": 5, - "pmcBEAR": 2 + "pmcBEAR": 2 }, "shoreline": { "bossKilla": 2, @@ -381,7 +381,7 @@ "arenaFighterEvent": 0, "crazyAssaultEvent": 3, "pmcBot": 5, - "pmcBEAR": 2 + "pmcBEAR": 2 }, "tarkovstreets": { "bossKilla": 2, @@ -402,7 +402,7 @@ "arenaFighterEvent": 0, "crazyAssaultEvent": 3, "pmcBot": 5, - "pmcBEAR": 2 + "pmcBEAR": 2 }, "sandbox": { "bossKilla": 2, @@ -425,7 +425,7 @@ "arenaFighterEvent": 1, "crazyAssaultEvent": 1, "pmcBot": 7, - "pmcBEAR": 2 + "pmcBEAR": 2 }, "sandbox_high": { "bossKilla": 2, @@ -448,7 +448,7 @@ "arenaFighterEvent": 1, "crazyAssaultEvent": 1, "pmcBot": 7, - "pmcBEAR": 2 + "pmcBEAR": 2 } }, "pmcusec": { @@ -471,7 +471,7 @@ "arenaFighterEvent": 0, "crazyAssaultEvent": 3, "pmcBot": 5, - "pmcUSEC": 2 + "pmcUSEC": 2 }, "factory4_night": { "bossKilla": 2, @@ -492,7 +492,7 @@ "arenaFighterEvent": 0, "crazyAssaultEvent": 3, "pmcBot": 5, - "pmcUSEC": 2 + "pmcUSEC": 2 }, "bigmap": { "bossKilla": 0, @@ -513,7 +513,7 @@ "arenaFighterEvent": 0, "crazyAssaultEvent": 2, "pmcBot": 6, - "pmcUSEC": 2 + "pmcUSEC": 2 }, "laboratory": { "bossKilla": 2, @@ -534,7 +534,7 @@ "arenaFighterEvent": 0, "crazyAssaultEvent": 3, "pmcBot": 5, - "pmcUSEC": 2 + "pmcUSEC": 2 }, "woods": { "bossKilla": 2, @@ -556,7 +556,7 @@ "arenaFighterEvent": 0, "crazyAssaultEvent": 3, "pmcBot": 5, - "pmcUSEC": 2 + "pmcUSEC": 2 }, "interchange": { "bossKilla": 2, @@ -577,7 +577,7 @@ "arenaFighterEvent": 0, "crazyAssaultEvent": 3, "pmcBot": 5, - "pmcUSEC": 2 + "pmcUSEC": 2 }, "lighthouse": { "bossKilla": 2, @@ -598,7 +598,7 @@ "arenaFighterEvent": 0, "crazyAssaultEvent": 3, "pmcBot": 5, - "pmcUSEC": 2 + "pmcUSEC": 2 }, "rezervbase": { "bossKilla": 2, @@ -619,7 +619,7 @@ "arenaFighterEvent": 1, "crazyAssaultEvent": 3, "pmcBot": 5, - "pmcUSEC": 2 + "pmcUSEC": 2 }, "shoreline": { "bossKilla": 2, @@ -640,7 +640,7 @@ "arenaFighterEvent": 0, "crazyAssaultEvent": 3, "pmcBot": 5, - "pmcUSEC": 2 + "pmcUSEC": 2 }, "tarkovstreets": { "bossKilla": 2, @@ -661,7 +661,7 @@ "arenaFighterEvent": 0, "crazyAssaultEvent": 3, "pmcBot": 5, - "pmcUSEC": 2 + "pmcUSEC": 2 }, "sandbox": { "bossKilla": 2, @@ -684,7 +684,7 @@ "arenaFighterEvent": 1, "crazyAssaultEvent": 1, "pmcBot": 7, - "pmcUSEC": 2 + "pmcUSEC": 2 }, "sandbox_high": { "bossKilla": 2, @@ -707,7 +707,7 @@ "arenaFighterEvent": 1, "crazyAssaultEvent": 1, "pmcBot": 7, - "pmcUSEC": 2 + "pmcUSEC": 2 } } }, diff --git a/project/assets/configs/quest.json b/project/assets/configs/quest.json index f986c5bd..4d787ef7 100644 --- a/project/assets/configs/quest.json +++ b/project/assets/configs/quest.json @@ -1,8 +1,8 @@ { "mailRedeemTimeHours": { - "default": 48, - "unheard_edition": 72 - }, + "default": 48, + "unheard_edition": 72 + }, "usecOnlyQuests": [ "6179b5eabca27a099552e052", "5e383a6386f77465910ce1f3", @@ -149,168 +149,73 @@ "endTimestamp": "", "yearly": false }, - "65e85198e32da31f2b30978e": { - "name": "Evil Spirits", - "season": "None", - "startTimestamp": 1341615600000, + "65e85198e32da31f2b30978e": { + "name": "Evil Spirits", + "season": "None", + "startTimestamp": 1341615600000, "endTimestamp": "", "yearly": false - }, - "6603fe74e773dcf3b0099f88": { - "name": "The Tarkov Mystery", - "season": "None", - "startTimestamp": 1341615600000, + }, + "6603fe74e773dcf3b0099f88": { + "name": "The Tarkov Mystery", + "season": "None", + "startTimestamp": 1341615600000, "endTimestamp": "", "yearly": false - }, - "6658a15615cbb1b2c6014d5b": { - "name": "Hustle2", - "season": "None", - "startTimestamp": 1341615600000, + }, + "6658a15615cbb1b2c6014d5b": { + "name": "Hustle2", + "season": "None", + "startTimestamp": 1341615600000, "endTimestamp": "", "yearly": false - }, - "6672ec2a2b6f3b71be794cc5": { - "name": "Key to salvation", - "season": "None", - "startTimestamp": 1341615600000, + }, + "6672ec2a2b6f3b71be794cc5": { + "name": "Key to salvation", + "season": "None", + "startTimestamp": 1341615600000, "endTimestamp": "", "yearly": false - } + } }, "repeatableQuests": [ { "id": "615ffc701c97c768137e719b", "name": "Daily", "side": "Pmc", - "types": [ - "Elimination", - "Completion", - "Exploration" - ], + "types": ["Elimination", "Completion", "Exploration"], "resetTime": 86400, "numQuests": 3, "minPlayerLevel": 5, "rewardScaling": { - "levels": [ - 1, - 10, - 20, - 30, - 40, - 50, - 60 - ], - "experience": [ - 1000, - 2000, - 8000, - 13000, - 19000, - 24000, - 30000 - ], - "roubles": [ - 11000, - 20000, - 32000, - 45000, - 58000, - 70000, - 82000 - ], - "gpCoins": [ - 3, - 3, - 6, - 6, - 8, - 8, - 10 - ], - "items": [ - 2, - 4, - 5, - 5, - 5, - 5, - 5 - ], - "reputation": [ - 0.01, - 0.01, - 0.02, - 0.02, - 0.03, - 0.03, - 0.03 - ], + "levels": [1, 10, 20, 30, 40, 50, 60], + "experience": [1000, 2000, 8000, 13000, 19000, 24000, 30000], + "roubles": [11000, 20000, 32000, 45000, 58000, 70000, 82000], + "gpCoins": [3, 3, 6, 6, 8, 8, 10], + "items": [2, 4, 5, 5, 5, 5, 5], + "reputation": [0.01, 0.01, 0.02, 0.02, 0.03, 0.03, 0.03], "rewardSpread": 0.5, - "skillRewardChance": [ - 0, - 0.01, - 0.05, - 0.1, - 0.1, - 0.15, - 0.15 - ], - "skillPointReward": [ - 10, - 15, - 20, - 25, - 30, - 35, - 40 - ] + "skillRewardChance": [0, 0.01, 0.05, 0.1, 0.1, 0.15, 0.15], + "skillPointReward": [10, 15, 20, 25, 30, 35, 40] }, "locations": { - "any": [ - "any" - ], - "factory4_day": [ - "factory4_day", - "factory4_night" - ], - "bigmap": [ - "bigmap" - ], - "Woods": [ - "Woods" - ], - "Shoreline": [ - "Shoreline" - ], - "Interchange": [ - "Interchange" - ], - "Lighthouse": [ - "Lighthouse" - ], - "laboratory": [ - "laboratory" - ], - "RezervBase": [ - "RezervBase" - ], - "TarkovStreets": [ - "TarkovStreets" - ], - "Sandbox": [ - "Sandbox" - ] + "any": ["any"], + "factory4_day": ["factory4_day", "factory4_night"], + "bigmap": ["bigmap"], + "Woods": ["Woods"], + "Shoreline": ["Shoreline"], + "Interchange": ["Interchange"], + "Lighthouse": ["Lighthouse"], + "laboratory": ["laboratory"], + "RezervBase": ["RezervBase"], + "TarkovStreets": ["TarkovStreets"], + "Sandbox": ["Sandbox"] }, "traderWhitelist": [ { "traderId": "54cb50c76803fa8b248b4571", "name": "prapor", - "questTypes": [ - "Completion", - "Exploration", - "Elimination" - ], + "questTypes": ["Completion", "Exploration", "Elimination"], "rewardBaseWhitelist": [ "543be6564bdc2df4348b4568", "5485a8684bdc2da71d8b4567", @@ -324,11 +229,7 @@ { "traderId": "54cb57776803fa99248b456e", "name": "therapist", - "questTypes": [ - "Completion", - "Exploration", - "Elimination" - ], + "questTypes": ["Completion", "Exploration", "Elimination"], "rewardBaseWhitelist": [ "57864a66245977548f04a81f", "5448f39d4bdc2d0a728b4568", @@ -347,11 +248,7 @@ { "traderId": "58330581ace78e27b8b10cee", "name": "skier", - "questTypes": [ - "Completion", - "Exploration", - "Elimination" - ], + "questTypes": ["Completion", "Exploration", "Elimination"], "rewardBaseWhitelist": [ "5a341c4086f77401f2541505", "5448e8d64bdc2dce718b4568", @@ -374,11 +271,7 @@ { "traderId": "5935c25fb3acc3127c3d8cd9", "name": "peacekeeper", - "questTypes": [ - "Completion", - "Exploration", - "Elimination" - ], + "questTypes": ["Completion", "Exploration", "Elimination"], "rewardBaseWhitelist": [ "543be6564bdc2df4348b4568", "5448e5284bdc2dcb718b4567", @@ -396,10 +289,7 @@ { "traderId": "5a7c2eca46aef81a7ca2145d", "name": "mechanic", - "questTypes": [ - "Completion", - "Exploration" - ], + "questTypes": ["Completion", "Exploration"], "rewardBaseWhitelist": [ "55818af64bdc2d5b648b4570", "5448bc234bdc2d3c308b4569", @@ -420,11 +310,7 @@ { "traderId": "5ac3b934156ae10c4430e83c", "name": "ragman", - "questTypes": [ - "Completion", - "Exploration", - "Elimination" - ], + "questTypes": ["Completion", "Exploration", "Elimination"], "rewardBaseWhitelist": [ "5a341c4086f77401f2541505", "5448e5724bdc2ddf718b4568", @@ -441,11 +327,7 @@ { "traderId": "5c0647fdd443bc2504c2d371", "name": "jaeger", - "questTypes": [ - "Completion", - "Exploration", - "Elimination" - ], + "questTypes": ["Completion", "Exploration", "Elimination"], "rewardBaseWhitelist": [ "5448f3ac4bdc2dce718b4569", "5c99f98d86f7745c314214b3", @@ -462,14 +344,10 @@ "rewardCanBeWeapon": false, "weaponRewardChancePercent": 0 }, - { + { "traderId": "6617beeaa9cfa777ca915b7c", "name": "ref", - "questTypes": [ - "Completion", - "Exploration", - "Elimination" - ], + "questTypes": ["Completion", "Exploration", "Elimination"], "rewardBaseWhitelist": [ "543be6564bdc2df4348b4568", "5485a8684bdc2da71d8b4567", @@ -485,11 +363,7 @@ "Exploration": { "maxExtracts": 5, "maxExtractsWithSpecificExit": 3, - "possibleSkillRewards": [ - "Endurance", - "Strength", - "Vitality" - ], + "possibleSkillRewards": ["Endurance", "Strength", "Vitality"], "specificExits": { "probability": 0.25, "passageRequirementWhitelist": [ @@ -503,11 +377,7 @@ } }, "Completion": { - "possibleSkillRewards": [ - "Endurance", - "Strength", - "Vitality" - ], + "possibleSkillRewards": ["Endurance", "Strength", "Vitality"], "minRequestedAmount": 1, "maxRequestedAmount": 4, "uniqueItemCount": 2, @@ -522,11 +392,7 @@ "min": 1, "max": 15 }, - "possibleSkillRewards": [ - "Endurance", - "Strength", - "Vitality" - ], + "possibleSkillRewards": ["Endurance", "Strength", "Vitality"], "targets": [ { "key": "Savage", @@ -541,41 +407,26 @@ { "key": "Head", "relativeProbability": 1, - "data": [ - "Head" - ] + "data": ["Head"] }, { "key": "Chest", "relativeProbability": 25, - "data": [ - "Chest", - "Stomach" - ] + "data": ["Chest", "Stomach"] }, { "key": "Arms", "relativeProbability": 0.5, - "data": [ - "LeftArm", - "RightArm" - ] + "data": ["LeftArm", "RightArm"] }, { "key": "Legs", "relativeProbability": 1, - "data": [ - "LeftLeg", - "RightLeg" - ] + "data": ["LeftLeg", "RightLeg"] } ], "specificLocationProb": 0.15, - "distLocationBlacklist": [ - "laboratory", - "factory4_day", - "factory4_night" - ], + "distLocationBlacklist": ["laboratory", "factory4_day", "factory4_night"], "distProb": 0.15, "maxDist": 75, "minDist": 10, @@ -591,123 +442,89 @@ { "key": "Shotgun", "relativeProbability": 10, - "data": [ - "5b5f794b86f77409407a7f92" - ] + "data": ["5b5f794b86f77409407a7f92"] }, { "key": "Pistol", "relativeProbability": 10, - "data": [ - "5b5f792486f77447ed5636b3" - ] + "data": ["5b5f792486f77447ed5636b3"] }, { "key": "AssaultRifle", "relativeProbability": 3, - "data": [ - "5b5f78fc86f77409407a7f90" - ] + "data": ["5b5f78fc86f77409407a7f90"] }, { "key": "AssaultCarbine", "relativeProbability": 10, - "data": [ - "5b5f78e986f77447ed5636b1" - ] + "data": ["5b5f78e986f77447ed5636b1"] }, { "key": "SMG", "relativeProbability": 3, - "data": [ - "5b5f796a86f774093f2ed3c0" - ] + "data": ["5b5f796a86f774093f2ed3c0"] }, { "key": "Melee", "relativeProbability": 0, - "data": [ - "5b5f7a0886f77409407a7f96" - ] + "data": ["5b5f7a0886f77409407a7f96"] }, { "key": "DMR", "relativeProbability": 3, - "data": [ - "5b5f791486f774093f2ed3be" - ] + "data": ["5b5f791486f774093f2ed3be"] }, { "key": "MarksmanRifle", "relativeProbability": 1, - "data": [ - "5447b6194bdc2d67278b4567" - ] + "data": ["5447b6194bdc2d67278b4567"] }, { "key": "BoltAction", "relativeProbability": 10, - "data": [ - "5b5f798886f77447ed5636b5" - ] + "data": ["5b5f798886f77447ed5636b5"] }, { "key": "MachineGun", "relativeProbability": 0, - "data": [ - "5b5f79a486f77409407a7f94" - ] + "data": ["5b5f79a486f77409407a7f94"] } ], "weaponRequirements": [ { "key": "Shotgun", "relativeProbability": 10, - "data": [ - "5447b6094bdc2dc3278b4567" - ] + "data": ["5447b6094bdc2dc3278b4567"] }, { "key": "Pistol", "relativeProbability": 10, - "data": [ - "5447b5cf4bdc2d65278b4567" - ] + "data": ["5447b5cf4bdc2d65278b4567"] }, { "key": "AssaultRifle", "relativeProbability": 3, - "data": [ - "5447b5f14bdc2d61278b4567" - ] + "data": ["5447b5f14bdc2d61278b4567"] }, { "key": "AssaultCarbine", "relativeProbability": 10, - "data": [ - "5447b5fc4bdc2d87278b4567" - ] + "data": ["5447b5fc4bdc2d87278b4567"] }, { "key": "MarksmanRifle", "relativeProbability": 1, - "data": [ - "5447b6194bdc2d67278b4567" - ] + "data": ["5447b6194bdc2d67278b4567"] }, { "key": "SniperRifle", "relativeProbability": 1, - "data": [ - "5447b6254bdc2dc3278b4568" - ] + "data": ["5447b6254bdc2dc3278b4568"] }, { "key": "SMG", "relativeProbability": 1, - "data": [ - "5447b5e04bdc2d62278b4567" - ] + "data": ["5447b5e04bdc2d62278b4567"] } ] }, @@ -716,11 +533,7 @@ "min": 16, "max": 40 }, - "possibleSkillRewards": [ - "Endurance", - "Strength", - "Vitality" - ], + "possibleSkillRewards": ["Endurance", "Strength", "Vitality"], "targets": [ { "key": "Savage", @@ -813,41 +626,26 @@ { "key": "Head", "relativeProbability": 1, - "data": [ - "Head" - ] + "data": ["Head"] }, { "key": "Chest", "relativeProbability": 8, - "data": [ - "Chest", - "Stomach" - ] + "data": ["Chest", "Stomach"] }, { "key": "Arms", "relativeProbability": 0.5, - "data": [ - "LeftArm", - "RightArm" - ] + "data": ["LeftArm", "RightArm"] }, { "key": "Legs", "relativeProbability": 1, - "data": [ - "LeftLeg", - "RightLeg" - ] + "data": ["LeftLeg", "RightLeg"] } ], "specificLocationProb": 0.2, - "distLocationBlacklist": [ - "laboratory", - "factory4_day", - "factory4_night" - ], + "distLocationBlacklist": ["laboratory", "factory4_day", "factory4_night"], "distProb": 0.25, "maxDist": 100, "minDist": 10, @@ -863,116 +661,84 @@ { "key": "Shotgun", "relativeProbability": 8, - "data": [ - "5b5f794b86f77409407a7f92" - ] + "data": ["5b5f794b86f77409407a7f92"] }, { "key": "Pistol", "relativeProbability": 5, - "data": [ - "5b5f792486f77447ed5636b3" - ] + "data": ["5b5f792486f77447ed5636b3"] }, { "key": "AssaultRifle", "relativeProbability": 10, - "data": [ - "5b5f78fc86f77409407a7f90" - ] + "data": ["5b5f78fc86f77409407a7f90"] }, { "key": "AssaultCarbine", "relativeProbability": 10, - "data": [ - "5b5f78e986f77447ed5636b1" - ] + "data": ["5b5f78e986f77447ed5636b1"] }, { "key": "SMG", "relativeProbability": 10, - "data": [ - "5b5f796a86f774093f2ed3c0" - ] + "data": ["5b5f796a86f774093f2ed3c0"] }, { "key": "Melee", "relativeProbability": 0, - "data": [ - "5b5f7a0886f77409407a7f96" - ] + "data": ["5b5f7a0886f77409407a7f96"] }, { "key": "DMR", "relativeProbability": 8, - "data": [ - "5b5f791486f774093f2ed3be" - ] + "data": ["5b5f791486f774093f2ed3be"] }, { "key": "BoltAction", "relativeProbability": 10, - "data": [ - "5b5f798886f77447ed5636b5" - ] + "data": ["5b5f798886f77447ed5636b5"] }, { "key": "MachineGun", "relativeProbability": 0, - "data": [ - "5b5f79a486f77409407a7f94" - ] + "data": ["5b5f79a486f77409407a7f94"] } ], "weaponRequirements": [ { "key": "Shotgun", "relativeProbability": 10, - "data": [ - "5447b6094bdc2dc3278b4567" - ] + "data": ["5447b6094bdc2dc3278b4567"] }, { "key": "Pistol", "relativeProbability": 10, - "data": [ - "5447b5cf4bdc2d65278b4567" - ] + "data": ["5447b5cf4bdc2d65278b4567"] }, { "key": "AssaultRifle", "relativeProbability": 3, - "data": [ - "5447b5f14bdc2d61278b4567" - ] + "data": ["5447b5f14bdc2d61278b4567"] }, { "key": "AssaultCarbine", "relativeProbability": 5, - "data": [ - "5447b5fc4bdc2d87278b4567" - ] + "data": ["5447b5fc4bdc2d87278b4567"] }, { "key": "MarksmanRifle", "relativeProbability": 1, - "data": [ - "5447b6194bdc2d67278b4567" - ] + "data": ["5447b6194bdc2d67278b4567"] }, { "key": "SniperRifle", "relativeProbability": 1, - "data": [ - "5447b6254bdc2dc3278b4568" - ] + "data": ["5447b6254bdc2dc3278b4568"] }, { "key": "SMG", "relativeProbability": 1, - "data": [ - "5447b5e04bdc2d62278b4567" - ] + "data": ["5447b5e04bdc2d62278b4567"] } ] }, @@ -981,11 +747,7 @@ "min": 41, "max": 100 }, - "possibleSkillRewards": [ - "Endurance", - "Strength", - "Vitality" - ], + "possibleSkillRewards": ["Endurance", "Strength", "Vitality"], "targets": [ { "key": "Savage", @@ -1078,41 +840,26 @@ { "key": "Head", "relativeProbability": 1, - "data": [ - "Head" - ] + "data": ["Head"] }, { "key": "Chest", "relativeProbability": 7, - "data": [ - "Chest", - "Stomach" - ] + "data": ["Chest", "Stomach"] }, { "key": "Arms", "relativeProbability": 0.5, - "data": [ - "LeftArm", - "RightArm" - ] + "data": ["LeftArm", "RightArm"] }, { "key": "Legs", "relativeProbability": 1, - "data": [ - "LeftLeg", - "RightLeg" - ] + "data": ["LeftLeg", "RightLeg"] } ], "specificLocationProb": 0.25, - "distLocationBlacklist": [ - "laboratory", - "factory4_day", - "factory4_night" - ], + "distLocationBlacklist": ["laboratory", "factory4_day", "factory4_night"], "distProb": 0.25, "maxDist": 100, "minDist": 10, @@ -1128,116 +875,84 @@ { "key": "Shotgun", "relativeProbability": 10, - "data": [ - "5b5f794b86f77409407a7f92" - ] + "data": ["5b5f794b86f77409407a7f92"] }, { "key": "Pistol", "relativeProbability": 10, - "data": [ - "5b5f792486f77447ed5636b3" - ] + "data": ["5b5f792486f77447ed5636b3"] }, { "key": "AssaultRifle", "relativeProbability": 10, - "data": [ - "5b5f78fc86f77409407a7f90" - ] + "data": ["5b5f78fc86f77409407a7f90"] }, { "key": "AssaultCarbine", "relativeProbability": 15, - "data": [ - "5b5f78e986f77447ed5636b1" - ] + "data": ["5b5f78e986f77447ed5636b1"] }, { "key": "SMG", "relativeProbability": 8, - "data": [ - "5b5f796a86f774093f2ed3c0" - ] + "data": ["5b5f796a86f774093f2ed3c0"] }, { "key": "Melee", "relativeProbability": 1, - "data": [ - "5b5f7a0886f77409407a7f96" - ] + "data": ["5b5f7a0886f77409407a7f96"] }, { "key": "DMR", "relativeProbability": 10, - "data": [ - "5b5f791486f774093f2ed3be" - ] + "data": ["5b5f791486f774093f2ed3be"] }, { "key": "BoltAction", "relativeProbability": 10, - "data": [ - "5b5f798886f77447ed5636b5" - ] + "data": ["5b5f798886f77447ed5636b5"] }, { "key": "MachineGun", "relativeProbability": 1, - "data": [ - "5b5f79a486f77409407a7f94" - ] + "data": ["5b5f79a486f77409407a7f94"] } ], "weaponRequirements": [ { "key": "Shotgun", "relativeProbability": 10, - "data": [ - "5447b6094bdc2dc3278b4567" - ] + "data": ["5447b6094bdc2dc3278b4567"] }, { "key": "Pistol", "relativeProbability": 10, - "data": [ - "5447b5cf4bdc2d65278b4567" - ] + "data": ["5447b5cf4bdc2d65278b4567"] }, { "key": "AssaultRifle", "relativeProbability": 10, - "data": [ - "5447b5f14bdc2d61278b4567" - ] + "data": ["5447b5f14bdc2d61278b4567"] }, { "key": "AssaultCarbine", "relativeProbability": 10, - "data": [ - "5447b5fc4bdc2d87278b4567" - ] + "data": ["5447b5fc4bdc2d87278b4567"] }, { "key": "MarksmanRifle", "relativeProbability": 10, - "data": [ - "5447b6194bdc2d67278b4567" - ] + "data": ["5447b6194bdc2d67278b4567"] }, { "key": "SniperRifle", "relativeProbability": 10, - "data": [ - "5447b6254bdc2dc3278b4568" - ] + "data": ["5447b6254bdc2dc3278b4568"] }, { "key": "SMG", "relativeProbability": 10, - "data": [ - "5447b5e04bdc2d62278b4567" - ] + "data": ["5447b5e04bdc2d62278b4567"] } ] } @@ -1248,147 +963,48 @@ "5b3f15d486f77432d0509248", "65649eb40bf0ed77b8044453" ], - "rewardBlacklist": [ - "627bce33f21bc425b06ab967", - "59f32c3b86f77472a31742f0", - "59f32bb586f774757e1e8442" - ], + "rewardBlacklist": ["627bce33f21bc425b06ab967", "59f32c3b86f77472a31742f0", "59f32bb586f774757e1e8442"], "rewardAmmoStackMinSize": 5, - "freeChangesAvailable": 2, + "freeChangesAvailable": 2, "freeChanges": 2 }, { "id": "618035d38012292db3081bf0", "name": "Weekly", "side": "Pmc", - "types": [ - "Elimination", - "Completion", - "Exploration" - ], + "types": ["Elimination", "Completion", "Exploration"], "resetTime": 604800, "numQuests": 1, "minPlayerLevel": 15, "rewardScaling": { - "levels": [ - 1, - 10, - 20, - 30, - 40, - 50, - 60 - ], - "experience": [ - 5000, - 15000, - 27000, - 80000, - 142000, - 220000, - 290000 - ], - "roubles": [ - 20000, - 50000, - 175000, - 350000, - 540000, - 710000, - 880000 - ], - "gpCoins": [ - 10, - 10, - 16, - 16, - 20, - 30, - 35 - ], - "items": [ - 4, - 5, - 5, - 6, - 6, - 7, - 7 - ], - "reputation": [ - 0.02, - 0.03, - 0.04, - 0.04, - 0.05, - 0.05, - 0.05 - ], + "levels": [1, 10, 20, 30, 40, 50, 60], + "experience": [5000, 15000, 27000, 80000, 142000, 220000, 290000], + "roubles": [20000, 50000, 175000, 350000, 540000, 710000, 880000], + "gpCoins": [10, 10, 16, 16, 20, 30, 35], + "items": [4, 5, 5, 6, 6, 7, 7], + "reputation": [0.02, 0.03, 0.04, 0.04, 0.05, 0.05, 0.05], "rewardSpread": 0.5, - "skillRewardChance": [ - 0, - 0.05, - 0.1, - 0.15, - 0.2, - 0.2, - 0.2 - ], - "skillPointReward": [ - 25, - 35, - 45, - 50, - 55, - 60, - 65 - ] + "skillRewardChance": [0, 0.05, 0.1, 0.15, 0.2, 0.2, 0.2], + "skillPointReward": [25, 35, 45, 50, 55, 60, 65] }, "locations": { - "any": [ - "any" - ], - "factory4_day": [ - "factory4_day", - "factory4_night" - ], - "bigmap": [ - "bigmap" - ], - "Woods": [ - "Woods" - ], - "Shoreline": [ - "Shoreline" - ], - "Interchange": [ - "Interchange" - ], - "Lighthouse": [ - "Lighthouse" - ], - "laboratory": [ - "laboratory" - ], - "RezervBase": [ - "RezervBase" - ], - "TarkovStreets": [ - "TarkovStreets" - ], - "Sandbox": [ - "Sandbox" - ] + "any": ["any"], + "factory4_day": ["factory4_day", "factory4_night"], + "bigmap": ["bigmap"], + "Woods": ["Woods"], + "Shoreline": ["Shoreline"], + "Interchange": ["Interchange"], + "Lighthouse": ["Lighthouse"], + "laboratory": ["laboratory"], + "RezervBase": ["RezervBase"], + "TarkovStreets": ["TarkovStreets"], + "Sandbox": ["Sandbox"] }, "traderWhitelist": [ { "traderId": "54cb50c76803fa8b248b4571", "name": "prapor", - "questTypes": [ - "Completion", - "Exploration", - "Elimination" - ], + "questTypes": ["Completion", "Exploration", "Elimination"], "rewardBaseWhitelist": [ "543be6564bdc2df4348b4568", "5485a8684bdc2da71d8b4567", @@ -1402,11 +1018,7 @@ { "traderId": "54cb57776803fa99248b456e", "name": "therapist", - "questTypes": [ - "Completion", - "Exploration", - "Elimination" - ], + "questTypes": ["Completion", "Exploration", "Elimination"], "rewardBaseWhitelist": [ "57864a66245977548f04a81f", "5448f39d4bdc2d0a728b4568", @@ -1425,11 +1037,7 @@ { "traderId": "58330581ace78e27b8b10cee", "name": "skier", - "questTypes": [ - "Completion", - "Exploration", - "Elimination" - ], + "questTypes": ["Completion", "Exploration", "Elimination"], "rewardBaseWhitelist": [ "5a341c4086f77401f2541505", "5448e8d64bdc2dce718b4568", @@ -1452,11 +1060,7 @@ { "traderId": "5935c25fb3acc3127c3d8cd9", "name": "peacekeeper", - "questTypes": [ - "Completion", - "Exploration", - "Elimination" - ], + "questTypes": ["Completion", "Exploration", "Elimination"], "rewardBaseWhitelist": [ "543be6564bdc2df4348b4568", "5448e5284bdc2dcb718b4567", @@ -1474,10 +1078,7 @@ { "traderId": "5a7c2eca46aef81a7ca2145d", "name": "mechanic", - "questTypes": [ - "Completion", - "Exploration" - ], + "questTypes": ["Completion", "Exploration"], "rewardBaseWhitelist": [ "55818af64bdc2d5b648b4570", "5448bc234bdc2d3c308b4569", @@ -1498,11 +1099,7 @@ { "traderId": "5ac3b934156ae10c4430e83c", "name": "ragman", - "questTypes": [ - "Completion", - "Exploration", - "Elimination" - ], + "questTypes": ["Completion", "Exploration", "Elimination"], "rewardBaseWhitelist": [ "5a341c4086f77401f2541505", "5448e5724bdc2ddf718b4568", @@ -1519,11 +1116,7 @@ { "traderId": "5c0647fdd443bc2504c2d371", "name": "jaeger", - "questTypes": [ - "Completion", - "Exploration", - "Elimination" - ], + "questTypes": ["Completion", "Exploration", "Elimination"], "rewardBaseWhitelist": [ "5448f3ac4bdc2dce718b4569", "5c99f98d86f7745c314214b3", @@ -1545,11 +1138,7 @@ "Exploration": { "maxExtracts": 25, "maxExtractsWithSpecificExit": 12, - "possibleSkillRewards": [ - "Endurance", - "Strength", - "Vitality" - ], + "possibleSkillRewards": ["Endurance", "Strength", "Vitality"], "specificExits": { "probability": 0.4, "passageRequirementWhitelist": [ @@ -1563,11 +1152,7 @@ } }, "Completion": { - "possibleSkillRewards": [ - "Endurance", - "Strength", - "Vitality" - ], + "possibleSkillRewards": ["Endurance", "Strength", "Vitality"], "minRequestedAmount": 4, "maxRequestedAmount": 12, "uniqueItemCount": 4, @@ -1582,11 +1167,7 @@ "min": 1, "max": 15 }, - "possibleSkillRewards": [ - "Endurance", - "Strength", - "Vitality" - ], + "possibleSkillRewards": ["Endurance", "Strength", "Vitality"], "targets": [ { "key": "Savage", @@ -1679,41 +1260,26 @@ { "key": "Head", "relativeProbability": 1, - "data": [ - "Head" - ] + "data": ["Head"] }, { "key": "Chest", "relativeProbability": 5, - "data": [ - "Chest", - "Stomach" - ] + "data": ["Chest", "Stomach"] }, { "key": "Arms", "relativeProbability": 0.5, - "data": [ - "LeftArm", - "RightArm" - ] + "data": ["LeftArm", "RightArm"] }, { "key": "Legs", "relativeProbability": 1, - "data": [ - "LeftLeg", - "RightLeg" - ] + "data": ["LeftLeg", "RightLeg"] } ], "specificLocationProb": 0.15, - "distLocationBlacklist": [ - "laboratory", - "factory4_day", - "factory4_night" - ], + "distLocationBlacklist": ["laboratory", "factory4_day", "factory4_night"], "distProb": 0.15, "maxDist": 75, "minDist": 10, @@ -1729,116 +1295,84 @@ { "key": "Shotgun", "relativeProbability": 10, - "data": [ - "5b5f794b86f77409407a7f92" - ] + "data": ["5b5f794b86f77409407a7f92"] }, { "key": "Pistol", "relativeProbability": 10, - "data": [ - "5b5f792486f77447ed5636b3" - ] + "data": ["5b5f792486f77447ed5636b3"] }, { "key": "AssaultRifle", "relativeProbability": 3, - "data": [ - "5b5f78fc86f77409407a7f90" - ] + "data": ["5b5f78fc86f77409407a7f90"] }, { "key": "AssaultCarbine", "relativeProbability": 5, - "data": [ - "5b5f78e986f77447ed5636b1" - ] + "data": ["5b5f78e986f77447ed5636b1"] }, { "key": "SMG", "relativeProbability": 1, - "data": [ - "5b5f796a86f774093f2ed3c0" - ] + "data": ["5b5f796a86f774093f2ed3c0"] }, { "key": "Melee", "relativeProbability": 0, - "data": [ - "5b5f7a0886f77409407a7f96" - ] + "data": ["5b5f7a0886f77409407a7f96"] }, { "key": "DMR", "relativeProbability": 1, - "data": [ - "5b5f791486f774093f2ed3be" - ] + "data": ["5b5f791486f774093f2ed3be"] }, { "key": "BoltAction", "relativeProbability": 5, - "data": [ - "5b5f798886f77447ed5636b5" - ] + "data": ["5b5f798886f77447ed5636b5"] }, { "key": "MachineGun", "relativeProbability": 0, - "data": [ - "5b5f79a486f77409407a7f94" - ] + "data": ["5b5f79a486f77409407a7f94"] } ], "weaponRequirements": [ { "key": "Shotgun", "relativeProbability": 10, - "data": [ - "5447b6094bdc2dc3278b4567" - ] + "data": ["5447b6094bdc2dc3278b4567"] }, { "key": "Pistol", "relativeProbability": 10, - "data": [ - "5447b5cf4bdc2d65278b4567" - ] + "data": ["5447b5cf4bdc2d65278b4567"] }, { "key": "AssaultRifle", "relativeProbability": 3, - "data": [ - "5447b5f14bdc2d61278b4567" - ] + "data": ["5447b5f14bdc2d61278b4567"] }, { "key": "AssaultCarbine", "relativeProbability": 5, - "data": [ - "5447b5fc4bdc2d87278b4567" - ] + "data": ["5447b5fc4bdc2d87278b4567"] }, { "key": "MarksmanRifle", "relativeProbability": 1, - "data": [ - "5447b6194bdc2d67278b4567" - ] + "data": ["5447b6194bdc2d67278b4567"] }, { "key": "SniperRifle", "relativeProbability": 1, - "data": [ - "5447b6254bdc2dc3278b4568" - ] + "data": ["5447b6254bdc2dc3278b4568"] }, { "key": "SMG", "relativeProbability": 1, - "data": [ - "5447b5e04bdc2d62278b4567" - ] + "data": ["5447b5e04bdc2d62278b4567"] } ] }, @@ -1847,11 +1381,7 @@ "min": 16, "max": 40 }, - "possibleSkillRewards": [ - "Endurance", - "Strength", - "Vitality" - ], + "possibleSkillRewards": ["Endurance", "Strength", "Vitality"], "targets": [ { "key": "Savage", @@ -1944,41 +1474,26 @@ { "key": "Head", "relativeProbability": 1, - "data": [ - "Head" - ] + "data": ["Head"] }, { "key": "Chest", "relativeProbability": 5, - "data": [ - "Chest", - "Stomach" - ] + "data": ["Chest", "Stomach"] }, { "key": "Arms", "relativeProbability": 0.5, - "data": [ - "LeftArm", - "RightArm" - ] + "data": ["LeftArm", "RightArm"] }, { "key": "Legs", "relativeProbability": 1, - "data": [ - "LeftLeg", - "RightLeg" - ] + "data": ["LeftLeg", "RightLeg"] } ], "specificLocationProb": 0.2, - "distLocationBlacklist": [ - "laboratory", - "factory4_day", - "factory4_night" - ], + "distLocationBlacklist": ["laboratory", "factory4_day", "factory4_night"], "distProb": 0.2, "maxDist": 75, "minDist": 10, @@ -1994,116 +1509,84 @@ { "key": "Shotgun", "relativeProbability": 10, - "data": [ - "5b5f794b86f77409407a7f92" - ] + "data": ["5b5f794b86f77409407a7f92"] }, { "key": "Pistol", "relativeProbability": 10, - "data": [ - "5b5f792486f77447ed5636b3" - ] + "data": ["5b5f792486f77447ed5636b3"] }, { "key": "AssaultRifle", "relativeProbability": 3, - "data": [ - "5b5f78fc86f77409407a7f90" - ] + "data": ["5b5f78fc86f77409407a7f90"] }, { "key": "AssaultCarbine", "relativeProbability": 5, - "data": [ - "5b5f78e986f77447ed5636b1" - ] + "data": ["5b5f78e986f77447ed5636b1"] }, { "key": "SMG", "relativeProbability": 1, - "data": [ - "5b5f796a86f774093f2ed3c0" - ] + "data": ["5b5f796a86f774093f2ed3c0"] }, { "key": "Melee", "relativeProbability": 0, - "data": [ - "5b5f7a0886f77409407a7f96" - ] + "data": ["5b5f7a0886f77409407a7f96"] }, { "key": "DMR", "relativeProbability": 1, - "data": [ - "5b5f791486f774093f2ed3be" - ] + "data": ["5b5f791486f774093f2ed3be"] }, { "key": "BoltAction", "relativeProbability": 1, - "data": [ - "5b5f798886f77447ed5636b5" - ] + "data": ["5b5f798886f77447ed5636b5"] }, { "key": "MachineGun", "relativeProbability": 1, - "data": [ - "5b5f79a486f77409407a7f94" - ] + "data": ["5b5f79a486f77409407a7f94"] } ], "weaponRequirements": [ { "key": "Shotgun", "relativeProbability": 10, - "data": [ - "5447b6094bdc2dc3278b4567" - ] + "data": ["5447b6094bdc2dc3278b4567"] }, { "key": "Pistol", "relativeProbability": 10, - "data": [ - "5447b5cf4bdc2d65278b4567" - ] + "data": ["5447b5cf4bdc2d65278b4567"] }, { "key": "AssaultRifle", "relativeProbability": 3, - "data": [ - "5447b5f14bdc2d61278b4567" - ] + "data": ["5447b5f14bdc2d61278b4567"] }, { "key": "AssaultCarbine", "relativeProbability": 5, - "data": [ - "5447b5fc4bdc2d87278b4567" - ] + "data": ["5447b5fc4bdc2d87278b4567"] }, { "key": "MarksmanRifle", "relativeProbability": 1, - "data": [ - "5447b6194bdc2d67278b4567" - ] + "data": ["5447b6194bdc2d67278b4567"] }, { "key": "SniperRifle", "relativeProbability": 1, - "data": [ - "5447b6254bdc2dc3278b4568" - ] + "data": ["5447b6254bdc2dc3278b4568"] }, { "key": "SMG", "relativeProbability": 1, - "data": [ - "5447b5e04bdc2d62278b4567" - ] + "data": ["5447b5e04bdc2d62278b4567"] } ] }, @@ -2112,11 +1595,7 @@ "min": 41, "max": 100 }, - "possibleSkillRewards": [ - "Endurance", - "Strength", - "Vitality" - ], + "possibleSkillRewards": ["Endurance", "Strength", "Vitality"], "targets": [ { "key": "Savage", @@ -2209,41 +1688,26 @@ { "key": "Head", "relativeProbability": 1, - "data": [ - "Head" - ] + "data": ["Head"] }, { "key": "Chest", "relativeProbability": 5, - "data": [ - "Chest", - "Stomach" - ] + "data": ["Chest", "Stomach"] }, { "key": "Arms", "relativeProbability": 0.5, - "data": [ - "LeftArm", - "RightArm" - ] + "data": ["LeftArm", "RightArm"] }, { "key": "Legs", "relativeProbability": 1, - "data": [ - "LeftLeg", - "RightLeg" - ] + "data": ["LeftLeg", "RightLeg"] } ], "specificLocationProb": 0.25, - "distLocationBlacklist": [ - "laboratory", - "factory4_day", - "factory4_night" - ], + "distLocationBlacklist": ["laboratory", "factory4_day", "factory4_night"], "distProb": 0.25, "maxDist": 100, "minDist": 10, @@ -2259,116 +1723,84 @@ { "key": "Shotgun", "relativeProbability": 10, - "data": [ - "5b5f794b86f77409407a7f92" - ] + "data": ["5b5f794b86f77409407a7f92"] }, { "key": "Pistol", "relativeProbability": 10, - "data": [ - "5b5f792486f77447ed5636b3" - ] + "data": ["5b5f792486f77447ed5636b3"] }, { "key": "AssaultRifle", "relativeProbability": 3, - "data": [ - "5b5f78fc86f77409407a7f90" - ] + "data": ["5b5f78fc86f77409407a7f90"] }, { "key": "AssaultCarbine", "relativeProbability": 5, - "data": [ - "5b5f78e986f77447ed5636b1" - ] + "data": ["5b5f78e986f77447ed5636b1"] }, { "key": "SMG", "relativeProbability": 1, - "data": [ - "5b5f796a86f774093f2ed3c0" - ] + "data": ["5b5f796a86f774093f2ed3c0"] }, { "key": "Melee", "relativeProbability": 0, - "data": [ - "5b5f7a0886f77409407a7f96" - ] + "data": ["5b5f7a0886f77409407a7f96"] }, { "key": "DMR", "relativeProbability": 1, - "data": [ - "5b5f791486f774093f2ed3be" - ] + "data": ["5b5f791486f774093f2ed3be"] }, { "key": "BoltAction", "relativeProbability": 5, - "data": [ - "5b5f798886f77447ed5636b5" - ] + "data": ["5b5f798886f77447ed5636b5"] }, { "key": "MachineGun", "relativeProbability": 1, - "data": [ - "5b5f79a486f77409407a7f94" - ] + "data": ["5b5f79a486f77409407a7f94"] } ], "weaponRequirements": [ { "key": "Shotgun", "relativeProbability": 10, - "data": [ - "5447b6094bdc2dc3278b4567" - ] + "data": ["5447b6094bdc2dc3278b4567"] }, { "key": "Pistol", "relativeProbability": 10, - "data": [ - "5447b5cf4bdc2d65278b4567" - ] + "data": ["5447b5cf4bdc2d65278b4567"] }, { "key": "AssaultRifle", "relativeProbability": 3, - "data": [ - "5447b5f14bdc2d61278b4567" - ] + "data": ["5447b5f14bdc2d61278b4567"] }, { "key": "AssaultCarbine", "relativeProbability": 5, - "data": [ - "5447b5fc4bdc2d87278b4567" - ] + "data": ["5447b5fc4bdc2d87278b4567"] }, { "key": "MarksmanRifle", "relativeProbability": 1, - "data": [ - "5447b6194bdc2d67278b4567" - ] + "data": ["5447b6194bdc2d67278b4567"] }, { "key": "SniperRifle", "relativeProbability": 1, - "data": [ - "5447b6254bdc2dc3278b4568" - ] + "data": ["5447b6254bdc2dc3278b4568"] }, { "key": "SMG", "relativeProbability": 1, - "data": [ - "5447b5e04bdc2d62278b4567" - ] + "data": ["5447b5e04bdc2d62278b4567"] } ] } @@ -2379,144 +1811,46 @@ "5b3f15d486f77432d0509248", "65649eb40bf0ed77b8044453" ], - "rewardBlacklist": [ - "627bce33f21bc425b06ab967", - "59f32c3b86f77472a31742f0", - "59f32bb586f774757e1e8442" - ], + "rewardBlacklist": ["627bce33f21bc425b06ab967", "59f32c3b86f77472a31742f0", "59f32bb586f774757e1e8442"], "rewardAmmoStackMinSize": 5, - "freeChangesAvailable": 0, + "freeChangesAvailable": 0, "freeChanges": 0 }, { "id": "62825ef60e88d037dc1eb426", "name": "Daily_Savage", "side": "Scav", - "types": [ - "Exploration", - "Elimination", - "Completion" - ], + "types": ["Exploration", "Elimination", "Completion"], "resetTime": 86400, "numQuests": 1, "minPlayerLevel": 1, "rewardScaling": { - "levels": [ - 1, - 10, - 20, - 30, - 40, - 50, - 60 - ], - "experience": [ - 0, - 0, - 0, - 0, - 0, - 0, - 0 - ], - "roubles": [ - 11000, - 20000, - 32000, - 45000, - 58000, - 70000, - 82000 - ], - "gpCoins": [ - 1, - 1, - 2, - 2, - 4, - 4, - 5 - ], - "items": [ - 2, - 3, - 3, - 3, - 3, - 4, - 4 - ], - "reputation": [ - 0.02, - 0.02, - 0.03, - 0.03, - 0.04, - 0.04, - 0.05 - ], + "levels": [1, 10, 20, 30, 40, 50, 60], + "experience": [0, 0, 0, 0, 0, 0, 0], + "roubles": [11000, 20000, 32000, 45000, 58000, 70000, 82000], + "gpCoins": [1, 1, 2, 2, 4, 4, 5], + "items": [2, 3, 3, 3, 3, 4, 4], + "reputation": [0.02, 0.02, 0.03, 0.03, 0.04, 0.04, 0.05], "rewardSpread": 0.5, - "skillRewardChance": [ - 0, - 0, - 0, - 0, - 0, - 0, - 0 - ], - "skillPointReward": [ - 10, - 15, - 20, - 25, - 30, - 35, - 40 - ] + "skillRewardChance": [0, 0, 0, 0, 0, 0, 0], + "skillPointReward": [10, 15, 20, 25, 30, 35, 40] }, "locations": { - "any": [ - "any" - ], - "factory4_day": [ - "factory4_day", - "factory4_night" - ], - "bigmap": [ - "bigmap" - ], - "Woods": [ - "Woods" - ], - "Shoreline": [ - "Shoreline" - ], - "Interchange": [ - "Interchange" - ], - "Lighthouse": [ - "Lighthouse" - ], - "RezervBase": [ - "RezervBase" - ], - "TarkovStreets": [ - "TarkovStreets" - ], - "Sandbox": [ - "Sandbox" - ] + "any": ["any"], + "factory4_day": ["factory4_day", "factory4_night"], + "bigmap": ["bigmap"], + "Woods": ["Woods"], + "Shoreline": ["Shoreline"], + "Interchange": ["Interchange"], + "Lighthouse": ["Lighthouse"], + "RezervBase": ["RezervBase"], + "TarkovStreets": ["TarkovStreets"], + "Sandbox": ["Sandbox"] }, "traderWhitelist": [ { "traderId": "579dc571d53a0658a154fbec", - "questTypes": [ - "Completion", - "Exploration", - "Elimination", - "Pickup" - ], + "questTypes": ["Completion", "Exploration", "Elimination", "Pickup"], "rewardBaseWhitelist": [ "55818a684bdc2ddd698b456d", "55818a594bdc2db9688b456a", @@ -2530,30 +1864,16 @@ ], "questConfig": { "Exploration": { - "possibleSkillRewards": [ - "Endurance", - "Strength", - "Vitality" - ], + "possibleSkillRewards": ["Endurance", "Strength", "Vitality"], "maxExtracts": 4, "maxExtractsWithSpecificExit": 2, "specificExits": { "probability": 0.25, - "passageRequirementWhitelist": [ - "None", - "WorldEvent", - "Train", - "Reference", - "Empty" - ] + "passageRequirementWhitelist": ["None", "WorldEvent", "Train", "Reference", "Empty"] } }, "Pickup": { - "possibleSkillRewards": [ - "Endurance", - "Strength", - "Vitality" - ], + "possibleSkillRewards": ["Endurance", "Strength", "Vitality"], "ItemTypeToFetchWithMaxCount": [ { "itemType": "5b47574386f77428ca22b335", @@ -2614,11 +1934,7 @@ "maxItemFetchCount": 3 }, "Completion": { - "possibleSkillRewards": [ - "Endurance", - "Strength", - "Vitality" - ], + "possibleSkillRewards": ["Endurance", "Strength", "Vitality"], "minRequestedAmount": 1, "maxRequestedAmount": 3, "uniqueItemCount": 1, @@ -2633,11 +1949,7 @@ "min": 1, "max": 15 }, - "possibleSkillRewards": [ - "Endurance", - "Strength", - "Vitality" - ], + "possibleSkillRewards": ["Endurance", "Strength", "Vitality"], "targets": [ { "key": "AnyPmc", @@ -2653,40 +1965,27 @@ { "key": "Head", "relativeProbability": 1, - "data": [ - "Head" - ] + "data": ["Head"] }, { "key": "Chest", "relativeProbability": 10, - "data": [ - "Chest", - "Stomach" - ] + "data": ["Chest", "Stomach"] }, { "key": "Arms", "relativeProbability": 0.5, - "data": [ - "LeftArm", - "RightArm" - ] + "data": ["LeftArm", "RightArm"] }, { "key": "Legs", "relativeProbability": 1, - "data": [ - "LeftLeg", - "RightLeg" - ] + "data": ["LeftLeg", "RightLeg"] } ], "specificLocationProb": 0.15, - "distLocationBlacklist": [ - "laboratory" - ], - "distProb": 0.20, + "distLocationBlacklist": ["laboratory"], + "distProb": 0.2, "maxDist": 75, "minDist": 10, "maxKills": 3, @@ -2701,116 +2000,84 @@ { "key": "Shotgun", "relativeProbability": 10, - "data": [ - "5b5f794b86f77409407a7f92" - ] + "data": ["5b5f794b86f77409407a7f92"] }, { "key": "Pistol", "relativeProbability": 10, - "data": [ - "5b5f792486f77447ed5636b3" - ] + "data": ["5b5f792486f77447ed5636b3"] }, { "key": "AssaultRifle", "relativeProbability": 3, - "data": [ - "5b5f78fc86f77409407a7f90" - ] + "data": ["5b5f78fc86f77409407a7f90"] }, { "key": "AssaultCarbine", "relativeProbability": 5, - "data": [ - "5b5f78e986f77447ed5636b1" - ] + "data": ["5b5f78e986f77447ed5636b1"] }, { "key": "SMG", "relativeProbability": 1, - "data": [ - "5b5f796a86f774093f2ed3c0" - ] + "data": ["5b5f796a86f774093f2ed3c0"] }, { "key": "Melee", "relativeProbability": 0, - "data": [ - "5b5f7a0886f77409407a7f96" - ] + "data": ["5b5f7a0886f77409407a7f96"] }, { "key": "DMR", "relativeProbability": 1, - "data": [ - "5b5f791486f774093f2ed3be" - ] + "data": ["5b5f791486f774093f2ed3be"] }, { "key": "BoltAction", "relativeProbability": 5, - "data": [ - "5b5f798886f77447ed5636b5" - ] + "data": ["5b5f798886f77447ed5636b5"] }, { "key": "MachineGun", "relativeProbability": 0, - "data": [ - "5b5f79a486f77409407a7f94" - ] + "data": ["5b5f79a486f77409407a7f94"] } ], "weaponRequirements": [ { "key": "Shotgun", "relativeProbability": 10, - "data": [ - "5447b6094bdc2dc3278b4567" - ] + "data": ["5447b6094bdc2dc3278b4567"] }, { "key": "Pistol", "relativeProbability": 10, - "data": [ - "5447b5cf4bdc2d65278b4567" - ] + "data": ["5447b5cf4bdc2d65278b4567"] }, { "key": "AssaultRifle", "relativeProbability": 3, - "data": [ - "5447b5f14bdc2d61278b4567" - ] + "data": ["5447b5f14bdc2d61278b4567"] }, { "key": "AssaultCarbine", "relativeProbability": 5, - "data": [ - "5447b5fc4bdc2d87278b4567" - ] + "data": ["5447b5fc4bdc2d87278b4567"] }, { "key": "MarksmanRifle", "relativeProbability": 1, - "data": [ - "5447b6194bdc2d67278b4567" - ] + "data": ["5447b6194bdc2d67278b4567"] }, { "key": "SniperRifle", "relativeProbability": 1, - "data": [ - "5447b6254bdc2dc3278b4568" - ] + "data": ["5447b6254bdc2dc3278b4568"] }, { "key": "SMG", "relativeProbability": 1, - "data": [ - "5447b5e04bdc2d62278b4567" - ] + "data": ["5447b5e04bdc2d62278b4567"] } ] }, @@ -2819,11 +2086,7 @@ "min": 16, "max": 100 }, - "possibleSkillRewards": [ - "Endurance", - "Strength", - "Vitality" - ], + "possibleSkillRewards": ["Endurance", "Strength", "Vitality"], "targets": [ { "key": "AnyPmc", @@ -2839,39 +2102,26 @@ { "key": "Head", "relativeProbability": 1, - "data": [ - "Head" - ] + "data": ["Head"] }, { "key": "Chest", "relativeProbability": 5, - "data": [ - "Chest", - "Stomach" - ] + "data": ["Chest", "Stomach"] }, { "key": "Arms", "relativeProbability": 0.5, - "data": [ - "LeftArm", - "RightArm" - ] + "data": ["LeftArm", "RightArm"] }, { "key": "Legs", "relativeProbability": 1, - "data": [ - "LeftLeg", - "RightLeg" - ] + "data": ["LeftLeg", "RightLeg"] } ], "specificLocationProb": 0.25, - "distLocationBlacklist": [ - "laboratory" - ], + "distLocationBlacklist": ["laboratory"], "distProb": 0.25, "maxDist": 75, "minDist": 10, @@ -2887,116 +2137,84 @@ { "key": "Shotgun", "relativeProbability": 1, - "data": [ - "5b5f794b86f77409407a7f92" - ] + "data": ["5b5f794b86f77409407a7f92"] }, { "key": "Pistol", "relativeProbability": 1, - "data": [ - "5b5f792486f77447ed5636b3" - ] + "data": ["5b5f792486f77447ed5636b3"] }, { "key": "AssaultRifle", "relativeProbability": 2, - "data": [ - "5b5f78fc86f77409407a7f90" - ] + "data": ["5b5f78fc86f77409407a7f90"] }, { "key": "AssaultCarbine", "relativeProbability": 1, - "data": [ - "5b5f78e986f77447ed5636b1" - ] + "data": ["5b5f78e986f77447ed5636b1"] }, { "key": "SMG", "relativeProbability": 1, - "data": [ - "5b5f796a86f774093f2ed3c0" - ] + "data": ["5b5f796a86f774093f2ed3c0"] }, { "key": "Melee", "relativeProbability": 1, - "data": [ - "5b5f7a0886f77409407a7f96" - ] + "data": ["5b5f7a0886f77409407a7f96"] }, { "key": "DMR", "relativeProbability": 1, - "data": [ - "5b5f791486f774093f2ed3be" - ] + "data": ["5b5f791486f774093f2ed3be"] }, { "key": "BoltAction", "relativeProbability": 1, - "data": [ - "5b5f798886f77447ed5636b5" - ] + "data": ["5b5f798886f77447ed5636b5"] }, { "key": "MachineGun", "relativeProbability": 1, - "data": [ - "5b5f79a486f77409407a7f94" - ] + "data": ["5b5f79a486f77409407a7f94"] } ], "weaponRequirements": [ { "key": "Shotgun", "relativeProbability": 10, - "data": [ - "5447b6094bdc2dc3278b4567" - ] + "data": ["5447b6094bdc2dc3278b4567"] }, { "key": "Pistol", "relativeProbability": 10, - "data": [ - "5447b5cf4bdc2d65278b4567" - ] + "data": ["5447b5cf4bdc2d65278b4567"] }, { "key": "AssaultRifle", "relativeProbability": 3, - "data": [ - "5447b5f14bdc2d61278b4567" - ] + "data": ["5447b5f14bdc2d61278b4567"] }, { "key": "AssaultCarbine", "relativeProbability": 5, - "data": [ - "5447b5fc4bdc2d87278b4567" - ] + "data": ["5447b5fc4bdc2d87278b4567"] }, { "key": "MarksmanRifle", "relativeProbability": 1, - "data": [ - "5447b6194bdc2d67278b4567" - ] + "data": ["5447b6194bdc2d67278b4567"] }, { "key": "SniperRifle", "relativeProbability": 1, - "data": [ - "5447b6254bdc2dc3278b4568" - ] + "data": ["5447b6254bdc2dc3278b4568"] }, { "key": "SMG", "relativeProbability": 1, - "data": [ - "5447b5e04bdc2d62278b4567" - ] + "data": ["5447b5e04bdc2d62278b4567"] } ] } @@ -3007,13 +2225,9 @@ "5b3f15d486f77432d0509248", "65649eb40bf0ed77b8044453" ], - "rewardBlacklist": [ - "627bce33f21bc425b06ab967", - "59f32c3b86f77472a31742f0", - "59f32bb586f774757e1e8442" - ], + "rewardBlacklist": ["627bce33f21bc425b06ab967", "59f32c3b86f77472a31742f0", "59f32bb586f774757e1e8442"], "rewardAmmoStackMinSize": 5, - "freeChangesAvailable": 0, + "freeChangesAvailable": 0, "freeChanges": 0 } ], @@ -3031,4 +2245,4 @@ "TarkovStreets": "5714dc692459777137212e12", "Sandbox": "653e6760052c01c1c805532f" } -} \ No newline at end of file +} diff --git a/project/assets/configs/ragfair.json b/project/assets/configs/ragfair.json index 5475ae9b..1c58e195 100644 --- a/project/assets/configs/ragfair.json +++ b/project/assets/configs/ragfair.json @@ -276,10 +276,7 @@ }, "armor": { "removeRemovablePlateChance": 40, - "plateSlotIdToRemovePool": [ - "front_plate", - "back_plate" - ] + "plateSlotIdToRemovePool": ["front_plate", "back_plate"] }, "itemPriceMultiplier": { "5737292724597765e5728562": 6, @@ -303,7 +300,7 @@ "62e910aaf957f2915e0a5e36", "5447e1d04bdc2dff2f8b4567", "57bef4c42459772e8d35a53b", - "55802f4a4bdc2ddb688b4569" + "55802f4a4bdc2ddb688b4569" ], "removeSeasonalItemsWhenNotInEvent": true, "blacklist": { @@ -314,10 +311,7 @@ "traderItems": false, "armorPlate": { "maxProtectionLevel": 4, - "ignoreSlots": [ - "right_side_plate", - "left_side_plate" - ] + "ignoreSlots": ["right_side_plate", "left_side_plate"] }, "enableCustomItemCategoryList": false, "customItemCategoryList": [] @@ -337,4 +331,4 @@ } } } -} \ No newline at end of file +} diff --git a/project/assets/configs/repair.json b/project/assets/configs/repair.json index 8d2f7980..cff2d136 100644 --- a/project/assets/configs/repair.json +++ b/project/assets/configs/repair.json @@ -12,9 +12,9 @@ "trader": 0.6 }, "weaponTreatment": { - "critSuccessChance": 0.10, + "critSuccessChance": 0.1, "critSuccessAmount": 4, - "critFailureChance": 0.10, + "critFailureChance": 0.1, "critFailureAmount": 4, "pointGainMultiplier": 0.6 }, @@ -163,7 +163,7 @@ "MalfunctionProtections": { "valuesMinMax": { "min": 0.75, - "max": 0.90 + "max": 0.9 }, "activeDurabilityPercentMinMax": { "min": 75, @@ -183,4 +183,4 @@ } } } -} \ No newline at end of file +} diff --git a/project/assets/configs/scavcase.json b/project/assets/configs/scavcase.json index ebdfd9b1..b95a06d2 100644 --- a/project/assets/configs/scavcase.json +++ b/project/assets/configs/scavcase.json @@ -86,9 +86,7 @@ "ammoRewardChancePercent": 10, "minStackSize": 10, "ammoRewardBlacklist": { - "common": [ - "59e690b686f7746c9f75e848" - ], + "common": ["59e690b686f7746c9f75e848"], "rare": [], "superrare": [] }, @@ -110,4 +108,4 @@ "allowMultipleMoneyRewardsPerRarity": false, "allowMultipleAmmoRewardsPerRarity": true, "allowBossItemsAsRewards": false -} \ No newline at end of file +} diff --git a/project/assets/configs/seasonalevents.json b/project/assets/configs/seasonalevents.json index 7499ca10..d93d2df4 100644 --- a/project/assets/configs/seasonalevents.json +++ b/project/assets/configs/seasonalevents.json @@ -721,4 +721,4 @@ "endMonth": "2" } ] -} \ No newline at end of file +} diff --git a/project/assets/configs/trader.json b/project/assets/configs/trader.json index 24905f12..575b8c82 100644 --- a/project/assets/configs/trader.json +++ b/project/assets/configs/trader.json @@ -202,11 +202,11 @@ } }, "chancePlateExistsInArmorPercent": { - "3": 95, - "4": 75, - "5": 25, - "6": 10 - }, + "3": 95, + "4": 75, + "5": 25, + "6": 10 + }, "armorMaxDurabilityPercentMinMax": { "current": { "min": 50, diff --git a/project/assets/configs/weather.json b/project/assets/configs/weather.json index 181bb86a..997a34b9 100644 --- a/project/assets/configs/weather.json +++ b/project/assets/configs/weather.json @@ -2,94 +2,32 @@ "acceleration": 7, "weather": { "clouds": { - "values": [ - -1.5, - -1, - 0, - 0.5, - 1, - 1.5 - ], - "weights": [ - 60, - 50, - 15, - 5, - 4, - 3 - ] + "values": [-1.5, -1, 0, 0.5, 1, 1.5], + "weights": [60, 50, 15, 5, 4, 3] }, "windSpeed": { - "values": [ - 0, - 1, - 2, - 3 - ], - "weights": [ - 4, - 3, - 2, - 1 - ] + "values": [0, 1, 2, 3], + "weights": [4, 3, 2, 1] }, "windDirection": { - "values": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8 - ], - "weights": [ - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1 - ] + "values": [1, 2, 3, 4, 5, 6, 7, 8], + "weights": [1, 1, 1, 1, 1, 1, 1, 1] }, "windGustiness": { "min": 0, "max": 1 }, "rain": { - "values": [ - 1, - 2, - 3 - ], - "weights": [ - 25, - 1, - 1 - ] + "values": [1, 2, 3], + "weights": [25, 1, 1] }, "rainIntensity": { "min": 0, "max": 1 }, "fog": { - "values": [ - 0.002, - 0.004, - 0.008, - 0.012, - 0.087 - ], - "weights": [ - 20, - 8, - 5, - 5, - 1 - ] + "values": [0.002, 0.004, 0.008, 0.012, 0.087], + "weights": [20, 8, 5, 5, 1] }, "temp": { "min": 0, @@ -100,55 +38,55 @@ "max": 764 } }, - "seasonDates": [ - { - "seasonType": 0, - "name": "SUMMER", - "startDay": "2", + "seasonDates": [ + { + "seasonType": 0, + "name": "SUMMER", + "startDay": "2", "startMonth": "6", "endDay": "1", "endMonth": "8" - }, - { - "seasonType": 1, - "name": "AUTUMN", - "startDay": "2", + }, + { + "seasonType": 1, + "name": "AUTUMN", + "startDay": "2", "startMonth": "8", "endDay": "1", "endMonth": "11" - }, - { - "seasonType": 2, - "name": "WINTER_END", - "startDay": "2", + }, + { + "seasonType": 2, + "name": "WINTER_END", + "startDay": "2", "startMonth": "11", "endDay": "31", "endMonth": "12" - }, - { - "seasonType": 2, - "name": "WINTER_START", - "startDay": "1", + }, + { + "seasonType": 2, + "name": "WINTER_START", + "startDay": "1", "startMonth": "1", "endDay": "24", "endMonth": "3" - }, - { - "seasonType": 3, - "name": "SPRING", - "startDay": "25", + }, + { + "seasonType": 3, + "name": "SPRING", + "startDay": "25", "startMonth": "3", "endDay": "1", "endMonth": "6" - }, - { - "seasonType": 4, - "name": "STORM", - "startDay": "24", + }, + { + "seasonType": 4, + "name": "STORM", + "startDay": "24", "startMonth": "10", "endDay": "4", "endMonth": "11" - } - ], - "overrideSeason": null -} \ No newline at end of file + } + ], + "overrideSeason": null +} diff --git a/project/biome.jsonc b/project/biome.jsonc index 1507924e..54b3e0e7 100644 --- a/project/biome.jsonc +++ b/project/biome.jsonc @@ -34,16 +34,16 @@ "enabled": true, "formatWithErrors": false, "ignore": [ - "**/.git", - "**/.pkg-cache", - "**/.vscode", - "**/build", - "**/node_modules", - "**/types", - "**/tests/__cache__", - "**/tests/__coverage__", - "**/.editorconfig" - ], + "**/.git", + "**/.pkg-cache", + "**/.vscode", + "**/build", + "**/node_modules", + "**/types", + "**/tests/__cache__", + "**/tests/__coverage__", + "**/.editorconfig" + ], "attributePosition": "auto", "indentStyle": "space", "indentWidth": 4, diff --git a/project/gulpfile.mjs b/project/gulpfile.mjs index fa1d1617..845ca61b 100644 --- a/project/gulpfile.mjs +++ b/project/gulpfile.mjs @@ -37,8 +37,7 @@ const licenseFile = "../LICENSE.md"; /** * Transpile src files into Javascript with SWC */ -const compile = async () => -{ +const compile = async () => { // Compile TypeScript files using SWC await exec("npx swc src -d obj", { stdio: "inherit" }); @@ -46,29 +45,23 @@ const compile = async () => const srcDir = path.join("obj", "src"); const destDir = path.join("obj"); - try - { + try { const entities = await fs.readdir(srcDir); - for (const entity of entities) - { + for (const entity of entities) { const srcPath = path.join(srcDir, entity); const destPath = path.join(destDir, entity); await fs.move(srcPath, destPath, { overwrite: true }); } // After moving all contents, remove the now-empty /obj/src directory await fs.remove(srcDir); - } - catch (error) - { + } catch (error) { console.error("An error occurred during the merge operation:", error); } }; // Packaging -const fetchPackageImage = async () => -{ - try - { +const fetchPackageImage = async () => { + try { const output = "./.pkg-cache/v3.5"; const fetchedPkg = await pkgfetch.need({ arch: targetArch, @@ -79,18 +72,14 @@ const fetchPackageImage = async () => console.log(`fetched node binary at ${fetchedPkg}`); const builtPkg = fetchedPkg.replace("node", "built"); await fs.copyFile(fetchedPkg, builtPkg); - } - catch (e) - { + } catch (e) { console.error(`Error while fetching and patching package image: ${e.message}`); console.error(e.stack); } }; -const updateBuildProperties = async () => -{ - if (targetPlatform !== "win32") - { +const updateBuildProperties = async () => { + if (targetPlatform !== "win32") { // can't modify executable's resource on non-windows build return; } @@ -110,12 +99,15 @@ const updateBuildProperties = async () => const vi = ResEdit.Resource.VersionInfo.fromEntries(res.entries)[0]; - vi.setStringValues({ lang: 1033, codepage: 1200 }, { - ProductName: manifest.author, - FileDescription: manifest.description, - CompanyName: manifest.name, - LegalCopyright: manifest.license, - }); + vi.setStringValues( + { lang: 1033, codepage: 1200 }, + { + ProductName: manifest.author, + FileDescription: manifest.description, + CompanyName: manifest.name, + LegalCopyright: manifest.license, + }, + ); vi.removeStringValue({ lang: 1033, codepage: 1200 }, "OriginalFilename"); vi.removeStringValue({ lang: 1033, codepage: 1200 }, "InternalName"); vi.setFileVersion(...manifest.version.split(".").map(Number)); @@ -129,15 +121,14 @@ const updateBuildProperties = async () => * Copy various asset files to the destination directory */ const copyAssets = () => - gulp.src(["assets/**/*.json", "assets/**/*.json5", "assets/**/*.png", "assets/**/*.jpg", "assets/**/*.ico"]).pipe( - gulp.dest(dataDir), - ); + gulp + .src(["assets/**/*.json", "assets/**/*.json5", "assets/**/*.png", "assets/**/*.jpg", "assets/**/*.ico"]) + .pipe(gulp.dest(dataDir)); /** * Download pnpm executable */ -const downloadPnpm = async () => -{ +const downloadPnpm = async () => { // Please ensure that the @pnpm/exe version in devDependencies is pinned to a specific version. If it's not, the // following task will download *all* versions that are compatible with the semver range specified. const pnpmVersion = manifest.devDependencies["@pnpm/exe"]; @@ -145,7 +136,9 @@ const downloadPnpm = async () => const npmResult = await exec(`npm view ${pnpmPackageName}@${pnpmVersion} dist.tarball`, { stdout: "pipe" }); const pnpmLink = npmResult.stdout.trim(); console.log(`Downloading pnpm binary from ${pnpmLink}`); - download(pnpmLink).pipe(decompress({ strip: 1 })).pipe(gulp.dest(path.join(dataDir, "@pnpm", "exe"))); + download(pnpmLink) + .pipe(decompress({ strip: 1 })) + .pipe(gulp.dest(path.join(dataDir, "@pnpm", "exe"))); }; /** @@ -156,10 +149,8 @@ const copyLicense = () => gulp.src([licenseFile]).pipe(rename("LICENSE-Server.tx /** * Writes the latest build data to the core.json and build.json configuration files. */ -const writeBuildDataToJSON = async () => -{ - try - { +const writeBuildDataToJSON = async () => { + try { // Fetch the latest Git commit hash const gitResult = await exec("git rev-parse HEAD", { stdout: "pipe" }); @@ -180,9 +171,7 @@ const writeBuildDataToJSON = async () => buildInfo.buildTime = coreParsed.buildTime; buildInfo.sptVersion = coreParsed.sptVersion; await fs.writeFile(buildJsonPath, JSON.stringify(buildInfo, null, 4)); - } - catch (error) - { + } catch (error) { throw new Error(`Failed to write commit hash to core.json: ${error.message}`); } }; @@ -190,8 +179,7 @@ const writeBuildDataToJSON = async () => /** * Create a hash file for asset checks */ -const createHashFile = async () => -{ +const createHashFile = async () => { const hashFileDir = path.resolve(dataDir, "checks.dat"); const assetData = await loadRecursiveAsync("assets/"); const assetDataString = Buffer.from(JSON.stringify(assetData), "utf-8").toString("base64"); @@ -218,18 +206,13 @@ const cleanCompiled = async () => await fs.rm("./obj", { recursive: true, force: * @param {string[]} files * @returns {Promise} */ -const getJSONFiles = async (dir, files = []) => -{ +const getJSONFiles = async (dir, files = []) => { const fileList = await fs.readdir(dir); - for (const file of fileList) - { + for (const file of fileList) { const name = path.resolve(dir, file); - if ((await fs.stat(name)).isDirectory()) - { + if ((await fs.stat(name)).isDirectory()) { getJSONFiles(name, files); - } - else if (name.slice(-5) === ".json") - { + } else if (name.slice(-5) === ".json") { files.push(name); } } @@ -239,21 +222,16 @@ const getJSONFiles = async (dir, files = []) => /** * Goes through every json file in assets and makes sure they're valid json. */ -const validateJSONs = async () => -{ +const validateJSONs = async () => { const assetsPath = path.resolve("assets"); const jsonFileList = await getJSONFiles(assetsPath); let jsonFileInProcess = ""; - try - { - for (const jsonFile of jsonFileList) - { + try { + for (const jsonFile of jsonFileList) { jsonFileInProcess = jsonFile; JSON.parse(await fs.readFile(jsonFile)); } - } - catch (error) - { + } catch (error) { throw new Error(`${error.message} | ${jsonFileInProcess}`); } }; @@ -264,8 +242,7 @@ const validateJSONs = async () => * @param {crypto.BinaryLike} data * @returns {string} */ -const generateHashForData = (data) => -{ +const generateHashForData = (data) => { const hashSum = crypto.createHash("sha1"); hashSum.update(data); return hashSum.digest("hex"); @@ -277,21 +254,16 @@ const generateHashForData = (data) => * @param {fs.PathLike} filepath * @returns {} */ -const loadRecursiveAsync = async (filepath) => -{ +const loadRecursiveAsync = async (filepath) => { const result = {}; const filesList = await fs.readdir(filepath); - for (const file of filesList) - { + for (const file of filesList) { const curPath = path.parse(path.join(filepath, file)); - if ((await fs.stat(path.join(curPath.dir, curPath.base))).isDirectory()) - { + if ((await fs.stat(path.join(curPath.dir, curPath.base))).isDirectory()) { result[curPath.name] = loadRecursiveAsync(`${filepath}${file}/`); - } - else if (curPath.ext === ".json") - { + } else if (curPath.ext === ".json") { result[curPath.name] = generateHashForData(await fs.readFile(`${filepath}${file}`)); } } @@ -299,8 +271,7 @@ const loadRecursiveAsync = async (filepath) => // set all loadRecursive to be executed asynchronously const resEntries = Object.entries(result); const resResolved = await Promise.all(resEntries.map((ent) => ent[1])); - for (let resIdx = 0; resIdx < resResolved.length; resIdx++) - { + for (let resIdx = 0; resIdx < resResolved.length; resIdx++) { resEntries[resIdx][1] = resResolved[resIdx]; } @@ -309,8 +280,7 @@ const loadRecursiveAsync = async (filepath) => }; // Main Tasks Generation -const build = (packagingType) => -{ +const build = (packagingType) => { const anonPackaging = () => packaging(entries[packagingType]); anonPackaging.displayName = `packaging-${packagingType}`; const tasks = [ @@ -327,11 +297,9 @@ const build = (packagingType) => }; // Packaging Arguments -const packaging = async (entry) => -{ +const packaging = async (entry) => { const target = `${nodeVersion}-${targetPlatform}-${targetArch}`; - try - { + try { await pkg.exec([ entry, "--compress", @@ -344,9 +312,7 @@ const packaging = async (entry) => pkgConfig, "--public", ]); - } - catch (error) - { + } catch (error) { console.error(`Error occurred during packaging: ${error}`); } }; @@ -361,8 +327,7 @@ gulp.task( "run:debug", async () => await exec("ts-node-dev -r tsconfig-paths/register src/ide/TestEntry.ts", { stdio }), ); -gulp.task("run:profiler", async () => -{ +gulp.task("run:profiler", async () => { await cleanCompiled(); await compile(); await exec("node --prof --inspect --trace-warnings obj/ide/TestEntry.js", { stdio }); diff --git a/project/pkgconfig.json b/project/pkgconfig.json index 7c438a55..e5a9d2ce 100644 --- a/project/pkgconfig.json +++ b/project/pkgconfig.json @@ -1,11 +1,6 @@ { "pkg": { - "scripts": [ - "obj/**/*.js" - ], - "assets": [ - "obj/**/*.js.map", - "package.json" - ] + "scripts": ["obj/**/*.js"], + "assets": ["obj/**/*.js.map", "package.json"] } } diff --git a/project/src/ErrorHandler.ts b/project/src/ErrorHandler.ts index 6e6fa673..17ea9bab 100644 --- a/project/src/ErrorHandler.ts +++ b/project/src/ErrorHandler.ts @@ -3,23 +3,19 @@ import { ILogger } from "@spt/models/spt/utils/ILogger"; import { AsyncQueue } from "@spt/utils/AsyncQueue"; import { WinstonMainLogger } from "@spt/utils/logging/WinstonMainLogger"; -export class ErrorHandler -{ +export class ErrorHandler { private logger: ILogger; private readLine: readline.Interface; - constructor() - { + constructor() { this.logger = new WinstonMainLogger(new AsyncQueue()); this.readLine = readline.createInterface({ input: process.stdin, output: process.stdout }); } - public handleCriticalError(err: Error): void - { + public handleCriticalError(err: Error): void { this.logger.error("The application had a critical error and failed to run"); this.logger.error(`Exception produced: ${err.name}`); - if (err.stack) - { + if (err.stack) { this.logger.error(`\nStacktrace:\n${err.stack}`); } diff --git a/project/src/Program.ts b/project/src/Program.ts index 2d58379b..167cdc94 100644 --- a/project/src/Program.ts +++ b/project/src/Program.ts @@ -1,25 +1,21 @@ -import { container } from "tsyringe"; -import { Container } from "@spt/di/Container"; import { ErrorHandler } from "@spt/ErrorHandler"; +import { Container } from "@spt/di/Container"; import type { PreSptModLoader } from "@spt/loaders/PreSptModLoader"; import { App } from "@spt/utils/App"; import { Watermark } from "@spt/utils/Watermark"; +import { container } from "tsyringe"; -export class Program -{ +export class Program { private errorHandler: ErrorHandler; - constructor() - { + constructor() { // set window properties process.stdout.setEncoding("utf8"); process.title = "SPT Server"; this.errorHandler = new ErrorHandler(); } - public async start(): Promise - { - try - { + public async start(): Promise { + try { Container.registerTypes(container); const childContainer = container.createChildContainer(); const watermark = childContainer.resolve("Watermark"); @@ -31,9 +27,7 @@ export class Program Container.registerPostLoadTypes(container, childContainer); childContainer.resolve("App").load(); - } - catch (err: any) - { + } catch (err: any) { this.errorHandler.handleCriticalError(err instanceof Error ? err : new Error(err)); } } diff --git a/project/src/callbacks/AchievementCallbacks.ts b/project/src/callbacks/AchievementCallbacks.ts index 960666e6..6f5925b7 100644 --- a/project/src/callbacks/AchievementCallbacks.ts +++ b/project/src/callbacks/AchievementCallbacks.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { AchievementController } from "@spt/controllers/AchievementController"; import { ProfileController } from "@spt/controllers/ProfileController"; import { IEmptyRequestData } from "@spt/models/eft/common/IEmptyRequestData"; @@ -6,16 +5,15 @@ import { IGetBodyResponseData } from "@spt/models/eft/httpResponse/IGetBodyRespo import { ICompletedAchievementsResponse } from "@spt/models/eft/profile/ICompletedAchievementsResponse"; import { IGetAchievementsResponse } from "@spt/models/eft/profile/IGetAchievementsResponse"; import { HttpResponseUtil } from "@spt/utils/HttpResponseUtil"; +import { inject, injectable } from "tsyringe"; @injectable() -export class AchievementCallbacks -{ +export class AchievementCallbacks { constructor( @inject("AchievementController") protected achievementController: AchievementController, @inject("ProfileController") protected profileController: ProfileController, @inject("HttpResponseUtil") protected httpResponse: HttpResponseUtil, - ) - {} + ) {} /** * Handle client/achievement/list @@ -24,8 +22,7 @@ export class AchievementCallbacks url: string, info: IEmptyRequestData, sessionID: string, - ): IGetBodyResponseData - { + ): IGetBodyResponseData { return this.httpResponse.getBody(this.achievementController.getAchievements(sessionID)); } @@ -36,8 +33,7 @@ export class AchievementCallbacks url: string, info: IEmptyRequestData, sessionID: string, - ): IGetBodyResponseData - { + ): IGetBodyResponseData { return this.httpResponse.getBody(this.achievementController.getAchievementStatistics(sessionID)); } } diff --git a/project/src/callbacks/BotCallbacks.ts b/project/src/callbacks/BotCallbacks.ts index ff72176c..52c4d551 100644 --- a/project/src/callbacks/BotCallbacks.ts +++ b/project/src/callbacks/BotCallbacks.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { BotController } from "@spt/controllers/BotController"; import { IGenerateBotsRequestData } from "@spt/models/eft/bot/IGenerateBotsRequestData"; import { IEmptyRequestData } from "@spt/models/eft/common/IEmptyRequestData"; @@ -6,23 +5,21 @@ import { IBotBase } from "@spt/models/eft/common/tables/IBotBase"; import { Difficulties } from "@spt/models/eft/common/tables/IBotType"; import { IGetBodyResponseData } from "@spt/models/eft/httpResponse/IGetBodyResponseData"; import { HttpResponseUtil } from "@spt/utils/HttpResponseUtil"; +import { inject, injectable } from "tsyringe"; @injectable() -export class BotCallbacks -{ +export class BotCallbacks { constructor( @inject("BotController") protected botController: BotController, @inject("HttpResponseUtil") protected httpResponse: HttpResponseUtil, - ) - {} + ) {} /** * Handle singleplayer/settings/bot/limit * Is called by client to define each bot roles wave limit * @returns string */ - public getBotLimit(url: string, info: IEmptyRequestData, sessionID: string): string - { + public getBotLimit(url: string, info: IEmptyRequestData, sessionID: string): string { const splittedUrl = url.split("/"); const type = splittedUrl[splittedUrl.length - 1]; return this.httpResponse.noBody(this.botController.getBotPresetGenerationLimit(type)); @@ -32,13 +29,11 @@ export class BotCallbacks * Handle singleplayer/settings/bot/difficulty * @returns string */ - public getBotDifficulty(url: string, info: IEmptyRequestData, sessionID: string): string - { + public getBotDifficulty(url: string, info: IEmptyRequestData, sessionID: string): string { const splittedUrl = url.split("/"); const type = splittedUrl[splittedUrl.length - 2].toLowerCase(); const difficulty = splittedUrl[splittedUrl.length - 1]; - if (difficulty === "core") - { + if (difficulty === "core") { return this.httpResponse.noBody(this.botController.getBotCoreDifficulty()); } return this.httpResponse.noBody(this.botController.getBotDifficulty(type, difficulty)); @@ -52,8 +47,7 @@ export class BotCallbacks url: string, info: IEmptyRequestData, sessionID: string, - ): Record - { + ): Record { return this.httpResponse.noBody(this.botController.getAllBotDifficulties()); } @@ -65,8 +59,7 @@ export class BotCallbacks url: string, info: IGenerateBotsRequestData, sessionID: string, - ): Promise> - { + ): Promise> { return this.httpResponse.getBody(await this.botController.generate(sessionID, info)); } @@ -74,8 +67,7 @@ export class BotCallbacks * Handle singleplayer/settings/bot/maxCap * @returns string */ - public getBotCap(url: string, info: any, sessionID: string): string - { + public getBotCap(url: string, info: any, sessionID: string): string { const splitUrl = url.split("/"); const location = splitUrl[splitUrl.length - 1]; return this.httpResponse.noBody(this.botController.getBotCap(location)); @@ -85,8 +77,7 @@ export class BotCallbacks * Handle singleplayer/settings/bot/getBotBehaviours * @returns string */ - public getBotBehaviours(): string - { + public getBotBehaviours(): string { return this.httpResponse.noBody(this.botController.getAiBotBrainTypes()); } } diff --git a/project/src/callbacks/BuildsCallbacks.ts b/project/src/callbacks/BuildsCallbacks.ts index 10813db1..358522bf 100644 --- a/project/src/callbacks/BuildsCallbacks.ts +++ b/project/src/callbacks/BuildsCallbacks.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { BuildController } from "@spt/controllers/BuildController"; import { ISetMagazineRequest } from "@spt/models/eft/builds/ISetMagazineRequest"; import { IEmptyRequestData } from "@spt/models/eft/common/IEmptyRequestData"; @@ -8,29 +7,26 @@ import { IPresetBuildActionRequestData } from "@spt/models/eft/presetBuild/IPres import { IRemoveBuildRequestData } from "@spt/models/eft/presetBuild/IRemoveBuildRequestData"; import { IUserBuilds } from "@spt/models/eft/profile/ISptProfile"; import { HttpResponseUtil } from "@spt/utils/HttpResponseUtil"; +import { inject, injectable } from "tsyringe"; @injectable() -export class BuildsCallbacks -{ +export class BuildsCallbacks { constructor( @inject("HttpResponseUtil") protected httpResponse: HttpResponseUtil, @inject("BuildController") protected buildController: BuildController, - ) - {} + ) {} /** * Handle client/builds/list */ - public getBuilds(url: string, info: IEmptyRequestData, sessionID: string): IGetBodyResponseData - { + public getBuilds(url: string, info: IEmptyRequestData, sessionID: string): IGetBodyResponseData { return this.httpResponse.getBody(this.buildController.getUserBuilds(sessionID)); } /** * Handle client/builds/magazine/save */ - public createMagazineTemplate(url: string, request: ISetMagazineRequest, sessionID: string): INullResponseData - { + public createMagazineTemplate(url: string, request: ISetMagazineRequest, sessionID: string): INullResponseData { this.buildController.createMagazineTemplate(sessionID, request); return this.httpResponse.nullResponse(); @@ -39,8 +35,7 @@ export class BuildsCallbacks /** * Handle client/builds/weapon/save */ - public setWeapon(url: string, info: IPresetBuildActionRequestData, sessionID: string): INullResponseData - { + public setWeapon(url: string, info: IPresetBuildActionRequestData, sessionID: string): INullResponseData { this.buildController.saveWeaponBuild(sessionID, info); return this.httpResponse.nullResponse(); @@ -49,8 +44,7 @@ export class BuildsCallbacks /** * Handle client/builds/equipment/save */ - public setEquipment(url: string, info: IPresetBuildActionRequestData, sessionID: string): INullResponseData - { + public setEquipment(url: string, info: IPresetBuildActionRequestData, sessionID: string): INullResponseData { this.buildController.saveEquipmentBuild(sessionID, info); return this.httpResponse.nullResponse(); @@ -59,8 +53,7 @@ export class BuildsCallbacks /** * Handle client/builds/delete */ - public deleteBuild(url: string, info: IRemoveBuildRequestData, sessionID: string): INullResponseData - { + public deleteBuild(url: string, info: IRemoveBuildRequestData, sessionID: string): INullResponseData { this.buildController.removeBuild(sessionID, info); return this.httpResponse.nullResponse(); diff --git a/project/src/callbacks/BundleCallbacks.ts b/project/src/callbacks/BundleCallbacks.ts index 7c42d529..07cbebf5 100644 --- a/project/src/callbacks/BundleCallbacks.ts +++ b/project/src/callbacks/BundleCallbacks.ts @@ -1,34 +1,30 @@ -import { inject, injectable } from "tsyringe"; import { BundleLoader } from "@spt/loaders/BundleLoader"; import { ConfigTypes } from "@spt/models/enums/ConfigTypes"; import { IHttpConfig } from "@spt/models/spt/config/IHttpConfig"; import { ConfigServer } from "@spt/servers/ConfigServer"; import { HttpResponseUtil } from "@spt/utils/HttpResponseUtil"; +import { inject, injectable } from "tsyringe"; @injectable() -export class BundleCallbacks -{ +export class BundleCallbacks { protected httpConfig: IHttpConfig; constructor( @inject("HttpResponseUtil") protected httpResponse: HttpResponseUtil, @inject("BundleLoader") protected bundleLoader: BundleLoader, @inject("ConfigServer") protected configServer: ConfigServer, - ) - { + ) { this.httpConfig = this.configServer.getConfig(ConfigTypes.HTTP); } /** * Handle singleplayer/bundles */ - public getBundles(url: string, info: any, sessionID: string): string - { + public getBundles(url: string, info: any, sessionID: string): string { return this.httpResponse.noBody(this.bundleLoader.getBundles()); } - public getBundle(url: string, info: any, sessionID: string): string - { + public getBundle(url: string, info: any, sessionID: string): string { return "BUNDLE"; } } diff --git a/project/src/callbacks/ClientLogCallbacks.ts b/project/src/callbacks/ClientLogCallbacks.ts index 47c0cb24..b88d4fbc 100644 --- a/project/src/callbacks/ClientLogCallbacks.ts +++ b/project/src/callbacks/ClientLogCallbacks.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { ClientLogController } from "@spt/controllers/ClientLogController"; import { ModLoadOrder } from "@spt/loaders/ModLoadOrder"; import { INullResponseData } from "@spt/models/eft/httpResponse/INullResponseData"; @@ -8,25 +7,23 @@ import { IClientLogRequest } from "@spt/models/spt/logging/IClientLogRequest"; import { ConfigServer } from "@spt/servers/ConfigServer"; import { LocalisationService } from "@spt/services/LocalisationService"; import { HttpResponseUtil } from "@spt/utils/HttpResponseUtil"; +import { inject, injectable } from "tsyringe"; /** Handle client logging related events */ @injectable() -export class ClientLogCallbacks -{ +export class ClientLogCallbacks { constructor( @inject("HttpResponseUtil") protected httpResponse: HttpResponseUtil, @inject("ClientLogController") protected clientLogController: ClientLogController, @inject("ConfigServer") protected configServer: ConfigServer, @inject("LocalisationService") protected localisationService: LocalisationService, @inject("ModLoadOrder") protected modLoadOrder: ModLoadOrder, - ) - {} + ) {} /** * Handle /singleplayer/log */ - public clientLog(url: string, info: IClientLogRequest, sessionID: string): INullResponseData - { + public clientLog(url: string, info: IClientLogRequest, sessionID: string): INullResponseData { this.clientLogController.clientLog(info); return this.httpResponse.nullResponse(); } @@ -34,8 +31,7 @@ export class ClientLogCallbacks /** * Handle /singleplayer/release */ - public releaseNotes(): string - { + public releaseNotes(): string { const data: IRelease = this.configServer.getConfig(ConfigTypes.CORE).release; data.betaDisclaimerText = globalThis.G_MODS_ENABLED @@ -62,8 +58,7 @@ export class ClientLogCallbacks * Handle /singleplayer/enableBSGlogging */ - public bsgLogging(): string - { + public bsgLogging(): string { const data: IBsgLogging = this.configServer.getConfig(ConfigTypes.CORE).bsgLogging; return this.httpResponse.noBody(data); } diff --git a/project/src/callbacks/CustomizationCallbacks.ts b/project/src/callbacks/CustomizationCallbacks.ts index 6bc39b56..fe59eb4d 100644 --- a/project/src/callbacks/CustomizationCallbacks.ts +++ b/project/src/callbacks/CustomizationCallbacks.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { CustomizationController } from "@spt/controllers/CustomizationController"; import { IEmptyRequestData } from "@spt/models/eft/common/IEmptyRequestData"; import { IPmcData } from "@spt/models/eft/common/IPmcData"; @@ -10,23 +9,21 @@ import { IGetBodyResponseData } from "@spt/models/eft/httpResponse/IGetBodyRespo import { IItemEventRouterResponse } from "@spt/models/eft/itemEvent/IItemEventRouterResponse"; import { SaveServer } from "@spt/servers/SaveServer"; import { HttpResponseUtil } from "@spt/utils/HttpResponseUtil"; +import { inject, injectable } from "tsyringe"; @injectable() -export class CustomizationCallbacks -{ +export class CustomizationCallbacks { constructor( @inject("CustomizationController") protected customizationController: CustomizationController, @inject("SaveServer") protected saveServer: SaveServer, @inject("HttpResponseUtil") protected httpResponse: HttpResponseUtil, - ) - {} + ) {} /** * Handle client/trading/customization/storage * @returns IGetSuitsResponse */ - public getSuits(url: string, info: IEmptyRequestData, sessionID: string): IGetBodyResponseData - { + public getSuits(url: string, info: IEmptyRequestData, sessionID: string): IGetBodyResponseData { const result: IGetSuitsResponse = { _id: sessionID, suites: this.saveServer.getProfile(sessionID).suits }; return this.httpResponse.getBody(result); } @@ -35,8 +32,7 @@ export class CustomizationCallbacks * Handle client/trading/customization * @returns ISuit[] */ - public getTraderSuits(url: string, info: IEmptyRequestData, sessionID: string): IGetBodyResponseData - { + public getTraderSuits(url: string, info: IEmptyRequestData, sessionID: string): IGetBodyResponseData { const splittedUrl = url.split("/"); const traderID = splittedUrl[splittedUrl.length - 2]; @@ -50,16 +46,14 @@ export class CustomizationCallbacks pmcData: IPmcData, body: IWearClothingRequestData, sessionID: string, - ): IItemEventRouterResponse - { + ): IItemEventRouterResponse { return this.customizationController.wearClothing(pmcData, body, sessionID); } /** * Handle CustomizationBuy event */ - public buyClothing(pmcData: IPmcData, body: IBuyClothingRequestData, sessionID: string): IItemEventRouterResponse - { + public buyClothing(pmcData: IPmcData, body: IBuyClothingRequestData, sessionID: string): IItemEventRouterResponse { return this.customizationController.buyClothing(pmcData, body, sessionID); } } diff --git a/project/src/callbacks/DataCallbacks.ts b/project/src/callbacks/DataCallbacks.ts index 24fb67ba..6a369347 100644 --- a/project/src/callbacks/DataCallbacks.ts +++ b/project/src/callbacks/DataCallbacks.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { HideoutController } from "@spt/controllers/HideoutController"; import { RagfairController } from "@spt/controllers/RagfairController"; import { TraderHelper } from "@spt/helpers/TraderHelper"; @@ -17,13 +16,13 @@ import { ISettingsBase } from "@spt/models/spt/server/ISettingsBase"; import { DatabaseService } from "@spt/services/DatabaseService"; import { HttpResponseUtil } from "@spt/utils/HttpResponseUtil"; import { TimeUtil } from "@spt/utils/TimeUtil"; +import { inject, injectable } from "tsyringe"; /** * Handle client requests */ @injectable() -export class DataCallbacks -{ +export class DataCallbacks { constructor( @inject("HttpResponseUtil") protected httpResponse: HttpResponseUtil, @inject("TimeUtil") protected timeUtil: TimeUtil, @@ -31,15 +30,13 @@ export class DataCallbacks @inject("DatabaseService") protected databaseService: DatabaseService, @inject("RagfairController") protected ragfairController: RagfairController, @inject("HideoutController") protected hideoutController: HideoutController, - ) - {} + ) {} /** * Handle client/settings * @returns ISettingsBase */ - public getSettings(url: string, info: IEmptyRequestData, sessionID: string): IGetBodyResponseData - { + public getSettings(url: string, info: IEmptyRequestData, sessionID: string): IGetBodyResponseData { return this.httpResponse.getBody(this.databaseService.getSettings()); } @@ -47,8 +44,7 @@ export class DataCallbacks * Handle client/globals * @returns IGlobals */ - public getGlobals(url: string, info: IEmptyRequestData, sessionID: string): IGetBodyResponseData - { + public getGlobals(url: string, info: IEmptyRequestData, sessionID: string): IGetBodyResponseData { const globals = this.databaseService.getGlobals(); globals.time = Date.now() / 1000; @@ -59,8 +55,7 @@ export class DataCallbacks * Handle client/items * @returns string */ - public getTemplateItems(url: string, info: IEmptyRequestData, sessionID: string): string - { + public getTemplateItems(url: string, info: IEmptyRequestData, sessionID: string): string { return this.httpResponse.getUnclearedBody(this.databaseService.getItems()); } @@ -72,8 +67,7 @@ export class DataCallbacks url: string, info: IEmptyRequestData, sessionID: string, - ): IGetBodyResponseData - { + ): IGetBodyResponseData { return this.httpResponse.getBody(this.databaseService.getHandbook()); } @@ -85,8 +79,7 @@ export class DataCallbacks url: string, info: IEmptyRequestData, sessionID: string, - ): IGetBodyResponseData> - { + ): IGetBodyResponseData> { return this.httpResponse.getBody(this.databaseService.getTemplates().customization); } @@ -98,8 +91,7 @@ export class DataCallbacks url: string, info: IEmptyRequestData, sessionID: string, - ): IGetBodyResponseData - { + ): IGetBodyResponseData { return this.httpResponse.getBody(this.databaseService.getTemplates().character); } @@ -111,8 +103,7 @@ export class DataCallbacks url: string, info: IEmptyRequestData, sessionID: string, - ): IGetBodyResponseData - { + ): IGetBodyResponseData { return this.httpResponse.getBody(this.databaseService.getHideout().settings); } @@ -120,8 +111,7 @@ export class DataCallbacks url: string, info: IEmptyRequestData, sessionID: string, - ): IGetBodyResponseData - { + ): IGetBodyResponseData { return this.httpResponse.getBody(this.databaseService.getHideout().areas); } @@ -129,8 +119,7 @@ export class DataCallbacks url: string, info: IEmptyRequestData, sessionID: string, - ): IGetBodyResponseData - { + ): IGetBodyResponseData { return this.httpResponse.getBody(this.databaseService.getHideout().production); } @@ -138,8 +127,7 @@ export class DataCallbacks url: string, info: IEmptyRequestData, sessionID: string, - ): IGetBodyResponseData - { + ): IGetBodyResponseData { return this.httpResponse.getBody(this.databaseService.getHideout().scavcase); } @@ -150,27 +138,23 @@ export class DataCallbacks url: string, info: IEmptyRequestData, sessionID: string, - ): IGetBodyResponseData> - { + ): IGetBodyResponseData> { return this.httpResponse.getBody(this.databaseService.getLocales().languages); } /** * Handle client/menu/locale */ - public getLocalesMenu(url: string, info: IEmptyRequestData, sessionID: string): IGetBodyResponseData - { + public getLocalesMenu(url: string, info: IEmptyRequestData, sessionID: string): IGetBodyResponseData { const localeId = url.replace("/client/menu/locale/", ""); const locales = this.databaseService.getLocales(); let result = locales.menu[localeId]; - if (result === undefined) - { + if (result === undefined) { result = locales.menu.en; } - if (result === undefined) - throw new Error(`Unable to determine locale for request with '${localeId}'`); + if (result === undefined) throw new Error(`Unable to determine locale for request with '${localeId}'`); return this.httpResponse.getBody(result); } @@ -178,14 +162,12 @@ export class DataCallbacks /** * Handle client/locale */ - public getLocalesGlobal(url: string, info: IEmptyRequestData, sessionID: string): string - { + public getLocalesGlobal(url: string, info: IEmptyRequestData, sessionID: string): string { const localeId = url.replace("/client/locale/", ""); const locales = this.databaseService.getLocales(); let result = locales.global[localeId]; - if (result === undefined) - { + if (result === undefined) { result = locales.global["en"]; } @@ -195,8 +177,7 @@ export class DataCallbacks /** * Handle client/hideout/qte/list */ - public getQteList(url: string, info: IEmptyRequestData, sessionID: string): string - { + public getQteList(url: string, info: IEmptyRequestData, sessionID: string): string { return this.httpResponse.getUnclearedBody(this.hideoutController.getQteList(sessionID)); } @@ -209,16 +190,14 @@ export class DataCallbacks url: string, info: IEmptyRequestData, sessionID: string, - ): IGetBodyResponseData - { + ): IGetBodyResponseData { const traderId = url.replace("/client/items/prices/", ""); // All traders share same item prices, unknown how to tell what items are shown for each trader // Shown items listed are likely linked to traders items_buy/category array const handbookPrices = this.ragfairController.getStaticPrices(); - const response: IGetItemPricesResponse - = { + const response: IGetItemPricesResponse = { supplyNextTime: this.traderHelper.getNextUpdateTimestamp(traderId), prices: handbookPrices, currencyCourses: { diff --git a/project/src/callbacks/DialogueCallbacks.ts b/project/src/callbacks/DialogueCallbacks.ts index 734cddcb..e5f0d59c 100644 --- a/project/src/callbacks/DialogueCallbacks.ts +++ b/project/src/callbacks/DialogueCallbacks.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { DialogueController } from "@spt/controllers/DialogueController"; import { OnUpdate } from "@spt/di/OnUpdate"; import { IEmptyRequestData } from "@spt/models/eft/common/IEmptyRequestData"; @@ -36,17 +35,16 @@ import { DialogueInfo } from "@spt/models/eft/profile/ISptProfile"; import { HashUtil } from "@spt/utils/HashUtil"; import { HttpResponseUtil } from "@spt/utils/HttpResponseUtil"; import { TimeUtil } from "@spt/utils/TimeUtil"; +import { inject, injectable } from "tsyringe"; @injectable() -export class DialogueCallbacks implements OnUpdate -{ +export class DialogueCallbacks implements OnUpdate { constructor( @inject("HashUtil") protected hashUtil: HashUtil, @inject("TimeUtil") protected timeUtil: TimeUtil, @inject("HttpResponseUtil") protected httpResponse: HttpResponseUtil, @inject("DialogueController") protected dialogueController: DialogueController, - ) - {} + ) {} /** * Handle client/friend/list @@ -56,8 +54,7 @@ export class DialogueCallbacks implements OnUpdate url: string, info: IEmptyRequestData, sessionID: string, - ): IGetBodyResponseData - { + ): IGetBodyResponseData { return this.httpResponse.getBody(this.dialogueController.getFriendList(sessionID)); } @@ -69,8 +66,7 @@ export class DialogueCallbacks implements OnUpdate url: string, info: IGetChatServerListRequestData, sessionID: string, - ): IGetBodyResponseData - { + ): IGetBodyResponseData { const chatServer: IChatServer = { _id: this.hashUtil.generate(), RegistrationId: 20, @@ -91,8 +87,7 @@ export class DialogueCallbacks implements OnUpdate url: string, info: IGetMailDialogListRequestData, sessionID: string, - ): IGetBodyResponseData - { + ): IGetBodyResponseData { return this.httpResponse.getBody(this.dialogueController.generateDialogueList(sessionID), 0, undefined, false); } @@ -101,8 +96,7 @@ export class DialogueCallbacks implements OnUpdate url: string, info: IGetMailDialogViewRequestData, sessionID: string, - ): IGetBodyResponseData - { + ): IGetBodyResponseData { return this.httpResponse.getBody( this.dialogueController.generateDialogueView(info, sessionID), 0, @@ -116,35 +110,30 @@ export class DialogueCallbacks implements OnUpdate url: string, info: IGetMailDialogInfoRequestData, sessionID: string, - ): IGetBodyResponseData - { + ): IGetBodyResponseData { return this.httpResponse.getBody(this.dialogueController.getDialogueInfo(info.dialogId, sessionID)); } /** Handle client/mail/dialog/remove */ - public removeDialog(url: string, info: IRemoveDialogRequestData, sessionID: string): IGetBodyResponseData - { + public removeDialog(url: string, info: IRemoveDialogRequestData, sessionID: string): IGetBodyResponseData { this.dialogueController.removeDialogue(info.dialogId, sessionID); return this.httpResponse.emptyArrayResponse(); } /** Handle client/mail/dialog/pin */ - public pinDialog(url: string, info: IPinDialogRequestData, sessionID: string): IGetBodyResponseData - { + public pinDialog(url: string, info: IPinDialogRequestData, sessionID: string): IGetBodyResponseData { this.dialogueController.setDialoguePin(info.dialogId, true, sessionID); return this.httpResponse.emptyArrayResponse(); } /** Handle client/mail/dialog/unpin */ - public unpinDialog(url: string, info: IPinDialogRequestData, sessionID: string): IGetBodyResponseData - { + public unpinDialog(url: string, info: IPinDialogRequestData, sessionID: string): IGetBodyResponseData { this.dialogueController.setDialoguePin(info.dialogId, false, sessionID); return this.httpResponse.emptyArrayResponse(); } /** Handle client/mail/dialog/read */ - public setRead(url: string, info: ISetDialogReadRequestData, sessionID: string): IGetBodyResponseData - { + public setRead(url: string, info: ISetDialogReadRequestData, sessionID: string): IGetBodyResponseData { this.dialogueController.setRead(info.dialogs, sessionID); return this.httpResponse.emptyArrayResponse(); } @@ -157,28 +146,24 @@ export class DialogueCallbacks implements OnUpdate url: string, info: IGetAllAttachmentsRequestData, sessionID: string, - ): IGetBodyResponseData - { + ): IGetBodyResponseData { return this.httpResponse.getBody(this.dialogueController.getAllAttachments(info.dialogId, sessionID)); } /** Handle client/mail/msg/send */ - public sendMessage(url: string, request: ISendMessageRequest, sessionID: string): IGetBodyResponseData - { + public sendMessage(url: string, request: ISendMessageRequest, sessionID: string): IGetBodyResponseData { return this.httpResponse.getBody(this.dialogueController.sendMessage(sessionID, request)); } /** Handle client/friend/request/list/outbox */ - public listOutbox(url: string, info: IEmptyRequestData, sessionID: string): IGetBodyResponseData - { + public listOutbox(url: string, info: IEmptyRequestData, sessionID: string): IGetBodyResponseData { return this.httpResponse.getBody([]); } /** * Handle client/friend/request/list/inbox */ - public listInbox(url: string, info: IEmptyRequestData, sessionID: string): IGetBodyResponseData - { + public listInbox(url: string, info: IEmptyRequestData, sessionID: string): IGetBodyResponseData { return this.httpResponse.getBody([]); } @@ -189,16 +174,14 @@ export class DialogueCallbacks implements OnUpdate url: string, request: IFriendRequestData, sessionID: string, - ): IGetBodyResponseData - { + ): IGetBodyResponseData { return this.httpResponse.getBody(this.dialogueController.sendFriendRequest(sessionID, request)); } /** * Handle client/friend/request/accept-all */ - public acceptAllFriendRequests(url: string, request: IEmptyRequestData, sessionID: string): INullResponseData - { + public acceptAllFriendRequests(url: string, request: IEmptyRequestData, sessionID: string): INullResponseData { return this.httpResponse.nullResponse(); } @@ -209,8 +192,7 @@ export class DialogueCallbacks implements OnUpdate url: string, request: IAcceptFriendRequestData, sessionID: string, - ): IGetBodyResponseData - { + ): IGetBodyResponseData { return this.httpResponse.getBody(true); } @@ -221,8 +203,7 @@ export class DialogueCallbacks implements OnUpdate url: string, request: IDeclineFriendRequestData, sessionID: string, - ): IGetBodyResponseData - { + ): IGetBodyResponseData { return this.httpResponse.getBody(true); } @@ -233,41 +214,34 @@ export class DialogueCallbacks implements OnUpdate url: string, request: ICancelFriendRequestData, sessionID: string, - ): IGetBodyResponseData - { + ): IGetBodyResponseData { return this.httpResponse.getBody(true); } /** Handle client/friend/delete */ - public deleteFriend(url: string, request: IDeleteFriendRequest, sessionID: string): INullResponseData - { + public deleteFriend(url: string, request: IDeleteFriendRequest, sessionID: string): INullResponseData { return this.httpResponse.nullResponse(); } /** Handle client/friend/ignore/set */ - public ignoreFriend(url: string, request: IUIDRequestData, sessionID: string): INullResponseData - { + public ignoreFriend(url: string, request: IUIDRequestData, sessionID: string): INullResponseData { return this.httpResponse.nullResponse(); } /** Handle client/friend/ignore/remove */ - public unIgnoreFriend(url: string, request: IUIDRequestData, sessionID: string): INullResponseData - { + public unIgnoreFriend(url: string, request: IUIDRequestData, sessionID: string): INullResponseData { return this.httpResponse.nullResponse(); } - public clearMail(url: string, request: IClearMailMessageRequest, sessionID: string): IGetBodyResponseData - { + public clearMail(url: string, request: IClearMailMessageRequest, sessionID: string): IGetBodyResponseData { return this.httpResponse.emptyArrayResponse(); } - public removeMail(url: string, request: IRemoveMailMessageRequest, sessionID: string): IGetBodyResponseData - { + public removeMail(url: string, request: IRemoveMailMessageRequest, sessionID: string): IGetBodyResponseData { return this.httpResponse.emptyArrayResponse(); } - public createGroupMail(url: string, info: ICreateGroupMailRequest, sessionID: string): IGetBodyResponseData - { + public createGroupMail(url: string, info: ICreateGroupMailRequest, sessionID: string): IGetBodyResponseData { return this.httpResponse.emptyArrayResponse(); } @@ -275,13 +249,11 @@ export class DialogueCallbacks implements OnUpdate url: string, info: IChangeGroupMailOwnerRequest, sessionID: string, - ): IGetBodyResponseData - { + ): IGetBodyResponseData { throw new Error("Method not implemented."); } - public addUserToMail(url: string, info: IAddUserGroupMailRequest, sessionID: string): IGetBodyResponseData - { + public addUserToMail(url: string, info: IAddUserGroupMailRequest, sessionID: string): IGetBodyResponseData { throw new Error("Method not implemented."); } @@ -289,19 +261,16 @@ export class DialogueCallbacks implements OnUpdate url: string, info: IRemoveUserGroupMailRequest, sessionID: string, - ): IGetBodyResponseData - { + ): IGetBodyResponseData { throw new Error("Method not implemented."); } - public async onUpdate(timeSinceLastRun: number): Promise - { + public async onUpdate(timeSinceLastRun: number): Promise { this.dialogueController.update(); return true; } - public getRoute(): string - { + public getRoute(): string { return "spt-dialogue"; } } diff --git a/project/src/callbacks/GameCallbacks.ts b/project/src/callbacks/GameCallbacks.ts index 115f7d94..6b898862 100644 --- a/project/src/callbacks/GameCallbacks.ts +++ b/project/src/callbacks/GameCallbacks.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { GameController } from "@spt/controllers/GameController"; import { OnLoad } from "@spt/di/OnLoad"; import { IEmptyRequestData } from "@spt/models/eft/common/IEmptyRequestData"; @@ -21,25 +20,22 @@ import { INullResponseData } from "@spt/models/eft/httpResponse/INullResponseDat import { SaveServer } from "@spt/servers/SaveServer"; import { HttpResponseUtil } from "@spt/utils/HttpResponseUtil"; import { Watermark } from "@spt/utils/Watermark"; +import { inject, injectable } from "tsyringe"; @injectable() -export class GameCallbacks implements OnLoad -{ +export class GameCallbacks implements OnLoad { constructor( @inject("HttpResponseUtil") protected httpResponse: HttpResponseUtil, @inject("Watermark") protected watermark: Watermark, @inject("SaveServer") protected saveServer: SaveServer, @inject("GameController") protected gameController: GameController, - ) - {} + ) {} - public async onLoad(): Promise - { + public async onLoad(): Promise { this.gameController.load(); } - public getRoute(): string - { + public getRoute(): string { return "spt-game"; } @@ -47,8 +43,7 @@ export class GameCallbacks implements OnLoad * Handle client/game/version/validate * @returns INullResponseData */ - public versionValidate(url: string, info: IVersionValidateRequestData, sessionID: string): INullResponseData - { + public versionValidate(url: string, info: IVersionValidateRequestData, sessionID: string): INullResponseData { return this.httpResponse.nullResponse(); } @@ -60,8 +55,7 @@ export class GameCallbacks implements OnLoad url: string, info: IEmptyRequestData, sessionID: string, - ): IGetBodyResponseData - { + ): IGetBodyResponseData { const today = new Date().toUTCString(); const startTimeStampMS = Date.parse(today); this.gameController.gameStart(url, info, sessionID, startTimeStampMS); @@ -77,8 +71,7 @@ export class GameCallbacks implements OnLoad url: string, info: IEmptyRequestData, sessionID: string, - ): IGetBodyResponseData - { + ): IGetBodyResponseData { this.saveServer.save(); return this.httpResponse.getBody({ status: "ok" }); } @@ -91,8 +84,7 @@ export class GameCallbacks implements OnLoad url: string, info: IGameEmptyCrcRequestData, sessionID: string, - ): IGetBodyResponseData - { + ): IGetBodyResponseData { return this.httpResponse.getBody(this.gameController.getGameConfig(sessionID)); } @@ -104,16 +96,14 @@ export class GameCallbacks implements OnLoad url: string, info: IGameModeRequestData, sessionID: string, - ): IGetBodyResponseData - { + ): IGetBodyResponseData { return this.httpResponse.getBody(this.gameController.getGameMode(sessionID, info)); } /** * Handle client/server/list */ - public getServer(url: string, info: IEmptyRequestData, sessionID: string): IGetBodyResponseData - { + public getServer(url: string, info: IEmptyRequestData, sessionID: string): IGetBodyResponseData { return this.httpResponse.getBody(this.gameController.getServer(sessionID)); } @@ -124,8 +114,7 @@ export class GameCallbacks implements OnLoad url: string, info: IEmptyRequestData, sessionID: string, - ): IGetBodyResponseData - { + ): IGetBodyResponseData { return this.httpResponse.getBody(this.gameController.getCurrentGroup(sessionID)); } @@ -136,8 +125,7 @@ export class GameCallbacks implements OnLoad url: string, info: IEmptyRequestData, sessionID: string, - ): IGetBodyResponseData - { + ): IGetBodyResponseData { return this.httpResponse.getBody(this.gameController.getValidGameVersion(sessionID)); } @@ -149,8 +137,7 @@ export class GameCallbacks implements OnLoad url: string, info: IEmptyRequestData, sessionID: string, - ): IGetBodyResponseData - { + ): IGetBodyResponseData { return this.httpResponse.getBody(this.gameController.getKeepAlive(sessionID)); } @@ -158,8 +145,7 @@ export class GameCallbacks implements OnLoad * Handle singleplayer/settings/version * @returns string */ - public getVersion(url: string, info: IEmptyRequestData, sessionID: string): string - { + public getVersion(url: string, info: IEmptyRequestData, sessionID: string): string { return this.httpResponse.noBody({ Version: this.watermark.getInGameVersionLabel() }); } @@ -167,8 +153,7 @@ export class GameCallbacks implements OnLoad * Handle /client/report/send & /client/reports/lobby/send * @returns INullResponseData */ - public reportNickname(url: string, info: IUIDRequestData, sessionID: string): INullResponseData - { + public reportNickname(url: string, info: IUIDRequestData, sessionID: string): INullResponseData { return this.httpResponse.nullResponse(); } @@ -176,8 +161,7 @@ export class GameCallbacks implements OnLoad * Handle singleplayer/settings/getRaidTime * @returns string */ - public getRaidTime(url: string, request: IGetRaidTimeRequest, sessionID: string): IGetRaidTimeResponse - { + public getRaidTime(url: string, request: IGetRaidTimeRequest, sessionID: string): IGetRaidTimeResponse { return this.httpResponse.noBody(this.gameController.getRaidTime(sessionID, request)); } @@ -185,8 +169,7 @@ export class GameCallbacks implements OnLoad * Handle /client/survey * @returns INullResponseData */ - public getSurvey(url: string, request: IEmptyRequestData, sessionID: string): INullResponseData - { + public getSurvey(url: string, request: IEmptyRequestData, sessionID: string): INullResponseData { return this.httpResponse.nullResponse(); } } diff --git a/project/src/callbacks/HandbookCallbacks.ts b/project/src/callbacks/HandbookCallbacks.ts index 84aefa2b..616a1f86 100644 --- a/project/src/callbacks/HandbookCallbacks.ts +++ b/project/src/callbacks/HandbookCallbacks.ts @@ -1,20 +1,16 @@ -import { inject, injectable } from "tsyringe"; import { HandbookController } from "@spt/controllers/HandbookController"; import { OnLoad } from "@spt/di/OnLoad"; +import { inject, injectable } from "tsyringe"; @injectable() -export class HandbookCallbacks implements OnLoad -{ - constructor(@inject("HandbookController") protected handbookController: HandbookController) - {} +export class HandbookCallbacks implements OnLoad { + constructor(@inject("HandbookController") protected handbookController: HandbookController) {} - public async onLoad(): Promise - { + public async onLoad(): Promise { this.handbookController.load(); } - public getRoute(): string - { + public getRoute(): string { return "spt-handbook"; } } diff --git a/project/src/callbacks/HealthCallbacks.ts b/project/src/callbacks/HealthCallbacks.ts index f3ff21ca..f473cdc0 100644 --- a/project/src/callbacks/HealthCallbacks.ts +++ b/project/src/callbacks/HealthCallbacks.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { HealthController } from "@spt/controllers/HealthController"; import { ProfileHelper } from "@spt/helpers/ProfileHelper"; import { IPmcData } from "@spt/models/eft/common/IPmcData"; @@ -10,16 +9,15 @@ import { IWorkoutData } from "@spt/models/eft/health/IWorkoutData"; import { IGetBodyResponseData } from "@spt/models/eft/httpResponse/IGetBodyResponseData"; import { IItemEventRouterResponse } from "@spt/models/eft/itemEvent/IItemEventRouterResponse"; import { HttpResponseUtil } from "@spt/utils/HttpResponseUtil"; +import { inject, injectable } from "tsyringe"; @injectable() -export class HealthCallbacks -{ +export class HealthCallbacks { constructor( @inject("HttpResponseUtil") protected httpResponse: HttpResponseUtil, @inject("ProfileHelper") protected profileHelper: ProfileHelper, @inject("HealthController") protected healthController: HealthController, - ) - {} + ) {} /** * Custom spt server request found in modules/HealthSynchronizer.cs @@ -28,8 +26,7 @@ export class HealthCallbacks * @param sessionID session id * @returns empty response, no data sent back to client */ - public syncHealth(url: string, info: ISyncHealthRequestData, sessionID: string): IGetBodyResponseData - { + public syncHealth(url: string, info: ISyncHealthRequestData, sessionID: string): IGetBodyResponseData { this.healthController.saveVitality(this.profileHelper.getPmcProfile(sessionID), info, sessionID); return this.httpResponse.emptyResponse(); } @@ -41,8 +38,7 @@ export class HealthCallbacks * @param sessionID session id * @returns empty response, no data sent back to client */ - public handleWorkoutEffects(url: string, info: IWorkoutData, sessionID: string): IGetBodyResponseData - { + public handleWorkoutEffects(url: string, info: IWorkoutData, sessionID: string): IGetBodyResponseData { this.healthController.applyWorkoutChanges(this.profileHelper.getPmcProfile(sessionID), info, sessionID); return this.httpResponse.emptyResponse(); } @@ -51,8 +47,7 @@ export class HealthCallbacks * Handle Eat * @returns IItemEventRouterResponse */ - public offraidEat(pmcData: IPmcData, body: IOffraidEatRequestData, sessionID: string): IItemEventRouterResponse - { + public offraidEat(pmcData: IPmcData, body: IOffraidEatRequestData, sessionID: string): IItemEventRouterResponse { return this.healthController.offraidEat(pmcData, body, sessionID); } @@ -60,8 +55,7 @@ export class HealthCallbacks * Handle Heal * @returns IItemEventRouterResponse */ - public offraidHeal(pmcData: IPmcData, body: IOffraidHealRequestData, sessionID: string): IItemEventRouterResponse - { + public offraidHeal(pmcData: IPmcData, body: IOffraidHealRequestData, sessionID: string): IItemEventRouterResponse { return this.healthController.offraidHeal(pmcData, body, sessionID); } @@ -73,8 +67,7 @@ export class HealthCallbacks pmcData: IPmcData, info: IHealthTreatmentRequestData, sessionID: string, - ): IItemEventRouterResponse - { + ): IItemEventRouterResponse { return this.healthController.healthTreatment(pmcData, info, sessionID); } } diff --git a/project/src/callbacks/HideoutCallbacks.ts b/project/src/callbacks/HideoutCallbacks.ts index 8b076a9e..f40b7bec 100644 --- a/project/src/callbacks/HideoutCallbacks.ts +++ b/project/src/callbacks/HideoutCallbacks.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { HideoutController } from "@spt/controllers/HideoutController"; import { OnUpdate } from "@spt/di/OnUpdate"; import { IPmcData } from "@spt/models/eft/common/IPmcData"; @@ -19,17 +18,16 @@ import { IItemEventRouterResponse } from "@spt/models/eft/itemEvent/IItemEventRo import { ConfigTypes } from "@spt/models/enums/ConfigTypes"; import { IHideoutConfig } from "@spt/models/spt/config/IHideoutConfig"; import { ConfigServer } from "@spt/servers/ConfigServer"; +import { inject, injectable } from "tsyringe"; @injectable() -export class HideoutCallbacks implements OnUpdate -{ +export class HideoutCallbacks implements OnUpdate { protected hideoutConfig: IHideoutConfig; constructor( @inject("HideoutController") protected hideoutController: HideoutController, // TODO: delay needed @inject("ConfigServer") protected configServer: ConfigServer, - ) - { + ) { this.hideoutConfig = this.configServer.getConfig(ConfigTypes.HIDEOUT); } @@ -41,8 +39,7 @@ export class HideoutCallbacks implements OnUpdate body: IHideoutUpgradeRequestData, sessionID: string, output: IItemEventRouterResponse, - ): IItemEventRouterResponse - { + ): IItemEventRouterResponse { this.hideoutController.startUpgrade(pmcData, body, sessionID, output); return output; @@ -56,8 +53,7 @@ export class HideoutCallbacks implements OnUpdate body: IHideoutUpgradeCompleteRequestData, sessionID: string, output: IItemEventRouterResponse, - ): IItemEventRouterResponse - { + ): IItemEventRouterResponse { this.hideoutController.upgradeComplete(pmcData, body, sessionID, output); return output; @@ -70,8 +66,7 @@ export class HideoutCallbacks implements OnUpdate pmcData: IPmcData, body: IHideoutPutItemInRequestData, sessionID: string, - ): IItemEventRouterResponse - { + ): IItemEventRouterResponse { return this.hideoutController.putItemsInAreaSlots(pmcData, body, sessionID); } @@ -82,8 +77,7 @@ export class HideoutCallbacks implements OnUpdate pmcData: IPmcData, body: IHideoutTakeItemOutRequestData, sessionID: string, - ): IItemEventRouterResponse - { + ): IItemEventRouterResponse { return this.hideoutController.takeItemsFromAreaSlots(pmcData, body, sessionID); } @@ -94,8 +88,7 @@ export class HideoutCallbacks implements OnUpdate pmcData: IPmcData, body: IHideoutToggleAreaRequestData, sessionID: string, - ): IItemEventRouterResponse - { + ): IItemEventRouterResponse { return this.hideoutController.toggleArea(pmcData, body, sessionID); } @@ -106,8 +99,7 @@ export class HideoutCallbacks implements OnUpdate pmcData: IPmcData, body: IHideoutSingleProductionStartRequestData, sessionID: string, - ): IItemEventRouterResponse - { + ): IItemEventRouterResponse { return this.hideoutController.singleProductionStart(pmcData, body, sessionID); } @@ -118,8 +110,7 @@ export class HideoutCallbacks implements OnUpdate pmcData: IPmcData, body: IHideoutScavCaseStartRequestData, sessionID: string, - ): IItemEventRouterResponse - { + ): IItemEventRouterResponse { return this.hideoutController.scavCaseProductionStart(pmcData, body, sessionID); } @@ -130,8 +121,7 @@ export class HideoutCallbacks implements OnUpdate pmcData: IPmcData, body: IHideoutContinuousProductionStartRequestData, sessionID: string, - ): IItemEventRouterResponse - { + ): IItemEventRouterResponse { return this.hideoutController.continuousProductionStart(pmcData, body, sessionID); } @@ -142,8 +132,7 @@ export class HideoutCallbacks implements OnUpdate pmcData: IPmcData, body: IHideoutTakeProductionRequestData, sessionID: string, - ): IItemEventRouterResponse - { + ): IItemEventRouterResponse { return this.hideoutController.takeProduction(pmcData, body, sessionID); } @@ -155,8 +144,7 @@ export class HideoutCallbacks implements OnUpdate request: IHandleQTEEventRequestData, sessionId: string, output: IItemEventRouterResponse, - ): IItemEventRouterResponse - { + ): IItemEventRouterResponse { this.hideoutController.handleQTEEventOutcome(sessionId, pmcData, request, output); return output; @@ -170,8 +158,7 @@ export class HideoutCallbacks implements OnUpdate request: IRecordShootingRangePoints, sessionId: string, output: IItemEventRouterResponse, - ): IItemEventRouterResponse - { + ): IItemEventRouterResponse { this.hideoutController.recordShootingRangePoints(sessionId, pmcData, request); return output; @@ -184,8 +171,7 @@ export class HideoutCallbacks implements OnUpdate pmcData: IPmcData, request: IHideoutImproveAreaRequestData, sessionId: string, - ): IItemEventRouterResponse - { + ): IItemEventRouterResponse { return this.hideoutController.improveArea(sessionId, pmcData, request); } @@ -196,23 +182,19 @@ export class HideoutCallbacks implements OnUpdate pmcData: IPmcData, request: IHideoutCancelProductionRequestData, sessionId: string, - ): IItemEventRouterResponse - { + ): IItemEventRouterResponse { return this.hideoutController.cancelProduction(sessionId, pmcData, request); } - public async onUpdate(timeSinceLastRun: number): Promise - { - if (timeSinceLastRun > this.hideoutConfig.runIntervalSeconds) - { + public async onUpdate(timeSinceLastRun: number): Promise { + if (timeSinceLastRun > this.hideoutConfig.runIntervalSeconds) { this.hideoutController.update(); return true; } return false; } - public getRoute(): string - { + public getRoute(): string { return "spt-hideout"; } } diff --git a/project/src/callbacks/HttpCallbacks.ts b/project/src/callbacks/HttpCallbacks.ts index a378126c..d1d2bffa 100644 --- a/project/src/callbacks/HttpCallbacks.ts +++ b/project/src/callbacks/HttpCallbacks.ts @@ -1,25 +1,20 @@ -import { inject, injectable } from "tsyringe"; import { OnLoad } from "@spt/di/OnLoad"; import { HttpServer } from "@spt/servers/HttpServer"; +import { inject, injectable } from "tsyringe"; @injectable() -export class HttpCallbacks implements OnLoad -{ - constructor(@inject("HttpServer") protected httpServer: HttpServer) - {} +export class HttpCallbacks implements OnLoad { + constructor(@inject("HttpServer") protected httpServer: HttpServer) {} - public async onLoad(): Promise - { + public async onLoad(): Promise { this.httpServer.load(); } - public getRoute(): string - { + public getRoute(): string { return "spt-http"; } - public getImage(): string - { + public getImage(): string { return ""; } } diff --git a/project/src/callbacks/InraidCallbacks.ts b/project/src/callbacks/InraidCallbacks.ts index daa01673..881a251f 100644 --- a/project/src/callbacks/InraidCallbacks.ts +++ b/project/src/callbacks/InraidCallbacks.ts @@ -1,22 +1,20 @@ -import { inject, injectable } from "tsyringe"; import { InraidController } from "@spt/controllers/InraidController"; import { IEmptyRequestData } from "@spt/models/eft/common/IEmptyRequestData"; import { INullResponseData } from "@spt/models/eft/httpResponse/INullResponseData"; import { IRegisterPlayerRequestData } from "@spt/models/eft/inRaid/IRegisterPlayerRequestData"; import { IScavSaveRequestData } from "@spt/models/eft/inRaid/IScavSaveRequestData"; import { HttpResponseUtil } from "@spt/utils/HttpResponseUtil"; +import { inject, injectable } from "tsyringe"; /** * Handle client requests */ @injectable() -export class InraidCallbacks -{ +export class InraidCallbacks { constructor( @inject("InraidController") protected inraidController: InraidController, @inject("HttpResponseUtil") protected httpResponse: HttpResponseUtil, - ) - {} + ) {} /** * Handle client/location/getLocalloot @@ -26,8 +24,7 @@ export class InraidCallbacks * @param sessionID Session id * @returns Null http response */ - public registerPlayer(url: string, info: IRegisterPlayerRequestData, sessionID: string): INullResponseData - { + public registerPlayer(url: string, info: IRegisterPlayerRequestData, sessionID: string): INullResponseData { this.inraidController.addPlayer(sessionID, info); return this.httpResponse.nullResponse(); } @@ -39,8 +36,7 @@ export class InraidCallbacks * @param sessionID Session id * @returns Null http response */ - public saveProgress(url: string, info: IScavSaveRequestData, sessionID: string): INullResponseData - { + public saveProgress(url: string, info: IScavSaveRequestData, sessionID: string): INullResponseData { this.inraidController.savePostRaidProfileForScav(info, sessionID); return this.httpResponse.nullResponse(); } @@ -50,8 +46,7 @@ export class InraidCallbacks * Handle singleplayer/settings/raid/endstate * @returns */ - public getRaidEndState(): string - { + public getRaidEndState(): string { return this.httpResponse.noBody(this.inraidController.getInraidConfig().MIAOnRaidEnd); } @@ -59,18 +54,15 @@ export class InraidCallbacks * Handle singleplayer/settings/raid/menu * @returns JSON as string */ - public getRaidMenuSettings(): string - { + public getRaidMenuSettings(): string { return this.httpResponse.noBody(this.inraidController.getInraidConfig().raidMenuSettings); } - public getTraitorScavHostileChance(url: string, info: IEmptyRequestData, sessionId: string): string - { + public getTraitorScavHostileChance(url: string, info: IEmptyRequestData, sessionId: string): string { return this.httpResponse.noBody(this.inraidController.getTraitorScavHostileChance(url, sessionId)); } - public getBossConvertSettings(url: string, info: IEmptyRequestData, sessionId: string): string - { + public getBossConvertSettings(url: string, info: IEmptyRequestData, sessionId: string): string { return this.httpResponse.noBody(this.inraidController.getBossConvertSettings(url, sessionId)); } } diff --git a/project/src/callbacks/InsuranceCallbacks.ts b/project/src/callbacks/InsuranceCallbacks.ts index 39786771..16728763 100644 --- a/project/src/callbacks/InsuranceCallbacks.ts +++ b/project/src/callbacks/InsuranceCallbacks.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { InsuranceController } from "@spt/controllers/InsuranceController"; import { OnUpdate } from "@spt/di/OnUpdate"; import { IPmcData } from "@spt/models/eft/common/IPmcData"; @@ -12,18 +11,17 @@ import { IInsuranceConfig } from "@spt/models/spt/config/IInsuranceConfig"; import { ConfigServer } from "@spt/servers/ConfigServer"; import { InsuranceService } from "@spt/services/InsuranceService"; import { HttpResponseUtil } from "@spt/utils/HttpResponseUtil"; +import { inject, injectable } from "tsyringe"; @injectable() -export class InsuranceCallbacks implements OnUpdate -{ +export class InsuranceCallbacks implements OnUpdate { protected insuranceConfig: IInsuranceConfig; constructor( @inject("InsuranceController") protected insuranceController: InsuranceController, @inject("InsuranceService") protected insuranceService: InsuranceService, @inject("HttpResponseUtil") protected httpResponse: HttpResponseUtil, @inject("ConfigServer") protected configServer: ConfigServer, - ) - { + ) { this.insuranceConfig = this.configServer.getConfig(ConfigTypes.INSURANCE); } @@ -35,8 +33,7 @@ export class InsuranceCallbacks implements OnUpdate url: string, info: IGetInsuranceCostRequestData, sessionID: string, - ): IGetBodyResponseData - { + ): IGetBodyResponseData { return this.httpResponse.getBody(this.insuranceController.cost(info, sessionID)); } @@ -44,24 +41,20 @@ export class InsuranceCallbacks implements OnUpdate * Handle Insure event * @returns IItemEventRouterResponse */ - public insure(pmcData: IPmcData, body: IInsureRequestData, sessionID: string): IItemEventRouterResponse - { + public insure(pmcData: IPmcData, body: IInsureRequestData, sessionID: string): IItemEventRouterResponse { return this.insuranceController.insure(pmcData, body, sessionID); } - public async onUpdate(secondsSinceLastRun: number): Promise - { + public async onUpdate(secondsSinceLastRun: number): Promise { // People edit the config value to be 0 and break it, force value to no lower than 1 - if (secondsSinceLastRun > Math.max(this.insuranceConfig.runIntervalSeconds, 1)) - { + if (secondsSinceLastRun > Math.max(this.insuranceConfig.runIntervalSeconds, 1)) { this.insuranceController.processReturn(); return true; } return false; } - public getRoute(): string - { + public getRoute(): string { return "spt-insurance"; } } diff --git a/project/src/callbacks/InventoryCallbacks.ts b/project/src/callbacks/InventoryCallbacks.ts index fb7546f1..5014b2bc 100644 --- a/project/src/callbacks/InventoryCallbacks.ts +++ b/project/src/callbacks/InventoryCallbacks.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { InventoryController } from "@spt/controllers/InventoryController"; import { QuestController } from "@spt/controllers/QuestController"; import { IPmcData } from "@spt/models/eft/common/IPmcData"; @@ -23,15 +22,14 @@ import { IRedeemProfileRequestData } from "@spt/models/eft/inventory/IRedeemProf import { ISetFavoriteItems } from "@spt/models/eft/inventory/ISetFavoriteItems"; import { IItemEventRouterResponse } from "@spt/models/eft/itemEvent/IItemEventRouterResponse"; import { IFailQuestRequestData } from "@spt/models/eft/quests/IFailQuestRequestData"; +import { inject, injectable } from "tsyringe"; @injectable() -export class InventoryCallbacks -{ +export class InventoryCallbacks { constructor( @inject("InventoryController") protected inventoryController: InventoryController, @inject("QuestController") protected questController: QuestController, - ) - {} + ) {} /** Handle client/game/profile/items/moving Move event */ public moveItem( @@ -39,8 +37,7 @@ export class InventoryCallbacks body: IInventoryMoveRequestData, sessionID: string, output: IItemEventRouterResponse, - ): IItemEventRouterResponse - { + ): IItemEventRouterResponse { this.inventoryController.moveItem(pmcData, body, sessionID, output); return output; @@ -52,8 +49,7 @@ export class InventoryCallbacks body: IInventoryRemoveRequestData, sessionID: string, output: IItemEventRouterResponse, - ): IItemEventRouterResponse - { + ): IItemEventRouterResponse { this.inventoryController.discardItem(pmcData, body, sessionID, output); return output; @@ -65,8 +61,7 @@ export class InventoryCallbacks body: IInventorySplitRequestData, sessionID: string, output: IItemEventRouterResponse, - ): IItemEventRouterResponse - { + ): IItemEventRouterResponse { return this.inventoryController.splitItem(pmcData, body, sessionID, output); } @@ -75,8 +70,7 @@ export class InventoryCallbacks body: IInventoryMergeRequestData, sessionID: string, output: IItemEventRouterResponse, - ): IItemEventRouterResponse - { + ): IItemEventRouterResponse { return this.inventoryController.mergeItem(pmcData, body, sessionID, output); } @@ -85,20 +79,17 @@ export class InventoryCallbacks request: IInventoryTransferRequestData, sessionID: string, output: IItemEventRouterResponse, - ): IItemEventRouterResponse - { + ): IItemEventRouterResponse { return this.inventoryController.transferItem(pmcData, request, sessionID, output); } /** Handle Swap */ // TODO: how is this triggered - public swapItem(pmcData: IPmcData, body: IInventorySwapRequestData, sessionID: string): IItemEventRouterResponse - { + public swapItem(pmcData: IPmcData, body: IInventorySwapRequestData, sessionID: string): IItemEventRouterResponse { return this.inventoryController.swapItem(pmcData, body, sessionID); } - public foldItem(pmcData: IPmcData, body: IInventoryFoldRequestData, sessionID: string): IItemEventRouterResponse - { + public foldItem(pmcData: IPmcData, body: IInventoryFoldRequestData, sessionID: string): IItemEventRouterResponse { return this.inventoryController.foldItem(pmcData, body, sessionID); } @@ -106,13 +97,11 @@ export class InventoryCallbacks pmcData: IPmcData, body: IInventoryToggleRequestData, sessionID: string, - ): IItemEventRouterResponse - { + ): IItemEventRouterResponse { return this.inventoryController.toggleItem(pmcData, body, sessionID); } - public tagItem(pmcData: IPmcData, body: IInventoryTagRequestData, sessionID: string): IItemEventRouterResponse - { + public tagItem(pmcData: IPmcData, body: IInventoryTagRequestData, sessionID: string): IItemEventRouterResponse { return this.inventoryController.tagItem(pmcData, body, sessionID); } @@ -121,8 +110,7 @@ export class InventoryCallbacks body: IInventoryBindRequestData, sessionID: string, output: IItemEventRouterResponse, - ): IItemEventRouterResponse - { + ): IItemEventRouterResponse { this.inventoryController.bindItem(pmcData, body, sessionID); return output; @@ -133,8 +121,7 @@ export class InventoryCallbacks body: IInventoryBindRequestData, sessionID: string, output: IItemEventRouterResponse, - ): IItemEventRouterResponse - { + ): IItemEventRouterResponse { this.inventoryController.unbindItem(pmcData, body, sessionID, output); return output; @@ -145,8 +132,7 @@ export class InventoryCallbacks body: IInventoryExamineRequestData, sessionID: string, output: IItemEventRouterResponse, - ): IItemEventRouterResponse - { + ): IItemEventRouterResponse { return this.inventoryController.examineItem(pmcData, body, sessionID, output); } @@ -155,8 +141,7 @@ export class InventoryCallbacks pmcData: IPmcData, body: IInventoryReadEncyclopediaRequestData, sessionID: string, - ): IItemEventRouterResponse - { + ): IItemEventRouterResponse { return this.inventoryController.readEncyclopedia(pmcData, body, sessionID); } @@ -166,8 +151,7 @@ export class InventoryCallbacks body: IInventorySortRequestData, sessionID: string, output: IItemEventRouterResponse, - ): IItemEventRouterResponse - { + ): IItemEventRouterResponse { this.inventoryController.sortInventory(pmcData, body, sessionID); return output; @@ -178,8 +162,7 @@ export class InventoryCallbacks body: IInventoryCreateMarkerRequestData, sessionID: string, output: IItemEventRouterResponse, - ): IItemEventRouterResponse - { + ): IItemEventRouterResponse { this.inventoryController.createMapMarker(pmcData, body, sessionID, output); return output; @@ -190,8 +173,7 @@ export class InventoryCallbacks body: IInventoryDeleteMarkerRequestData, sessionID: string, output: IItemEventRouterResponse, - ): IItemEventRouterResponse - { + ): IItemEventRouterResponse { this.inventoryController.deleteMapMarker(pmcData, body, sessionID, output); return output; @@ -202,8 +184,7 @@ export class InventoryCallbacks body: IInventoryEditMarkerRequestData, sessionID: string, output: IItemEventRouterResponse, - ): IItemEventRouterResponse - { + ): IItemEventRouterResponse { this.inventoryController.editMapMarker(pmcData, body, sessionID, output); return output; @@ -215,8 +196,7 @@ export class InventoryCallbacks body: IOpenRandomLootContainerRequestData, sessionID: string, output: IItemEventRouterResponse, - ): IItemEventRouterResponse - { + ): IItemEventRouterResponse { this.inventoryController.openRandomLootContainer(pmcData, body, sessionID, output); return output; @@ -227,8 +207,7 @@ export class InventoryCallbacks body: IRedeemProfileRequestData, sessionId: string, output: IItemEventRouterResponse, - ): IItemEventRouterResponse - { + ): IItemEventRouterResponse { this.inventoryController.redeemProfileReward(pmcData, body, sessionId); return output; @@ -239,8 +218,7 @@ export class InventoryCallbacks body: ISetFavoriteItems, sessionId: string, output: IItemEventRouterResponse, - ): IItemEventRouterResponse - { + ): IItemEventRouterResponse { this.inventoryController.setFavoriteItem(pmcData, body, sessionId); return output; @@ -255,8 +233,7 @@ export class InventoryCallbacks request: IFailQuestRequestData, sessionID: string, output: IItemEventRouterResponse, - ): IItemEventRouterResponse - { + ): IItemEventRouterResponse { return this.questController.failQuest(pmcData, request, sessionID, output); } } diff --git a/project/src/callbacks/ItemEventCallbacks.ts b/project/src/callbacks/ItemEventCallbacks.ts index 96da162a..ee02539e 100644 --- a/project/src/callbacks/ItemEventCallbacks.ts +++ b/project/src/callbacks/ItemEventCallbacks.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { IGetBodyResponseData } from "@spt/models/eft/httpResponse/IGetBodyResponseData"; import { Warning } from "@spt/models/eft/itemEvent/IItemEventRouterBase"; import { IItemEventRouterRequest } from "@spt/models/eft/itemEvent/IItemEventRouterRequest"; @@ -6,29 +5,27 @@ import { IItemEventRouterResponse } from "@spt/models/eft/itemEvent/IItemEventRo import { BackendErrorCodes } from "@spt/models/enums/BackendErrorCodes"; import { ItemEventRouter } from "@spt/routers/ItemEventRouter"; import { HttpResponseUtil } from "@spt/utils/HttpResponseUtil"; +import { inject, injectable } from "tsyringe"; @injectable() -export class ItemEventCallbacks -{ +export class ItemEventCallbacks { constructor( @inject("HttpResponseUtil") protected httpResponse: HttpResponseUtil, @inject("ItemEventRouter") protected itemEventRouter: ItemEventRouter, - ) - {} + ) {} public async handleEvents( url: string, info: IItemEventRouterRequest, sessionID: string, - ): Promise> - { + ): Promise> { const eventResponse = await this.itemEventRouter.handleEvents(info, sessionID); const result = this.isCriticalError(eventResponse.warnings) ? this.httpResponse.getBody( - eventResponse, - this.getErrorCode(eventResponse.warnings), - eventResponse.warnings[0].errmsg, - ) + eventResponse, + this.getErrorCode(eventResponse.warnings), + eventResponse.warnings[0].errmsg, + ) : this.httpResponse.getBody(eventResponse); return result; @@ -39,15 +36,12 @@ export class ItemEventCallbacks * @param warnings The list of warnings to check for critical errors * @returns */ - private isCriticalError(warnings: Warning[]): boolean - { + private isCriticalError(warnings: Warning[]): boolean { // List of non-critical error codes, we return true if any error NOT included is passed in const nonCriticalErrorCodes: BackendErrorCodes[] = [BackendErrorCodes.NOTENOUGHSPACE]; - for (const warning of warnings) - { - if (!nonCriticalErrorCodes.includes(+(warning?.code ?? "0"))) - { + for (const warning of warnings) { + if (!nonCriticalErrorCodes.includes(+(warning?.code ?? "0"))) { return true; } } @@ -55,10 +49,8 @@ export class ItemEventCallbacks return false; } - protected getErrorCode(warnings: Warning[]): number - { - if (warnings[0]?.code) - { + protected getErrorCode(warnings: Warning[]): number { + if (warnings[0]?.code) { return Number(warnings[0].code); } return BackendErrorCodes.UNKNOWN_ERROR; diff --git a/project/src/callbacks/LauncherCallbacks.ts b/project/src/callbacks/LauncherCallbacks.ts index 6324f5fb..e60cc5f1 100644 --- a/project/src/callbacks/LauncherCallbacks.ts +++ b/project/src/callbacks/LauncherCallbacks.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { LauncherController } from "@spt/controllers/LauncherController"; import { IEmptyRequestData } from "@spt/models/eft/common/IEmptyRequestData"; import { IChangeRequestData } from "@spt/models/eft/launcher/IChangeRequestData"; @@ -8,86 +7,72 @@ import { IRemoveProfileData } from "@spt/models/eft/launcher/IRemoveProfileData" import { SaveServer } from "@spt/servers/SaveServer"; import { HttpResponseUtil } from "@spt/utils/HttpResponseUtil"; import { Watermark } from "@spt/utils/Watermark"; +import { inject, injectable } from "tsyringe"; @injectable() -export class LauncherCallbacks -{ +export class LauncherCallbacks { constructor( @inject("HttpResponseUtil") protected httpResponse: HttpResponseUtil, @inject("LauncherController") protected launcherController: LauncherController, @inject("SaveServer") protected saveServer: SaveServer, @inject("Watermark") protected watermark: Watermark, - ) - {} + ) {} - public connect(): string - { + public connect(): string { return this.httpResponse.noBody(this.launcherController.connect()); } - public login(url: string, info: ILoginRequestData, sessionID: string): string - { + public login(url: string, info: ILoginRequestData, sessionID: string): string { const output = this.launcherController.login(info); return !output ? "FAILED" : output; } - public register(url: string, info: IRegisterData, sessionID: string): "FAILED" | "OK" - { + public register(url: string, info: IRegisterData, sessionID: string): "FAILED" | "OK" { const output = this.launcherController.register(info); return !output ? "FAILED" : "OK"; } - public get(url: string, info: ILoginRequestData, sessionID: string): string - { + public get(url: string, info: ILoginRequestData, sessionID: string): string { const output = this.launcherController.find(this.launcherController.login(info)); return this.httpResponse.noBody(output); } - public changeUsername(url: string, info: IChangeRequestData, sessionID: string): "FAILED" | "OK" - { + public changeUsername(url: string, info: IChangeRequestData, sessionID: string): "FAILED" | "OK" { const output = this.launcherController.changeUsername(info); return !output ? "FAILED" : "OK"; } - public changePassword(url: string, info: IChangeRequestData, sessionID: string): "FAILED" | "OK" - { + public changePassword(url: string, info: IChangeRequestData, sessionID: string): "FAILED" | "OK" { const output = this.launcherController.changePassword(info); return !output ? "FAILED" : "OK"; } - public wipe(url: string, info: IRegisterData, sessionID: string): "FAILED" | "OK" - { + public wipe(url: string, info: IRegisterData, sessionID: string): "FAILED" | "OK" { const output = this.launcherController.wipe(info); return !output ? "FAILED" : "OK"; } - public getServerVersion(): string - { + public getServerVersion(): string { return this.httpResponse.noBody(this.watermark.getVersionTag()); } - public ping(url: string, info: IEmptyRequestData, sessionID: string): string - { + public ping(url: string, info: IEmptyRequestData, sessionID: string): string { return this.httpResponse.noBody("pong!"); } - public removeProfile(url: string, info: IRemoveProfileData, sessionID: string): string - { + public removeProfile(url: string, info: IRemoveProfileData, sessionID: string): string { return this.httpResponse.noBody(this.saveServer.removeProfile(sessionID)); } - public getCompatibleTarkovVersion(): string - { + public getCompatibleTarkovVersion(): string { return this.httpResponse.noBody(this.launcherController.getCompatibleTarkovVersion()); } - public getLoadedServerMods(): string - { + public getLoadedServerMods(): string { return this.httpResponse.noBody(this.launcherController.getLoadedServerMods()); } - public getServerModsProfileUsed(url: string, info: IEmptyRequestData, sessionId: string): string - { + public getServerModsProfileUsed(url: string, info: IEmptyRequestData, sessionId: string): string { return this.httpResponse.noBody(this.launcherController.getServerModsProfileUsed(sessionId)); } } diff --git a/project/src/callbacks/LocationCallbacks.ts b/project/src/callbacks/LocationCallbacks.ts index da0541f9..140702c4 100644 --- a/project/src/callbacks/LocationCallbacks.ts +++ b/project/src/callbacks/LocationCallbacks.ts @@ -1,27 +1,24 @@ -import { inject, injectable } from "tsyringe"; import { LocationController } from "@spt/controllers/LocationController"; import { IEmptyRequestData } from "@spt/models/eft/common/IEmptyRequestData"; import { ILocationsGenerateAllResponse } from "@spt/models/eft/common/ILocationsSourceDestinationBase"; import { IGetBodyResponseData } from "@spt/models/eft/httpResponse/IGetBodyResponseData"; import { IGetAirdropLootResponse } from "@spt/models/eft/location/IGetAirdropLootResponse"; import { HttpResponseUtil } from "@spt/utils/HttpResponseUtil"; +import { inject, injectable } from "tsyringe"; @injectable() -export class LocationCallbacks -{ +export class LocationCallbacks { constructor( @inject("HttpResponseUtil") protected httpResponse: HttpResponseUtil, @inject("LocationController") protected locationController: LocationController, - ) - {} + ) {} /** Handle client/locations */ public getLocationData( url: string, info: IEmptyRequestData, sessionID: string, - ): IGetBodyResponseData - { + ): IGetBodyResponseData { return this.httpResponse.getBody(this.locationController.generateAll(sessionID)); } @@ -30,8 +27,7 @@ export class LocationCallbacks url: string, info: IEmptyRequestData, sessionID: string, - ): IGetBodyResponseData - { + ): IGetBodyResponseData { return this.httpResponse.getBody(this.locationController.getAirdropLoot()); } } diff --git a/project/src/callbacks/MatchCallbacks.ts b/project/src/callbacks/MatchCallbacks.ts index 114db4f0..4b00825b 100644 --- a/project/src/callbacks/MatchCallbacks.ts +++ b/project/src/callbacks/MatchCallbacks.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { MatchController } from "@spt/controllers/MatchController"; import { IEmptyRequestData } from "@spt/models/eft/common/IEmptyRequestData"; import { IGetBodyResponseData } from "@spt/models/eft/httpResponse/IGetBodyResponseData"; @@ -22,33 +21,29 @@ import { IUpdatePingRequestData } from "@spt/models/eft/match/IUpdatePingRequest import { DatabaseService } from "@spt/services/DatabaseService"; import { HttpResponseUtil } from "@spt/utils/HttpResponseUtil"; import { JsonUtil } from "@spt/utils/JsonUtil"; +import { inject, injectable } from "tsyringe"; @injectable() -export class MatchCallbacks -{ +export class MatchCallbacks { constructor( @inject("HttpResponseUtil") protected httpResponse: HttpResponseUtil, @inject("JsonUtil") protected jsonUtil: JsonUtil, @inject("MatchController") protected matchController: MatchController, @inject("DatabaseService") protected databaseService: DatabaseService, - ) - {} + ) {} /** Handle client/match/updatePing */ - public updatePing(url: string, info: IUpdatePingRequestData, sessionID: string): INullResponseData - { + public updatePing(url: string, info: IUpdatePingRequestData, sessionID: string): INullResponseData { return this.httpResponse.nullResponse(); } // Handle client/match/exit - public exitMatch(url: string, info: IEmptyRequestData, sessionID: string): INullResponseData - { + public exitMatch(url: string, info: IEmptyRequestData, sessionID: string): INullResponseData { return this.httpResponse.nullResponse(); } /** Handle client/match/group/exit_from_menu */ - public exitToMenu(url: string, info: IEmptyRequestData, sessionID: string): INullResponseData - { + public exitToMenu(url: string, info: IEmptyRequestData, sessionID: string): INullResponseData { return this.httpResponse.nullResponse(); } @@ -56,18 +51,15 @@ export class MatchCallbacks url: string, info: IEmptyRequestData, sessionID: string, - ): IGetBodyResponseData - { + ): IGetBodyResponseData { return this.httpResponse.getBody({ squad: [] }); } - public startGroupSearch(url: string, info: IEmptyRequestData, sessionID: string): INullResponseData - { + public startGroupSearch(url: string, info: IEmptyRequestData, sessionID: string): INullResponseData { return this.httpResponse.nullResponse(); } - public stopGroupSearch(url: string, info: IEmptyRequestData, sessionID: string): INullResponseData - { + public stopGroupSearch(url: string, info: IEmptyRequestData, sessionID: string): INullResponseData { return this.httpResponse.nullResponse(); } @@ -76,8 +68,7 @@ export class MatchCallbacks url: string, info: IMatchGroupInviteSendRequest, sessionID: string, - ): IGetBodyResponseData - { + ): IGetBodyResponseData { return this.httpResponse.getBody("2427943f23698ay9f2863735"); } @@ -86,8 +77,7 @@ export class MatchCallbacks url: string, info: IRequestIdRequest, sessionId: string, - ): IGetBodyResponseData - { + ): IGetBodyResponseData { const result = []; result.push({}); @@ -95,14 +85,12 @@ export class MatchCallbacks } /** Handle client/match/group/invite/decline */ - public declineGroupInvite(url: string, info: IRequestIdRequest, sessionId: string): IGetBodyResponseData - { + public declineGroupInvite(url: string, info: IRequestIdRequest, sessionId: string): IGetBodyResponseData { return this.httpResponse.getBody(true); } /** Handle client/match/group/invite/cancel */ - public cancelGroupInvite(url: string, info: IRequestIdRequest, sessionID: string): IGetBodyResponseData - { + public cancelGroupInvite(url: string, info: IRequestIdRequest, sessionID: string): IGetBodyResponseData { return this.httpResponse.getBody(true); } @@ -111,8 +99,7 @@ export class MatchCallbacks url: string, info: IMatchGroupTransferRequest, sessionId: string, - ): IGetBodyResponseData - { + ): IGetBodyResponseData { return this.httpResponse.getBody(true); } @@ -121,19 +108,16 @@ export class MatchCallbacks url: string, info: IEmptyRequestData, sessionId: string, - ): IGetBodyResponseData - { + ): IGetBodyResponseData { return this.httpResponse.getBody(true); } - public putMetrics(url: string, request: IPutMetricsRequestData, sessionId: string): INullResponseData - { + public putMetrics(url: string, request: IPutMetricsRequestData, sessionId: string): INullResponseData { return this.httpResponse.nullResponse(); } // Handle client/match/available - public serverAvailable(url: string, info: IEmptyRequestData, sessionId: string): IGetBodyResponseData - { + public serverAvailable(url: string, info: IEmptyRequestData, sessionId: string): IGetBodyResponseData { const output = this.matchController.getEnabled(); return this.httpResponse.getBody(output); @@ -144,14 +128,12 @@ export class MatchCallbacks url: string, info: IMatchGroupStartGameRequest, sessionID: string, - ): IGetBodyResponseData - { + ): IGetBodyResponseData { return this.httpResponse.getBody(this.matchController.joinMatch(info, sessionID)); } /** Handle client/getMetricsConfig */ - public getMetrics(url: string, info: any, sessionID: string): IGetBodyResponseData - { + public getMetrics(url: string, info: any, sessionID: string): IGetBodyResponseData { return this.httpResponse.getBody(this.jsonUtil.serialize(this.databaseService.getMatch().metrics)); } @@ -164,21 +146,18 @@ export class MatchCallbacks url: string, info: IMatchGroupStatusRequest, sessionID: string, - ): IGetBodyResponseData - { + ): IGetBodyResponseData { return this.httpResponse.getBody(this.matchController.getGroupStatus(info)); } /** Handle client/match/group/delete */ - public deleteGroup(url: string, info: IEmptyRequestData, sessionID: string): IGetBodyResponseData - { + public deleteGroup(url: string, info: IEmptyRequestData, sessionID: string): IGetBodyResponseData { this.matchController.deleteGroup(info); return this.httpResponse.getBody(true); } // Handle client/match/group/leave - public leaveGroup(url: string, info: IEmptyRequestData, sessionID: string): IGetBodyResponseData - { + public leaveGroup(url: string, info: IEmptyRequestData, sessionID: string): IGetBodyResponseData { return this.httpResponse.getBody(true); } @@ -187,8 +166,7 @@ export class MatchCallbacks url: string, info: IMatchGroupPlayerRemoveRequest, sessionID: string, - ): IGetBodyResponseData - { + ): IGetBodyResponseData { return this.httpResponse.getBody(true); } @@ -197,18 +175,12 @@ export class MatchCallbacks url: string, info: IStartLocalRaidRequestData, sessionID: string, - ): IGetBodyResponseData - { + ): IGetBodyResponseData { return this.httpResponse.getBody(this.matchController.startLocalRaid(sessionID, info)); } /** Handle client/match/local/end */ - public endLocalRaid( - url: string, - info: IEndLocalRaidRequestData, - sessionID: string, - ): INullResponseData - { + public endLocalRaid(url: string, info: IEndLocalRaidRequestData, sessionID: string): INullResponseData { this.matchController.endLocalRaid(sessionID, info); return this.httpResponse.nullResponse(); } @@ -218,8 +190,7 @@ export class MatchCallbacks url: string, info: IGetRaidConfigurationRequestData, sessionID: string, - ): INullResponseData - { + ): INullResponseData { this.matchController.configureOfflineRaid(info, sessionID); return this.httpResponse.nullResponse(); } @@ -229,20 +200,17 @@ export class MatchCallbacks url: string, info: IGetRaidConfigurationRequestData, sessionID: string, - ): INullResponseData - { + ): INullResponseData { return this.httpResponse.nullResponse(); } /** Handle client/match/group/raid/ready */ - public raidReady(url: string, info: IEmptyRequestData, sessionId: string): IGetBodyResponseData - { + public raidReady(url: string, info: IEmptyRequestData, sessionId: string): IGetBodyResponseData { return this.httpResponse.getBody(true); } /** Handle client/match/group/raid/not-ready */ - public notRaidReady(url: string, info: IEmptyRequestData, sessionId: string): IGetBodyResponseData - { + public notRaidReady(url: string, info: IEmptyRequestData, sessionId: string): IGetBodyResponseData { return this.httpResponse.getBody(true); } } diff --git a/project/src/callbacks/ModCallbacks.ts b/project/src/callbacks/ModCallbacks.ts index 3655902c..c6dce2c9 100644 --- a/project/src/callbacks/ModCallbacks.ts +++ b/project/src/callbacks/ModCallbacks.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { OnLoad } from "@spt/di/OnLoad"; import { PostSptModLoader } from "@spt/loaders/PostSptModLoader"; import { ConfigTypes } from "@spt/models/enums/ConfigTypes"; @@ -8,10 +7,10 @@ import { ConfigServer } from "@spt/servers/ConfigServer"; import { LocalisationService } from "@spt/services/LocalisationService"; import { HttpFileUtil } from "@spt/utils/HttpFileUtil"; import { HttpResponseUtil } from "@spt/utils/HttpResponseUtil"; +import { inject, injectable } from "tsyringe"; @injectable() -export class ModCallbacks implements OnLoad -{ +export class ModCallbacks implements OnLoad { protected httpConfig: IHttpConfig; constructor( @@ -21,21 +20,17 @@ export class ModCallbacks implements OnLoad @inject("PostSptModLoader") protected postSptModLoader: PostSptModLoader, @inject("LocalisationService") protected localisationService: LocalisationService, @inject("ConfigServer") protected configServer: ConfigServer, - ) - { + ) { this.httpConfig = this.configServer.getConfig(ConfigTypes.HTTP); } - public async onLoad(): Promise - { - if (globalThis.G_MODS_ENABLED) - { + public async onLoad(): Promise { + if (globalThis.G_MODS_ENABLED) { await this.postSptModLoader.load(); } } - public getRoute(): string - { + public getRoute(): string { return "spt-mods"; } } diff --git a/project/src/callbacks/NoteCallbacks.ts b/project/src/callbacks/NoteCallbacks.ts index 723496f5..603a89fb 100644 --- a/project/src/callbacks/NoteCallbacks.ts +++ b/project/src/callbacks/NoteCallbacks.ts @@ -1,30 +1,25 @@ -import { inject, injectable } from "tsyringe"; import { NoteController } from "@spt/controllers/NoteController"; import { IPmcData } from "@spt/models/eft/common/IPmcData"; import { IItemEventRouterResponse } from "@spt/models/eft/itemEvent/IItemEventRouterResponse"; import { INoteActionData } from "@spt/models/eft/notes/INoteActionData"; +import { inject, injectable } from "tsyringe"; @injectable() -export class NoteCallbacks -{ - constructor(@inject("NoteController") protected noteController: NoteController) - {} +export class NoteCallbacks { + constructor(@inject("NoteController") protected noteController: NoteController) {} /** Handle AddNote event */ - public addNote(pmcData: IPmcData, body: INoteActionData, sessionID: string): IItemEventRouterResponse - { + public addNote(pmcData: IPmcData, body: INoteActionData, sessionID: string): IItemEventRouterResponse { return this.noteController.addNote(pmcData, body, sessionID); } /** Handle EditNote event */ - public editNote(pmcData: IPmcData, body: INoteActionData, sessionID: string): IItemEventRouterResponse - { + public editNote(pmcData: IPmcData, body: INoteActionData, sessionID: string): IItemEventRouterResponse { return this.noteController.editNote(pmcData, body, sessionID); } /** Handle DeleteNote event */ - public deleteNote(pmcData: IPmcData, body: INoteActionData, sessionID: string): IItemEventRouterResponse - { + public deleteNote(pmcData: IPmcData, body: INoteActionData, sessionID: string): IItemEventRouterResponse { return this.noteController.deleteNote(pmcData, body, sessionID); } } diff --git a/project/src/callbacks/NotifierCallbacks.ts b/project/src/callbacks/NotifierCallbacks.ts index 3eb9ab73..d6716add 100644 --- a/project/src/callbacks/NotifierCallbacks.ts +++ b/project/src/callbacks/NotifierCallbacks.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { NotifierController } from "@spt/controllers/NotifierController"; import { HttpServerHelper } from "@spt/helpers/HttpServerHelper"; import { IEmptyRequestData } from "@spt/models/eft/common/IEmptyRequestData"; @@ -8,17 +7,16 @@ import { INotifierChannel } from "@spt/models/eft/notifier/INotifier"; import { ISelectProfileResponse } from "@spt/models/eft/notifier/ISelectProfileResponse"; import { HttpResponseUtil } from "@spt/utils/HttpResponseUtil"; import { JsonUtil } from "@spt/utils/JsonUtil"; +import { inject, injectable } from "tsyringe"; @injectable() -export class NotifierCallbacks -{ +export class NotifierCallbacks { constructor( @inject("HttpServerHelper") protected httpServerHelper: HttpServerHelper, @inject("HttpResponseUtil") protected httpResponse: HttpResponseUtil, @inject("JsonUtil") protected jsonUtil: JsonUtil, @inject("NotifierController") protected notifierController: NotifierController, - ) - {} + ) {} /** * If we don't have anything to send, it's ok to not send anything back @@ -26,8 +24,7 @@ export class NotifierCallbacks * until we actually have something to send because otherwise we'd spam the client * and the client would abort the connection due to spam. */ - public sendNotification(sessionID: string, req: any, resp: any, data: any): void - { + public sendNotification(sessionID: string, req: any, resp: any, data: any): void { const splittedUrl = req.url.split("/"); const tmpSessionID = splittedUrl[splittedUrl.length - 1].split("?last_id")[0]; @@ -44,8 +41,7 @@ export class NotifierCallbacks /** Handle push/notifier/get */ /** Handle push/notifier/getwebsocket */ // TODO: removed from client? - public getNotifier(url: string, info: any, sessionID: string): IGetBodyResponseData - { + public getNotifier(url: string, info: any, sessionID: string): IGetBodyResponseData { return this.httpResponse.emptyArrayResponse(); } @@ -54,8 +50,7 @@ export class NotifierCallbacks url: string, info: IEmptyRequestData, sessionID: string, - ): IGetBodyResponseData - { + ): IGetBodyResponseData { return this.httpResponse.getBody(this.notifierController.getChannel(sessionID)); } @@ -67,13 +62,11 @@ export class NotifierCallbacks url: string, info: IUIDRequestData, sessionID: string, - ): IGetBodyResponseData - { + ): IGetBodyResponseData { return this.httpResponse.getBody({ status: "ok" }); } - public notify(url: string, info: any, sessionID: string): string - { + public notify(url: string, info: any, sessionID: string): string { return "NOTIFY"; } } diff --git a/project/src/callbacks/PresetCallbacks.ts b/project/src/callbacks/PresetCallbacks.ts index 0fafb7c1..81ff20d1 100644 --- a/project/src/callbacks/PresetCallbacks.ts +++ b/project/src/callbacks/PresetCallbacks.ts @@ -1,20 +1,16 @@ -import { inject, injectable } from "tsyringe"; import { PresetController } from "@spt/controllers/PresetController"; import { OnLoad } from "@spt/di/OnLoad"; +import { inject, injectable } from "tsyringe"; @injectable() -export class PresetCallbacks implements OnLoad -{ - constructor(@inject("PresetController") protected presetController: PresetController) - {} +export class PresetCallbacks implements OnLoad { + constructor(@inject("PresetController") protected presetController: PresetController) {} - public async onLoad(): Promise - { + public async onLoad(): Promise { this.presetController.initialize(); } - public getRoute(): string - { + public getRoute(): string { return "spt-presets"; } } diff --git a/project/src/callbacks/ProfileCallbacks.ts b/project/src/callbacks/ProfileCallbacks.ts index 364c1c12..733037fd 100644 --- a/project/src/callbacks/ProfileCallbacks.ts +++ b/project/src/callbacks/ProfileCallbacks.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { ProfileController } from "@spt/controllers/ProfileController"; import { ProfileHelper } from "@spt/helpers/ProfileHelper"; import { IEmptyRequestData } from "@spt/models/eft/common/IEmptyRequestData"; @@ -19,18 +18,17 @@ import { ISearchFriendResponse } from "@spt/models/eft/profile/ISearchFriendResp import { IValidateNicknameRequestData } from "@spt/models/eft/profile/IValidateNicknameRequestData"; import { HttpResponseUtil } from "@spt/utils/HttpResponseUtil"; import { TimeUtil } from "@spt/utils/TimeUtil"; +import { inject, injectable } from "tsyringe"; /** Handle profile related client events */ @injectable() -export class ProfileCallbacks -{ +export class ProfileCallbacks { constructor( @inject("HttpResponseUtil") protected httpResponse: HttpResponseUtil, @inject("TimeUtil") protected timeUtil: TimeUtil, @inject("ProfileController") protected profileController: ProfileController, @inject("ProfileHelper") protected profileHelper: ProfileHelper, - ) - {} + ) {} /** * Handle client/game/profile/create @@ -39,8 +37,7 @@ export class ProfileCallbacks url: string, info: IProfileCreateRequestData, sessionID: string, - ): IGetBodyResponseData - { + ): IGetBodyResponseData { const id = this.profileController.createProfile(info, sessionID); return this.httpResponse.getBody({ uid: id }); } @@ -49,8 +46,7 @@ export class ProfileCallbacks * Handle client/game/profile/list * Get the complete player profile (scav + pmc character) */ - public getProfileData(url: string, info: IEmptyRequestData, sessionID: string): IGetBodyResponseData - { + public getProfileData(url: string, info: IEmptyRequestData, sessionID: string): IGetBodyResponseData { return this.httpResponse.getBody(this.profileController.getCompleteProfile(sessionID)); } @@ -63,16 +59,14 @@ export class ProfileCallbacks * @param sessionID Session id * @returns Profile object */ - public regenerateScav(url: string, info: IEmptyRequestData, sessionID: string): IGetBodyResponseData - { + public regenerateScav(url: string, info: IEmptyRequestData, sessionID: string): IGetBodyResponseData { return this.httpResponse.getBody([this.profileController.generatePlayerScav(sessionID)]); } /** * Handle client/game/profile/voice/change event */ - public changeVoice(url: string, info: IProfileChangeVoiceRequestData, sessionID: string): INullResponseData - { + public changeVoice(url: string, info: IProfileChangeVoiceRequestData, sessionID: string): INullResponseData { this.profileController.changeVoice(info, sessionID); return this.httpResponse.nullResponse(); } @@ -85,17 +79,14 @@ export class ProfileCallbacks url: string, info: IProfileChangeNicknameRequestData, sessionID: string, - ): IGetBodyResponseData - { + ): IGetBodyResponseData { const output = this.profileController.changeNickname(info, sessionID); - if (output === "taken") - { + if (output === "taken") { return this.httpResponse.getBody(undefined, 255, "The nickname is already in use"); } - if (output === "tooshort") - { + if (output === "tooshort") { return this.httpResponse.getBody(undefined, 1, "The nickname is too short"); } @@ -109,17 +100,14 @@ export class ProfileCallbacks url: string, info: IValidateNicknameRequestData, sessionID: string, - ): IGetBodyResponseData - { + ): IGetBodyResponseData { const output = this.profileController.validateNickname(info, sessionID); - if (output === "taken") - { + if (output === "taken") { return this.httpResponse.getBody(undefined, 255, "225 - "); } - if (output === "tooshort") - { + if (output === "tooshort") { return this.httpResponse.getBody(undefined, 256, "256 - "); } @@ -129,8 +117,7 @@ export class ProfileCallbacks /** * Handle client/game/profile/nickname/reserved */ - public getReservedNickname(url: string, info: IEmptyRequestData, sessionID: string): IGetBodyResponseData - { + public getReservedNickname(url: string, info: IEmptyRequestData, sessionID: string): IGetBodyResponseData { return this.httpResponse.getBody("SPTarkov"); } @@ -142,8 +129,7 @@ export class ProfileCallbacks url: string, info: IEmptyRequestData, sessionID: string, - ): IGetBodyResponseData - { + ): IGetBodyResponseData { return this.httpResponse.getBody(this.profileController.getProfileStatus(sessionID)); } @@ -155,8 +141,7 @@ export class ProfileCallbacks url: string, request: IGetOtherProfileRequest, sessionID: string, - ): IGetBodyResponseData - { + ): IGetBodyResponseData { return this.httpResponse.getBody(this.profileController.getOtherProfile(sessionID, request)); } @@ -167,8 +152,7 @@ export class ProfileCallbacks url: string, info: IGetProfileSettingsRequest, sessionId: string, - ): IGetBodyResponseData - { + ): IGetBodyResponseData { return this.httpResponse.getBody(this.profileController.setChosenProfileIcon(sessionId, info)); } @@ -179,24 +163,21 @@ export class ProfileCallbacks url: string, info: ISearchFriendRequestData, sessionID: string, - ): IGetBodyResponseData - { + ): IGetBodyResponseData { return this.httpResponse.getBody(this.profileController.getFriends(info, sessionID)); } /** * Handle launcher/profile/info */ - public getMiniProfile(url: string, info: IGetMiniProfileRequestData, sessionID: string): string - { + public getMiniProfile(url: string, info: IGetMiniProfileRequestData, sessionID: string): string { return this.httpResponse.noBody(this.profileController.getMiniProfile(sessionID)); } /** * Handle /launcher/profiles */ - public getAllMiniProfiles(url: string, info: IEmptyRequestData, sessionID: string): string - { + public getAllMiniProfiles(url: string, info: IEmptyRequestData, sessionID: string): string { return this.httpResponse.noBody(this.profileController.getMiniProfiles()); } } diff --git a/project/src/callbacks/QuestCallbacks.ts b/project/src/callbacks/QuestCallbacks.ts index 8ea32290..e080abce 100644 --- a/project/src/callbacks/QuestCallbacks.ts +++ b/project/src/callbacks/QuestCallbacks.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { QuestController } from "@spt/controllers/QuestController"; import { RepeatableQuestController } from "@spt/controllers/RepeatableQuestController"; import { IEmptyRequestData } from "@spt/models/eft/common/IEmptyRequestData"; @@ -13,16 +12,15 @@ import { IHandoverQuestRequestData } from "@spt/models/eft/quests/IHandoverQuest import { IListQuestsRequestData } from "@spt/models/eft/quests/IListQuestsRequestData"; import { IRepeatableQuestChangeRequest } from "@spt/models/eft/quests/IRepeatableQuestChangeRequest"; import { HttpResponseUtil } from "@spt/utils/HttpResponseUtil"; +import { inject, injectable } from "tsyringe"; @injectable() -export class QuestCallbacks -{ +export class QuestCallbacks { constructor( @inject("HttpResponseUtil") protected httpResponse: HttpResponseUtil, @inject("QuestController") protected questController: QuestController, @inject("RepeatableQuestController") protected repeatableQuestController: RepeatableQuestController, - ) - {} + ) {} /** * Handle RepeatableQuestChange event @@ -31,18 +29,15 @@ export class QuestCallbacks pmcData: IPmcData, body: IRepeatableQuestChangeRequest, sessionID: string, - ): IItemEventRouterResponse - { + ): IItemEventRouterResponse { return this.repeatableQuestController.changeRepeatableQuest(pmcData, body, sessionID); } /** * Handle QuestAccept event */ - public acceptQuest(pmcData: IPmcData, body: IAcceptQuestRequestData, sessionID: string): IItemEventRouterResponse - { - if (body.type === "repeatable") - { + public acceptQuest(pmcData: IPmcData, body: IAcceptQuestRequestData, sessionID: string): IItemEventRouterResponse { + if (body.type === "repeatable") { return this.questController.acceptRepeatableQuest(pmcData, body, sessionID); } return this.questController.acceptQuest(pmcData, body, sessionID); @@ -55,8 +50,7 @@ export class QuestCallbacks pmcData: IPmcData, body: ICompleteQuestRequestData, sessionID: string, - ): IItemEventRouterResponse - { + ): IItemEventRouterResponse { return this.questController.completeQuest(pmcData, body, sessionID); } @@ -67,16 +61,14 @@ export class QuestCallbacks pmcData: IPmcData, body: IHandoverQuestRequestData, sessionID: string, - ): IItemEventRouterResponse - { + ): IItemEventRouterResponse { return this.questController.handoverQuest(pmcData, body, sessionID); } /** * Handle client/quest/list */ - public listQuests(url: string, info: IListQuestsRequestData, sessionID: string): IGetBodyResponseData - { + public listQuests(url: string, info: IListQuestsRequestData, sessionID: string): IGetBodyResponseData { return this.httpResponse.getBody(this.questController.getClientQuests(sessionID)); } @@ -87,8 +79,7 @@ export class QuestCallbacks url: string, info: IEmptyRequestData, sessionID: string, - ): IGetBodyResponseData - { + ): IGetBodyResponseData { return this.httpResponse.getBody(this.repeatableQuestController.getClientRepeatableQuests(sessionID)); } } diff --git a/project/src/callbacks/RagfairCallbacks.ts b/project/src/callbacks/RagfairCallbacks.ts index bc5b8e9a..99310a8c 100644 --- a/project/src/callbacks/RagfairCallbacks.ts +++ b/project/src/callbacks/RagfairCallbacks.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { RagfairController } from "@spt/controllers/RagfairController"; import { OnLoad } from "@spt/di/OnLoad"; import { OnUpdate } from "@spt/di/OnUpdate"; @@ -24,13 +23,13 @@ import { ConfigServer } from "@spt/servers/ConfigServer"; import { RagfairServer } from "@spt/servers/RagfairServer"; import { RagfairTaxService } from "@spt/services/RagfairTaxService"; import { HttpResponseUtil } from "@spt/utils/HttpResponseUtil"; +import { inject, injectable } from "tsyringe"; /** * Handle ragfair related callback events */ @injectable() -export class RagfairCallbacks implements OnLoad, OnUpdate -{ +export class RagfairCallbacks implements OnLoad, OnUpdate { protected ragfairConfig: IRagfairConfig; constructor( @@ -39,25 +38,20 @@ export class RagfairCallbacks implements OnLoad, OnUpdate @inject("RagfairController") protected ragfairController: RagfairController, @inject("RagfairTaxService") protected ragfairTaxService: RagfairTaxService, @inject("ConfigServer") protected configServer: ConfigServer, - ) - { + ) { this.ragfairConfig = this.configServer.getConfig(ConfigTypes.RAGFAIR); } - public async onLoad(): Promise - { + public async onLoad(): Promise { await this.ragfairServer.load(); } - public getRoute(): string - { + public getRoute(): string { return "spt-ragfair"; } - public async onUpdate(timeSinceLastRun: number): Promise - { - if (timeSinceLastRun > this.ragfairConfig.runIntervalSeconds) - { + public async onUpdate(timeSinceLastRun: number): Promise { + if (timeSinceLastRun > this.ragfairConfig.runIntervalSeconds) { // There is a flag inside this class that only makes it run once. this.ragfairServer.addPlayerOffers(); @@ -76,8 +70,7 @@ export class RagfairCallbacks implements OnLoad, OnUpdate * Handle client/ragfair/search * Handle client/ragfair/find */ - public search(url: string, info: ISearchRequestData, sessionID: string): IGetBodyResponseData - { + public search(url: string, info: ISearchRequestData, sessionID: string): IGetBodyResponseData { return this.httpResponse.getBody(this.ragfairController.getOffers(sessionID, info)); } @@ -86,26 +79,22 @@ export class RagfairCallbacks implements OnLoad, OnUpdate url: string, info: IGetMarketPriceRequestData, sessionID: string, - ): IGetBodyResponseData - { + ): IGetBodyResponseData { return this.httpResponse.getBody(this.ragfairController.getItemMinAvgMaxFleaPriceValues(info)); } /** Handle RagFairAddOffer event */ - public addOffer(pmcData: IPmcData, info: IAddOfferRequestData, sessionID: string): IItemEventRouterResponse - { + public addOffer(pmcData: IPmcData, info: IAddOfferRequestData, sessionID: string): IItemEventRouterResponse { return this.ragfairController.addPlayerOffer(pmcData, info, sessionID); } /** Handle RagFairRemoveOffer event */ - public removeOffer(pmcData: IPmcData, info: IRemoveOfferRequestData, sessionID: string): IItemEventRouterResponse - { + public removeOffer(pmcData: IPmcData, info: IRemoveOfferRequestData, sessionID: string): IItemEventRouterResponse { return this.ragfairController.removeOffer(info, sessionID); } /** Handle RagFairRenewOffer event */ - public extendOffer(pmcData: IPmcData, info: IExtendOfferRequestData, sessionID: string): IItemEventRouterResponse - { + public extendOffer(pmcData: IPmcData, info: IExtendOfferRequestData, sessionID: string): IItemEventRouterResponse { return this.ragfairController.extendOffer(info, sessionID); } @@ -117,14 +106,12 @@ export class RagfairCallbacks implements OnLoad, OnUpdate url: string, request: IEmptyRequestData, sessionID: string, - ): IGetBodyResponseData> - { + ): IGetBodyResponseData> { return this.httpResponse.getBody(this.ragfairController.getAllFleaPrices()); } /** Handle client/reports/ragfair/send */ - public sendReport(url: string, info: ISendRagfairReportRequestData, sessionID: string): INullResponseData - { + public sendReport(url: string, info: ISendRagfairReportRequestData, sessionID: string): INullResponseData { return this.httpResponse.nullResponse(); } @@ -132,8 +119,7 @@ export class RagfairCallbacks implements OnLoad, OnUpdate url: string, request: IStorePlayerOfferTaxAmountRequestData, sessionId: string, - ): INullResponseData - { + ): INullResponseData { this.ragfairTaxService.storeClientOfferTaxValue(sessionId, request); return this.httpResponse.nullResponse(); } @@ -143,8 +129,7 @@ export class RagfairCallbacks implements OnLoad, OnUpdate url: string, request: IGetRagfairOfferByIdRequest, sessionID: string, - ): IGetBodyResponseData - { + ): IGetBodyResponseData { return this.httpResponse.getBody(this.ragfairController.getOfferById(sessionID, request)); } } diff --git a/project/src/callbacks/RepairCallbacks.ts b/project/src/callbacks/RepairCallbacks.ts index 97095090..a32a79f3 100644 --- a/project/src/callbacks/RepairCallbacks.ts +++ b/project/src/callbacks/RepairCallbacks.ts @@ -1,15 +1,13 @@ -import { inject, injectable } from "tsyringe"; import { RepairController } from "@spt/controllers/RepairController"; import { IPmcData } from "@spt/models/eft/common/IPmcData"; import { IItemEventRouterResponse } from "@spt/models/eft/itemEvent/IItemEventRouterResponse"; import { IRepairActionDataRequest } from "@spt/models/eft/repair/IRepairActionDataRequest"; import { ITraderRepairActionDataRequest } from "@spt/models/eft/repair/ITraderRepairActionDataRequest"; +import { inject, injectable } from "tsyringe"; @injectable() -export class RepairCallbacks -{ - constructor(@inject("RepairController") protected repairController: RepairController) - {} +export class RepairCallbacks { + constructor(@inject("RepairController") protected repairController: RepairController) {} /** * Handle TraderRepair event @@ -23,8 +21,7 @@ export class RepairCallbacks pmcData: IPmcData, traderRepairRequest: ITraderRepairActionDataRequest, sessionID: string, - ): IItemEventRouterResponse - { + ): IItemEventRouterResponse { return this.repairController.traderRepair(sessionID, traderRepairRequest, pmcData); } @@ -40,8 +37,7 @@ export class RepairCallbacks pmcData: IPmcData, repairRequest: IRepairActionDataRequest, sessionID: string, - ): IItemEventRouterResponse - { + ): IItemEventRouterResponse { return this.repairController.repairWithKit(sessionID, repairRequest, pmcData); } } diff --git a/project/src/callbacks/SaveCallbacks.ts b/project/src/callbacks/SaveCallbacks.ts index b5d7d941..82c3ee3b 100644 --- a/project/src/callbacks/SaveCallbacks.ts +++ b/project/src/callbacks/SaveCallbacks.ts @@ -1,39 +1,33 @@ -import { inject, injectable } from "tsyringe"; import { OnLoad } from "@spt/di/OnLoad"; import { OnUpdate } from "@spt/di/OnUpdate"; import { ConfigTypes } from "@spt/models/enums/ConfigTypes"; import { ICoreConfig } from "@spt/models/spt/config/ICoreConfig"; import { ConfigServer } from "@spt/servers/ConfigServer"; import { SaveServer } from "@spt/servers/SaveServer"; +import { inject, injectable } from "tsyringe"; @injectable() -export class SaveCallbacks implements OnLoad, OnUpdate -{ +export class SaveCallbacks implements OnLoad, OnUpdate { protected coreConfig: ICoreConfig; constructor( @inject("SaveServer") protected saveServer: SaveServer, @inject("ConfigServer") protected configServer: ConfigServer, - ) - { + ) { this.coreConfig = this.configServer.getConfig(ConfigTypes.CORE); } - public async onLoad(): Promise - { + public async onLoad(): Promise { this.saveServer.load(); } - public getRoute(): string - { + public getRoute(): string { return "spt-save"; } - public async onUpdate(secondsSinceLastRun: number): Promise - { + public async onUpdate(secondsSinceLastRun: number): Promise { // run every 15 seconds - if (secondsSinceLastRun > this.coreConfig.profileSaveIntervalSeconds) - { + if (secondsSinceLastRun > this.coreConfig.profileSaveIntervalSeconds) { this.saveServer.save(); return true; } diff --git a/project/src/callbacks/TradeCallbacks.ts b/project/src/callbacks/TradeCallbacks.ts index a77f5a0e..69195ea8 100644 --- a/project/src/callbacks/TradeCallbacks.ts +++ b/project/src/callbacks/TradeCallbacks.ts @@ -1,16 +1,14 @@ -import { inject, injectable } from "tsyringe"; import { TradeController } from "@spt/controllers/TradeController"; import { IPmcData } from "@spt/models/eft/common/IPmcData"; import { IItemEventRouterResponse } from "@spt/models/eft/itemEvent/IItemEventRouterResponse"; import { IProcessBaseTradeRequestData } from "@spt/models/eft/trade/IProcessBaseTradeRequestData"; import { IProcessRagfairTradeRequestData } from "@spt/models/eft/trade/IProcessRagfairTradeRequestData"; import { ISellScavItemsToFenceRequestData } from "@spt/models/eft/trade/ISellScavItemsToFenceRequestData"; +import { inject, injectable } from "tsyringe"; @injectable() -export class TradeCallbacks -{ - constructor(@inject("TradeController") protected tradeController: TradeController) - {} +export class TradeCallbacks { + constructor(@inject("TradeController") protected tradeController: TradeController) {} /** * Handle client/game/profile/items/moving TradingConfirm event @@ -19,8 +17,7 @@ export class TradeCallbacks pmcData: IPmcData, body: IProcessBaseTradeRequestData, sessionID: string, - ): IItemEventRouterResponse - { + ): IItemEventRouterResponse { // body can be IProcessBuyTradeRequestData or IProcessSellTradeRequestData return this.tradeController.confirmTrading(pmcData, body, sessionID); } @@ -30,8 +27,7 @@ export class TradeCallbacks pmcData: IPmcData, body: IProcessRagfairTradeRequestData, sessionID: string, - ): IItemEventRouterResponse - { + ): IItemEventRouterResponse { return this.tradeController.confirmRagfairTrading(pmcData, body, sessionID); } @@ -40,8 +36,7 @@ export class TradeCallbacks pmcData: IPmcData, body: ISellScavItemsToFenceRequestData, sessionID: string, - ): IItemEventRouterResponse - { + ): IItemEventRouterResponse { return this.tradeController.sellScavItemsToFence(pmcData, body, sessionID); } } diff --git a/project/src/callbacks/TraderCallbacks.ts b/project/src/callbacks/TraderCallbacks.ts index 45599353..9518070c 100644 --- a/project/src/callbacks/TraderCallbacks.ts +++ b/project/src/callbacks/TraderCallbacks.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { TraderController } from "@spt/controllers/TraderController"; import { OnLoad } from "@spt/di/OnLoad"; import { OnUpdate } from "@spt/di/OnUpdate"; @@ -6,28 +5,24 @@ import { IEmptyRequestData } from "@spt/models/eft/common/IEmptyRequestData"; import { ITraderAssort, ITraderBase } from "@spt/models/eft/common/tables/ITrader"; import { IGetBodyResponseData } from "@spt/models/eft/httpResponse/IGetBodyResponseData"; import { HttpResponseUtil } from "@spt/utils/HttpResponseUtil"; +import { inject, injectable } from "tsyringe"; @injectable() -export class TraderCallbacks implements OnLoad, OnUpdate -{ +export class TraderCallbacks implements OnLoad, OnUpdate { constructor( @inject("HttpResponseUtil") protected httpResponse: HttpResponseUtil, // TODO: delay required @inject("TraderController") protected traderController: TraderController, - ) - {} + ) {} - public async onLoad(): Promise - { + public async onLoad(): Promise { this.traderController.load(); } - public async onUpdate(): Promise - { + public async onUpdate(): Promise { return this.traderController.update(); } - public getRoute(): string - { + public getRoute(): string { return "spt-traders"; } @@ -36,21 +31,18 @@ export class TraderCallbacks implements OnLoad, OnUpdate url: string, info: IEmptyRequestData, sessionID: string, - ): IGetBodyResponseData - { + ): IGetBodyResponseData { return this.httpResponse.getBody(this.traderController.getAllTraders(sessionID)); } /** Handle client/trading/api/getTrader */ - public getTrader(url: string, info: IEmptyRequestData, sessionID: string): IGetBodyResponseData - { + public getTrader(url: string, info: IEmptyRequestData, sessionID: string): IGetBodyResponseData { const traderID = url.replace("/client/trading/api/getTrader/", ""); return this.httpResponse.getBody(this.traderController.getTrader(sessionID, traderID)); } /** Handle client/trading/api/getTraderAssort */ - public getAssort(url: string, info: IEmptyRequestData, sessionID: string): IGetBodyResponseData - { + public getAssort(url: string, info: IEmptyRequestData, sessionID: string): IGetBodyResponseData { const traderID = url.replace("/client/trading/api/getTraderAssort/", ""); return this.httpResponse.getBody(this.traderController.getAssort(sessionID, traderID)); } diff --git a/project/src/callbacks/WeatherCallbacks.ts b/project/src/callbacks/WeatherCallbacks.ts index 975632ea..d3367989 100644 --- a/project/src/callbacks/WeatherCallbacks.ts +++ b/project/src/callbacks/WeatherCallbacks.ts @@ -1,31 +1,31 @@ -import { inject, injectable } from "tsyringe"; import { WeatherController } from "@spt/controllers/WeatherController"; import { IEmptyRequestData } from "@spt/models/eft/common/IEmptyRequestData"; import { IGetBodyResponseData } from "@spt/models/eft/httpResponse/IGetBodyResponseData"; import { IWeatherData } from "@spt/models/eft/weather/IWeatherData"; -import { HttpResponseUtil } from "@spt/utils/HttpResponseUtil"; import { IGetLocalWeatherResponseData } from "@spt/models/spt/weather/IGetLocalWeatherResponseData"; +import { HttpResponseUtil } from "@spt/utils/HttpResponseUtil"; +import { inject, injectable } from "tsyringe"; @injectable() -export class WeatherCallbacks -{ +export class WeatherCallbacks { constructor( @inject("HttpResponseUtil") protected httpResponse: HttpResponseUtil, @inject("WeatherController") protected weatherController: WeatherController, - ) - {} + ) {} /** * Handle client/weather * @returns IWeatherData */ - public getWeather(url: string, info: IEmptyRequestData, sessionID: string): IGetBodyResponseData - { + public getWeather(url: string, info: IEmptyRequestData, sessionID: string): IGetBodyResponseData { return this.httpResponse.getBody(this.weatherController.generate()); } - public getLocalWeather(url: string, info: IEmptyRequestData, sessionID: string): IGetBodyResponseData - { + public getLocalWeather( + url: string, + info: IEmptyRequestData, + sessionID: string, + ): IGetBodyResponseData { return this.httpResponse.getBody(this.weatherController.generateLocal(sessionID)); } } diff --git a/project/src/callbacks/WishlistCallbacks.ts b/project/src/callbacks/WishlistCallbacks.ts index 7f103231..14c6b2b3 100644 --- a/project/src/callbacks/WishlistCallbacks.ts +++ b/project/src/callbacks/WishlistCallbacks.ts @@ -1,24 +1,21 @@ -import { inject, injectable } from "tsyringe"; import { WishlistController } from "@spt/controllers/WishlistController"; import { IPmcData } from "@spt/models/eft/common/IPmcData"; import { IItemEventRouterResponse } from "@spt/models/eft/itemEvent/IItemEventRouterResponse"; import { IAddToWishlistRequest } from "@spt/models/eft/wishlist/IAddToWishlistRequest"; import { IChangeWishlistItemCategoryRequest } from "@spt/models/eft/wishlist/IChangeWishlistItemCategoryRequest"; import { IRemoveFromWishlistRequest } from "@spt/models/eft/wishlist/IRemoveFromWishlistRequest"; +import { inject, injectable } from "tsyringe"; @injectable() -export class WishlistCallbacks -{ - constructor(@inject("WishlistController") protected wishlistController: WishlistController) - {} +export class WishlistCallbacks { + constructor(@inject("WishlistController") protected wishlistController: WishlistController) {} /** Handle AddToWishList event */ public addToWishlist( pmcData: IPmcData, request: IAddToWishlistRequest, sessionID: string, - ): IItemEventRouterResponse - { + ): IItemEventRouterResponse { return this.wishlistController.addToWishList(pmcData, request, sessionID); } @@ -27,8 +24,7 @@ export class WishlistCallbacks pmcData: IPmcData, request: IRemoveFromWishlistRequest, sessionID: string, - ): IItemEventRouterResponse - { + ): IItemEventRouterResponse { return this.wishlistController.removeFromWishList(pmcData, request, sessionID); } @@ -37,8 +33,7 @@ export class WishlistCallbacks pmcData: IPmcData, request: IChangeWishlistItemCategoryRequest, sessionID: string, - ): IItemEventRouterResponse - { + ): IItemEventRouterResponse { return this.wishlistController.changeWishlistItemCategory(pmcData, request, sessionID); } } diff --git a/project/src/context/ApplicationContext.ts b/project/src/context/ApplicationContext.ts index e0720180..fdb6428a 100644 --- a/project/src/context/ApplicationContext.ts +++ b/project/src/context/ApplicationContext.ts @@ -1,11 +1,10 @@ -import { injectable } from "tsyringe"; import { ContextVariable } from "@spt/context/ContextVariable"; import { ContextVariableType } from "@spt/context/ContextVariableType"; import { LinkedList } from "@spt/utils/collections/lists/LinkedList"; +import { injectable } from "tsyringe"; @injectable() -export class ApplicationContext -{ +export class ApplicationContext { private variables = new Map>(); private static holderMaxSize = 10; @@ -19,23 +18,18 @@ export class ApplicationContext * const matchInfo = this.applicationContext.getLatestValue(ContextVariableType.RAID_CONFIGURATION).getValue(); * ``` */ - public getLatestValue(type: ContextVariableType): ContextVariable | undefined - { - if (this.variables.has(type)) - { + public getLatestValue(type: ContextVariableType): ContextVariable | undefined { + if (this.variables.has(type)) { return this.variables.get(type)?.getTail(); } return undefined; } - public getValues(type: ContextVariableType): ContextVariable[] | undefined - { - if (this.variables.has(type)) - { + public getValues(type: ContextVariableType): ContextVariable[] | undefined { + if (this.variables.has(type)) { const res: ContextVariable[] = []; - for (const value of this.variables.get(type)!.values()) - { + for (const value of this.variables.get(type)!.values()) { res.push(value); } @@ -44,20 +38,15 @@ export class ApplicationContext return undefined; } - public addValue(type: ContextVariableType, value: any): void - { + public addValue(type: ContextVariableType, value: any): void { let list: LinkedList; - if (this.variables.has(type)) - { + if (this.variables.has(type)) { list = this.variables.get(type)!; - } - else - { + } else { list = new LinkedList(); } - if (list.length >= ApplicationContext.holderMaxSize) - { + if (list.length >= ApplicationContext.holderMaxSize) { list.shift(); } @@ -65,10 +54,8 @@ export class ApplicationContext this.variables.set(type, list); } - public clearValues(type: ContextVariableType): void - { - if (this.variables.has(type)) - { + public clearValues(type: ContextVariableType): void { + if (this.variables.has(type)) { this.variables.delete(type); } } diff --git a/project/src/context/ContextVariable.ts b/project/src/context/ContextVariable.ts index 34c92ec7..3f14b7ee 100644 --- a/project/src/context/ContextVariable.ts +++ b/project/src/context/ContextVariable.ts @@ -1,30 +1,25 @@ import { ContextVariableType } from "@spt/context/ContextVariableType"; -export class ContextVariable -{ +export class ContextVariable { private value: any; private timestamp: Date; private type: ContextVariableType; - constructor(value: any, type: ContextVariableType) - { + constructor(value: any, type: ContextVariableType) { this.value = value; this.timestamp = new Date(); this.type = type; } - public getValue(): T - { + public getValue(): T { return this.value; } - public getTimestamp(): Date - { + public getTimestamp(): Date { return this.timestamp; } - public getType(): ContextVariableType - { + public getType(): ContextVariableType { return this.type; } } diff --git a/project/src/context/ContextVariableType.ts b/project/src/context/ContextVariableType.ts index 4632e8c1..e928a5a2 100644 --- a/project/src/context/ContextVariableType.ts +++ b/project/src/context/ContextVariableType.ts @@ -1,5 +1,4 @@ -export enum ContextVariableType -{ +export enum ContextVariableType { /** Logged in users session id */ SESSION_ID = 0, /** Currently acive raid information */ diff --git a/project/src/controllers/AchievementController.ts b/project/src/controllers/AchievementController.ts index eb8e4de8..88e947e7 100644 --- a/project/src/controllers/AchievementController.ts +++ b/project/src/controllers/AchievementController.ts @@ -1,27 +1,24 @@ -import { inject, injectable } from "tsyringe"; import { ICompletedAchievementsResponse } from "@spt/models/eft/profile/ICompletedAchievementsResponse"; import { IGetAchievementsResponse } from "@spt/models/eft/profile/IGetAchievementsResponse"; import { ILogger } from "@spt/models/spt/utils/ILogger"; import { DatabaseService } from "@spt/services/DatabaseService"; +import { inject, injectable } from "tsyringe"; /** * Logic for handling In Raid callbacks */ @injectable() -export class AchievementController -{ +export class AchievementController { constructor( @inject("PrimaryLogger") protected logger: ILogger, @inject("DatabaseService") protected databaseService: DatabaseService, - ) - {} + ) {} /** * Get base achievements * @param sessionID Session id */ - public getAchievements(sessionID: string): IGetAchievementsResponse - { + public getAchievements(sessionID: string): IGetAchievementsResponse { return { elements: this.databaseService.getAchievements() }; } @@ -30,13 +27,11 @@ export class AchievementController * @param sessionId Session id * @returns ICompletedAchievementsResponse */ - public getAchievementStatistics(sessionId: string): ICompletedAchievementsResponse - { + public getAchievementStatistics(sessionId: string): ICompletedAchievementsResponse { const achievements = this.databaseService.getAchievements(); const stats = {}; - for (const achievement of achievements) - { + for (const achievement of achievements) { stats[achievement.id] = 0; } diff --git a/project/src/controllers/BotController.ts b/project/src/controllers/BotController.ts index d82c4935..363cce0e 100644 --- a/project/src/controllers/BotController.ts +++ b/project/src/controllers/BotController.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { ApplicationContext } from "@spt/context/ApplicationContext"; import { ContextVariableType } from "@spt/context/ContextVariableType"; import { BotGenerator } from "@spt/generators/BotGenerator"; @@ -25,12 +24,12 @@ import { DatabaseService } from "@spt/services/DatabaseService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { MatchBotDetailsCacheService } from "@spt/services/MatchBotDetailsCacheService"; import { SeasonalEventService } from "@spt/services/SeasonalEventService"; -import { ICloner } from "@spt/utils/cloners/ICloner"; import { RandomUtil } from "@spt/utils/RandomUtil"; +import { ICloner } from "@spt/utils/cloners/ICloner"; +import { inject, injectable } from "tsyringe"; @injectable() -export class BotController -{ +export class BotController { protected botConfig: IBotConfig; protected pmcConfig: IPmcConfig; @@ -50,8 +49,7 @@ export class BotController @inject("ApplicationContext") protected applicationContext: ApplicationContext, @inject("RandomUtil") protected randomUtil: RandomUtil, @inject("PrimaryCloner") protected cloner: ICloner, - ) - { + ) { this.botConfig = this.configServer.getConfig(ConfigTypes.BOT); this.pmcConfig = this.configServer.getConfig(ConfigTypes.PMC); } @@ -61,12 +59,10 @@ export class BotController * @param type bot Type we want the load-out gen count for * @returns number of bots to generate */ - public getBotPresetGenerationLimit(type: string): number - { + public getBotPresetGenerationLimit(type: string): number { const value = this.botConfig.presetBatch[type === "assaultGroup" ? "assault" : type]; - if (!value) - { + if (!value) { this.logger.warning(this.localisationService.getText("bot-bot_preset_count_value_missing", type)); return 30; @@ -80,8 +76,7 @@ export class BotController * Get the core.json difficulty settings from database/bots * @returns IBotCore */ - public getBotCoreDifficulty(): IBotCore - { + public getBotCoreDifficulty(): IBotCore { return this.databaseService.getBots().core; } @@ -93,15 +88,13 @@ export class BotController * @param ignoreRaidSettings should raid settings chosen pre-raid be ignored * @returns Difficulty object */ - public getBotDifficulty(type: string, diffLevel: string, ignoreRaidSettings = false): Difficulty - { + public getBotDifficulty(type: string, diffLevel: string, ignoreRaidSettings = false): Difficulty { let difficulty = diffLevel.toLowerCase(); const raidConfig = this.applicationContext .getLatestValue(ContextVariableType.RAID_CONFIGURATION) ?.getValue(); - if (!(raidConfig || ignoreRaidSettings)) - { + if (!(raidConfig || ignoreRaidSettings)) { this.logger.error( this.localisationService.getText("bot-missing_application_context", "RAID_CONFIGURATION"), ); @@ -110,16 +103,14 @@ export class BotController // Check value chosen in pre-raid difficulty dropdown // If value is not 'asonline', change requested difficulty to be what was chosen in dropdown const botDifficultyDropDownValue = raidConfig?.wavesSettings.botDifficulty.toLowerCase() ?? "asonline"; - if (botDifficultyDropDownValue !== "asonline") - { - difficulty - = this.botDifficultyHelper.convertBotDifficultyDropdownToBotDifficulty(botDifficultyDropDownValue); + if (botDifficultyDropDownValue !== "asonline") { + difficulty = + this.botDifficultyHelper.convertBotDifficultyDropdownToBotDifficulty(botDifficultyDropDownValue); } let difficultySettings: Difficulty; const lowercasedBotType = type.toLowerCase(); - switch (lowercasedBotType) - { + switch (lowercasedBotType) { case this.pmcConfig.bearType.toLowerCase(): difficultySettings = this.botDifficultyHelper.getPmcDifficultySettings( "bear", @@ -144,14 +135,12 @@ export class BotController return difficultySettings; } - public getAllBotDifficulties(): Record - { + public getAllBotDifficulties(): Record { const result = {}; const botTypesDb = this.databaseService.getBots().types; const botTypes = Object.keys(WildSpawnTypeNumber).filter((v) => Number.isNaN(Number(v))); - for (let botType of botTypes) - { + for (let botType of botTypes) { const enumType = botType.toLowerCase(); // pmcBEAR/pmcUSEC need to be converted into `usec`/`bear` so we can read difficulty settings from bots/types botType = this.botHelper.isBotPmc(botType) @@ -159,15 +148,13 @@ export class BotController : botType.toLowerCase(); const botDetails = botTypesDb[botType]; - if (!botDetails?.difficulty) - { + if (!botDetails?.difficulty) { continue; } const botDifficulties = Object.keys(botDetails.difficulty); result[enumType] = {}; - for (const difficulty of botDifficulties) - { + for (const difficulty of botDifficulties) { result[enumType][difficulty] = this.getBotDifficulty(enumType, difficulty, true); } } @@ -181,14 +168,12 @@ export class BotController * @param info bot generation request info * @returns IBotBase array */ - public async generate(sessionId: string, info: IGenerateBotsRequestData): Promise - { + public async generate(sessionId: string, info: IGenerateBotsRequestData): Promise { const pmcProfile = this.profileHelper.getPmcProfile(sessionId); // Use this opportunity to create and cache bots for later retreval const multipleBotTypesRequested = info.conditions.length > 1; - if (multipleBotTypesRequested) - { + if (multipleBotTypesRequested) { return this.generateMultipleBotsAndCache(info, pmcProfile, sessionId); } @@ -206,26 +191,23 @@ export class BotController request: IGenerateBotsRequestData, pmcProfile: IPmcData, sessionId: string, - ): Promise - { + ): Promise { const raidSettings = this.applicationContext .getLatestValue(ContextVariableType.RAID_CONFIGURATION) ?.getValue(); - if (raidSettings === undefined) - { + if (raidSettings === undefined) { // throw new Error(this.localisationService.getText("bot-unable_to_load_raid_settings_from_appcontext")); } - const pmcLevelRangeForMap - = this.pmcConfig.locationSpecificPmcLevelOverride[raidSettings?.location.toLowerCase()]; + const pmcLevelRangeForMap = + this.pmcConfig.locationSpecificPmcLevelOverride[raidSettings?.location.toLowerCase()]; const allPmcsHaveSameNameAsPlayer = this.randomUtil.getChance100( this.pmcConfig.allPMCsHavePlayerNameWithRandomPrefixChance, ); const conditionPromises: Promise[] = []; - for (const condition of request.conditions) - { + for (const condition of request.conditions) { const botGenerationDetails = this.getBotGenerationDetailsForWave( condition, pmcProfile, @@ -260,8 +242,7 @@ export class BotController pmcLevelRangeForMap: MinMax, botCountToGenerate: number, generateAsPmc: boolean, - ): BotGenerationDetails - { + ): BotGenerationDetails { return { isPmc: generateAsPmc, side: "Savage", @@ -283,8 +264,7 @@ export class BotController * @param pmcProfile Profile to get level from * @returns Level as number */ - protected getPlayerLevelFromProfile(pmcProfile: IPmcData): number - { + protected getPlayerLevelFromProfile(pmcProfile: IPmcData): number { return pmcProfile.Info.Level; } @@ -299,11 +279,9 @@ export class BotController condition: Condition, botGenerationDetails: BotGenerationDetails, sessionId: string, - ): Promise - { + ): Promise { const isEventBot = condition.Role.toLowerCase().includes("event"); - if (isEventBot) - { + if (isEventBot) { // Add eventRole data + reassign role property to be base type botGenerationDetails.eventRole = condition.Role; botGenerationDetails.role = this.seasonalEventService.getBaseRoleForEventBot( @@ -313,8 +291,7 @@ export class BotController // Custom map waves can have spt roles in them // Is bot type pmcUSEC/pmcBEAR, set is pmc true and set side - if (this.botHelper.botRoleIsPmc(condition.Role)) - { + if (this.botHelper.botRoleIsPmc(condition.Role)) { botGenerationDetails.isPmc = true; botGenerationDetails.side = this.botHelper.getPmcSideByRole(condition.Role); } @@ -328,20 +305,17 @@ export class BotController // Get number of bots we have in cache const botCacheCount = this.botGenerationCacheService.getCachedBotCount(cacheKey); const botPromises: Promise[] = []; - if (botCacheCount > botGenerationDetails.botCountToGenerate) - { + if (botCacheCount > botGenerationDetails.botCountToGenerate) { return; } // We're below desired count, add bots to cache - for (let i = 0; i < botGenerationDetails.botCountToGenerate; i++) - { + for (let i = 0; i < botGenerationDetails.botCountToGenerate; i++) { const detailsClone = this.cloner.clone(botGenerationDetails); botPromises.push(this.generateSingleBotAndStoreInCache(detailsClone, sessionId, cacheKey)); } - return Promise.all(botPromises).then(() => - { + return Promise.all(botPromises).then(() => { this.logger.debug( `Generated ${botGenerationDetails.botCountToGenerate} ${botGenerationDetails.role} (${ botGenerationDetails.eventRole ?? "" @@ -361,8 +335,7 @@ export class BotController botGenerationDetails: BotGenerationDetails, sessionId: string, cacheKey: string, - ): Promise - { + ): Promise { const botToCache = this.botGenerator.prepareAndGenerateBot(sessionId, botGenerationDetails); this.botGenerationCacheService.storeBots(cacheKey, [botToCache]); @@ -379,8 +352,7 @@ export class BotController protected async returnSingleBotFromCache( sessionId: string, request: IGenerateBotsRequestData, - ): Promise - { + ): Promise { const pmcProfile = this.profileHelper.getPmcProfile(sessionId); const requestedBot = request.conditions[0]; @@ -388,12 +360,11 @@ export class BotController .getLatestValue(ContextVariableType.RAID_CONFIGURATION) ?.getValue(); - if (raidSettings === undefined) - { + if (raidSettings === undefined) { throw new Error(this.localisationService.getText("bot-unable_to_load_raid_settings_from_appcontext")); } - const pmcLevelRangeForMap - = this.pmcConfig.locationSpecificPmcLevelOverride[raidSettings.location.toLowerCase()]; + const pmcLevelRangeForMap = + this.pmcConfig.locationSpecificPmcLevelOverride[raidSettings.location.toLowerCase()]; // Create gen request for when cache is empty const condition: Condition = { @@ -412,8 +383,7 @@ export class BotController // Event bots need special actions to occur, set data up for them const isEventBot = requestedBot.Role.toLowerCase().includes("event"); - if (isEventBot) - { + if (isEventBot) { // Add eventRole data + reassign role property botGenerationDetails.eventRole = requestedBot.Role; botGenerationDetails.role = this.seasonalEventService.getBaseRoleForEventBot( @@ -421,20 +391,17 @@ export class BotController ); } - if (this.botHelper.isBotPmc(botGenerationDetails.role)) - { + if (this.botHelper.isBotPmc(botGenerationDetails.role)) { botGenerationDetails.isPmc = true; botGenerationDetails.side = this.botHelper.getPmcSideByRole(requestedBot.Role); } // Roll chance to be pmc if type is allowed to be one const botConvertRateMinMax = this.pmcConfig.convertIntoPmcChance[requestedBot.Role.toLowerCase()]; - if (botConvertRateMinMax) - { + if (botConvertRateMinMax) { // Should bot become PMC const convertToPmc = this.botHelper.rollChanceToBePmc(requestedBot.Role, botConvertRateMinMax); - if (convertToPmc) - { + if (convertToPmc) { botGenerationDetails.isPmc = true; botGenerationDetails.role = this.botHelper.getRandomizedPmcRole(); botGenerationDetails.side = this.botHelper.getPmcSideByRole(botGenerationDetails.role); @@ -443,22 +410,16 @@ export class BotController } } // Only convert to boss when not already converted to PMC & Boss Convert is enabled - const { - bossConvertEnabled, - bossConvertMinMax, - bossesToConvertToWeights } = this.botConfig.assaultToBossConversion; - if (bossConvertEnabled && !botGenerationDetails.isPmc) - { + const { bossConvertEnabled, bossConvertMinMax, bossesToConvertToWeights } = + this.botConfig.assaultToBossConversion; + if (bossConvertEnabled && !botGenerationDetails.isPmc) { const bossConvertPercent = bossConvertMinMax[requestedBot.Role.toLowerCase()]; - if (bossConvertPercent) - { + if (bossConvertPercent) { // Roll a percentage check if we should convert scav to boss - if (this.randomUtil.getChance100( - this.randomUtil.getInt(bossConvertPercent.min, bossConvertPercent.max))) - { - this.updateBotGenerationDetailsToRandomBoss( - botGenerationDetails, - bossesToConvertToWeights); + if ( + this.randomUtil.getChance100(this.randomUtil.getInt(bossConvertPercent.min, bossConvertPercent.max)) + ) { + this.updateBotGenerationDetailsToRandomBoss(botGenerationDetails, bossesToConvertToWeights); } } } @@ -466,20 +427,18 @@ export class BotController // Create a compound key to store bots in cache against const cacheKey = this.botGenerationCacheService.createCacheKey( botGenerationDetails.eventRole ?? botGenerationDetails.role, - botGenerationDetails.botDifficulty); + botGenerationDetails.botDifficulty, + ); // Check cache for bot using above key - if (!this.botGenerationCacheService.cacheHasBotOfRole(cacheKey)) - { + if (!this.botGenerationCacheService.cacheHasBotOfRole(cacheKey)) { const botPromises: Promise[] = []; // No bot in cache, generate new and return one - for (let i = 0; i < botGenerationDetails.botCountToGenerate; i++) - { + for (let i = 0; i < botGenerationDetails.botCountToGenerate; i++) { botPromises.push(this.generateSingleBotAndStoreInCache(botGenerationDetails, sessionId, cacheKey)); } - await Promise.all(botPromises).then(() => - { + await Promise.all(botPromises).then(() => { this.logger.debug( `Generated ${botGenerationDetails.botCountToGenerate} ${botGenerationDetails.role} (${ botGenerationDetails.eventRole ?? "" @@ -496,11 +455,10 @@ export class BotController protected updateBotGenerationDetailsToRandomBoss( botGenerationDetails: BotGenerationDetails, - possibleBossTypeWeights: Record): void - { + possibleBossTypeWeights: Record, + ): void { // Seems Actual bosses have the same Brain issues like PMC gaining Boss Brains We cant use all bosses - botGenerationDetails.role - = this.weightedRandomHelper.getWeightedValue(possibleBossTypeWeights); + botGenerationDetails.role = this.weightedRandomHelper.getWeightedValue(possibleBossTypeWeights); // Bosses are only ever 'normal' botGenerationDetails.botDifficulty = "normal"; @@ -512,16 +470,13 @@ export class BotController * @param requestedDifficulty * @returns */ - public getPMCDifficulty(requestedDifficulty: string): string - { + public getPMCDifficulty(requestedDifficulty: string): string { // Maybe return a random difficulty... - if (this.pmcConfig.difficulty.toLowerCase() === "asonline") - { + if (this.pmcConfig.difficulty.toLowerCase() === "asonline") { return requestedDifficulty; } - if (this.pmcConfig.difficulty.toLowerCase() === "random") - { + if (this.pmcConfig.difficulty.toLowerCase() === "random") { return this.botDifficultyHelper.chooseRandomDifficulty(); } @@ -534,24 +489,18 @@ export class BotController * @param location The map location cap was requested for * @returns cap number */ - public getBotCap(location: string): number - { + public getBotCap(location: string): number { const botCap = this.botConfig.maxBotCap[location.toLowerCase()]; - if (location === "default") - { + if (location === "default") { this.logger.warning( - this.localisationService.getText( - "bot-no_bot_cap_found_for_location", - location.toLowerCase(), - ), + this.localisationService.getText("bot-no_bot_cap_found_for_location", location.toLowerCase()), ); } return botCap; } - public getAiBotBrainTypes(): any - { + public getAiBotBrainTypes(): any { return { pmc: this.pmcConfig.pmcType, assault: this.botConfig.assaultBrainType, diff --git a/project/src/controllers/BuildController.ts b/project/src/controllers/BuildController.ts index bfff1ed5..f5bcac13 100644 --- a/project/src/controllers/BuildController.ts +++ b/project/src/controllers/BuildController.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { ItemHelper } from "@spt/helpers/ItemHelper"; import { ProfileHelper } from "@spt/helpers/ProfileHelper"; import { ISetMagazineRequest } from "@spt/models/eft/builds/ISetMagazineRequest"; @@ -11,12 +10,12 @@ import { EventOutputHolder } from "@spt/routers/EventOutputHolder"; import { SaveServer } from "@spt/servers/SaveServer"; 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 { ICloner } from "@spt/utils/cloners/ICloner"; +import { inject, injectable } from "tsyringe"; @injectable() -export class BuildController -{ +export class BuildController { constructor( @inject("PrimaryLogger") protected logger: ILogger, @inject("HashUtil") protected hashUtil: HashUtil, @@ -27,16 +26,13 @@ export class BuildController @inject("ItemHelper") protected itemHelper: ItemHelper, @inject("SaveServer") protected saveServer: SaveServer, @inject("PrimaryCloner") protected cloner: ICloner, - ) - {} + ) {} /** Handle client/handbook/builds/my/list */ - public getUserBuilds(sessionID: string): IUserBuilds - { + public getUserBuilds(sessionID: string): IUserBuilds { const secureContainerSlotId = "SecuredContainer"; const profile = this.saveServer.getProfile(sessionID); - if (!profile.userbuilds) - { + if (!profile.userbuilds) { profile.userbuilds = { equipmentBuilds: [], weaponBuilds: [], magazineBuilds: [] }; } @@ -50,15 +46,12 @@ export class BuildController const firstDefaultItemsSecureContainer = defaultEquipmentPresetsClone[0]?.Items?.find( (x) => x.slotId === secureContainerSlotId, ); - if (playerSecureContainer && playerSecureContainer?._tpl !== firstDefaultItemsSecureContainer?._tpl) - { + if (playerSecureContainer && playerSecureContainer?._tpl !== firstDefaultItemsSecureContainer?._tpl) { // Default equipment presets' secure container tpl doesn't match players secure container tpl - for (const defaultPreset of defaultEquipmentPresetsClone) - { + for (const defaultPreset of defaultEquipmentPresetsClone) { // Find presets secure container const secureContainer = defaultPreset.Items.find((item) => item.slotId === secureContainerSlotId); - if (secureContainer) - { + if (secureContainer) { secureContainer._tpl = playerSecureContainer._tpl; } } @@ -72,8 +65,7 @@ export class BuildController } /** Handle client/builds/weapon/save */ - public saveWeaponBuild(sessionId: string, body: IPresetBuildActionRequestData): void - { + public saveWeaponBuild(sessionId: string, body: IPresetBuildActionRequestData): void { const pmcData = this.profileHelper.getPmcProfile(sessionId); // Replace duplicate Id's. The first item is the base item. @@ -86,28 +78,24 @@ export class BuildController const savedWeaponBuilds = this.saveServer.getProfile(sessionId).userbuilds.weaponBuilds; const existingBuild = savedWeaponBuilds.find((x) => x.Id === body.Id); - if (existingBuild) - { + if (existingBuild) { // exists, replace this.saveServer .getProfile(sessionId) .userbuilds.weaponBuilds.splice(savedWeaponBuilds.indexOf(existingBuild), 1, newBuild); - } - else - { + } else { // Add fresh this.saveServer.getProfile(sessionId).userbuilds.weaponBuilds.push(newBuild); } } /** Handle client/builds/equipment/save event */ - public saveEquipmentBuild(sessionID: string, request: IPresetBuildActionRequestData): void - { + public saveEquipmentBuild(sessionID: string, request: IPresetBuildActionRequestData): void { const buildType = "equipmentBuilds"; const pmcData = this.profileHelper.getPmcProfile(sessionID); - const existingSavedEquipmentBuilds: IEquipmentBuild[] - = this.saveServer.getProfile(sessionID).userbuilds[buildType]; + const existingSavedEquipmentBuilds: IEquipmentBuild[] = + this.saveServer.getProfile(sessionID).userbuilds[buildType]; // Replace duplicate ID's. The first item is the base item. // Root ID and the base item ID need to match. @@ -124,28 +112,23 @@ export class BuildController const existingBuild = existingSavedEquipmentBuilds.find( (build) => build.Name === request.Name || build.Id === request.Id, ); - if (existingBuild) - { + if (existingBuild) { // Already exists, replace this.saveServer .getProfile(sessionID) .userbuilds[buildType].splice(existingSavedEquipmentBuilds.indexOf(existingBuild), 1, newBuild); - } - else - { + } else { // Fresh, add new this.saveServer.getProfile(sessionID).userbuilds[buildType].push(newBuild); } } /** Handle client/builds/delete */ - public removeBuild(sessionID: string, request: IRemoveBuildRequestData): void - { + public removeBuild(sessionID: string, request: IRemoveBuildRequestData): void { this.removePlayerBuild(request.id, sessionID); } - protected removePlayerBuild(idToRemove: string, sessionID: string): void - { + protected removePlayerBuild(idToRemove: string, sessionID: string): void { const profile = this.saveServer.getProfile(sessionID); const weaponBuilds = profile.userbuilds.weaponBuilds; const equipmentBuilds = profile.userbuilds.equipmentBuilds; @@ -153,8 +136,7 @@ export class BuildController // Check for id in weapon array first const matchingWeaponBuild = weaponBuilds.find((weaponBuild) => weaponBuild.Id === idToRemove); - if (matchingWeaponBuild) - { + if (matchingWeaponBuild) { weaponBuilds.splice(weaponBuilds.indexOf(matchingWeaponBuild), 1); return; @@ -162,8 +144,7 @@ export class BuildController // Id not found in weapons, try equipment const matchingEquipmentBuild = equipmentBuilds.find((equipmentBuild) => equipmentBuild.Id === idToRemove); - if (matchingEquipmentBuild) - { + if (matchingEquipmentBuild) { equipmentBuilds.splice(equipmentBuilds.indexOf(matchingEquipmentBuild), 1); return; @@ -171,8 +152,7 @@ export class BuildController // Id not found in weapons/equipment, try mags const matchingMagazineBuild = magazineBuilds.find((magBuild) => magBuild.Id === idToRemove); - if (matchingMagazineBuild) - { + if (matchingMagazineBuild) { magazineBuilds.splice(magazineBuilds.indexOf(matchingMagazineBuild), 1); return; @@ -185,8 +165,7 @@ export class BuildController /** * Handle client/builds/magazine/save */ - public createMagazineTemplate(sessionId: string, request: ISetMagazineRequest): void - { + public createMagazineTemplate(sessionId: string, request: ISetMagazineRequest): void { const result: IMagazineBuild = { Id: request.Id, Name: request.Name, @@ -201,12 +180,9 @@ export class BuildController profile.userbuilds.magazineBuilds ||= []; const existingArrayId = profile.userbuilds.magazineBuilds.findIndex((item) => item.Name === request.Name); - if (existingArrayId === -1) - { + if (existingArrayId === -1) { profile.userbuilds.magazineBuilds.push(result); - } - else - { + } else { profile.userbuilds.magazineBuilds.splice(existingArrayId, 1, result); } } diff --git a/project/src/controllers/ClientLogController.ts b/project/src/controllers/ClientLogController.ts index f00b5c51..e5127e57 100644 --- a/project/src/controllers/ClientLogController.ts +++ b/project/src/controllers/ClientLogController.ts @@ -1,21 +1,18 @@ -import { inject, injectable } from "tsyringe"; import { IClientLogRequest } from "@spt/models/spt/logging/IClientLogRequest"; import { LogBackgroundColor } from "@spt/models/spt/logging/LogBackgroundColor"; import { LogLevel } from "@spt/models/spt/logging/LogLevel"; import { LogTextColor } from "@spt/models/spt/logging/LogTextColor"; import { ILogger } from "@spt/models/spt/utils/ILogger"; +import { inject, injectable } from "tsyringe"; @injectable() -export class ClientLogController -{ - constructor(@inject("PrimaryLogger") protected logger: ILogger) - {} +export class ClientLogController { + constructor(@inject("PrimaryLogger") protected logger: ILogger) {} /** * Handle /singleplayer/log */ - public clientLog(logRequest: IClientLogRequest): void - { + public clientLog(logRequest: IClientLogRequest): void { const message = `[${logRequest.Source}] ${logRequest.Message}`; const color = logRequest.Color ?? LogTextColor.WHITE; const backgroundColor = logRequest.BackgroundColor ?? LogBackgroundColor.DEFAULT; @@ -23,13 +20,11 @@ export class ClientLogController // Allow supporting either string or enum levels // Required due to the C# modules serializing enums as their name let level = logRequest.Level; - if (typeof level === "string") - { + if (typeof level === "string") { level = LogLevel[level.toUpperCase() as keyof typeof LogLevel]; } - switch (level) - { + switch (level) { case LogLevel.ERROR: this.logger.error(message); break; diff --git a/project/src/controllers/CustomizationController.ts b/project/src/controllers/CustomizationController.ts index 0f7b49b0..a8e91c55 100644 --- a/project/src/controllers/CustomizationController.ts +++ b/project/src/controllers/CustomizationController.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { ProfileHelper } from "@spt/helpers/ProfileHelper"; import { IPmcData } from "@spt/models/eft/common/IPmcData"; import { ISuit } from "@spt/models/eft/common/tables/ITrader"; @@ -10,10 +9,10 @@ import { EventOutputHolder } from "@spt/routers/EventOutputHolder"; import { SaveServer } from "@spt/servers/SaveServer"; import { DatabaseService } from "@spt/services/DatabaseService"; import { LocalisationService } from "@spt/services/LocalisationService"; +import { inject, injectable } from "tsyringe"; @injectable() -export class CustomizationController -{ +export class CustomizationController { protected readonly clothingIds = { lowerParentId: "5cd944d01388ce000a659df9", upperParentId: "5cd944ca1388ce03a44dc2a4", @@ -26,8 +25,7 @@ export class CustomizationController @inject("SaveServer") protected saveServer: SaveServer, @inject("LocalisationService") protected localisationService: LocalisationService, @inject("ProfileHelper") protected profileHelper: ProfileHelper, - ) - {} + ) {} /** * Get purchasable clothing items from trader that match players side (usec/bear) @@ -35,8 +33,7 @@ export class CustomizationController * @param sessionID Session id * @returns ISuit array */ - public getTraderSuits(traderID: string, sessionID: string): ISuit[] - { + public getTraderSuits(traderID: string, sessionID: string): ISuit[] { const pmcData = this.profileHelper.getPmcProfile(sessionID); const clothing = this.databaseService.getCustomization(); const suits = this.databaseService.getTrader(traderID).suits; @@ -45,7 +42,9 @@ export class CustomizationController const matchingSuits = suits?.filter((suit) => suit.suiteId in clothing); // Return all suits that have a side array containing the players side (usec/bear) - const matchedSuits = matchingSuits?.filter((matchingSuit) => clothing[matchingSuit.suiteId]._props.Side.includes(pmcData.Info.Side)); + const matchedSuits = matchingSuits?.filter((matchingSuit) => + clothing[matchingSuit.suiteId]._props.Side.includes(pmcData.Info.Side), + ); if (matchingSuits === undefined) throw new Error(this.localisationService.getText("customisation-unable_to_get_trader_suits", traderID)); @@ -60,22 +59,18 @@ export class CustomizationController pmcData: IPmcData, wearClothingRequest: IWearClothingRequestData, sessionID: string, - ): IItemEventRouterResponse - { - for (const suitId of wearClothingRequest.suites) - { + ): IItemEventRouterResponse { + for (const suitId of wearClothingRequest.suites) { // Find desired clothing item in db const dbSuit = this.databaseService.getCustomization()[suitId]; // Legs - if (dbSuit._parent === this.clothingIds.lowerParentId) - { + if (dbSuit._parent === this.clothingIds.lowerParentId) { pmcData.Customization.Feet = dbSuit._props.Feet; } // Torso - if (dbSuit._parent === this.clothingIds.upperParentId) - { + if (dbSuit._parent === this.clothingIds.upperParentId) { pmcData.Customization.Body = dbSuit._props.Body; pmcData.Customization.Hands = dbSuit._props.Hands; } @@ -96,13 +91,11 @@ export class CustomizationController pmcData: IPmcData, buyClothingRequest: IBuyClothingRequestData, sessionId: string, - ): IItemEventRouterResponse - { + ): IItemEventRouterResponse { const output = this.eventOutputHolder.getOutput(sessionId); const traderOffer = this.getTraderClothingOffer(sessionId, buyClothingRequest.offer); - if (!traderOffer) - { + if (!traderOffer) { this.logger.error( this.localisationService.getText("customisation-unable_to_find_suit_by_id", buyClothingRequest.offer), ); @@ -111,8 +104,7 @@ export class CustomizationController } const suitId = traderOffer.suiteId; - if (this.outfitAlreadyPurchased(suitId, sessionId)) - { + if (this.outfitAlreadyPurchased(suitId, sessionId)) { const suitDetails = this.databaseService.getCustomization()[suitId]; this.logger.error( this.localisationService.getText("customisation-item_already_purchased", { @@ -133,11 +125,9 @@ export class CustomizationController return output; } - protected getTraderClothingOffer(sessionId: string, offerId: string): ISuit - { + protected getTraderClothingOffer(sessionId: string, offerId: string): ISuit { const foundSuit = this.getAllTraderSuits(sessionId).find((x) => x._id === offerId); - if (foundSuit === undefined) - { + if (foundSuit === undefined) { throw new Error(this.localisationService.getText("customisation-unable_to_find_suit_with_id", offerId)); } @@ -150,8 +140,7 @@ export class CustomizationController * @param sessionID Session id of profile to check for clothing in * @returns true if already purchased */ - protected outfitAlreadyPurchased(suitId: string, sessionID: string): boolean - { + protected outfitAlreadyPurchased(suitId: string, sessionID: string): boolean { return this.saveServer.getProfile(sessionID).suits.includes(suitId); } @@ -167,10 +156,8 @@ export class CustomizationController pmcData: IPmcData, clothingItems: ClothingItem[], output: IItemEventRouterResponse, - ): void - { - for (const sellItem of clothingItems) - { + ): void { + for (const sellItem of clothingItems) { this.payForClothingItem(sessionId, pmcData, sellItem, output); } } @@ -187,11 +174,9 @@ export class CustomizationController pmcData: IPmcData, clothingItem: ClothingItem, output: IItemEventRouterResponse, - ): void - { + ): void { const relatedItem = pmcData.Inventory.items.find((x) => x._id === clothingItem.id); - if (!relatedItem) - { + if (!relatedItem) { this.logger.error( this.localisationService.getText( "customisation-unable_to_find_clothing_item_in_inventory", @@ -202,19 +187,18 @@ export class CustomizationController return; } - if (clothingItem.del === true) - { + if (clothingItem.del === true) { output.profileChanges[sessionId].items.del.push(relatedItem); pmcData.Inventory.items.splice(pmcData.Inventory.items.indexOf(relatedItem), 1); } - if (!relatedItem.upd || !relatedItem.upd.StackObjectsCount) - { - throw new Error(this.localisationService.getText("customisation-suit_lacks_upd_or_stack_property", relatedItem._tpl)); + if (!relatedItem.upd || !relatedItem.upd.StackObjectsCount) { + throw new Error( + this.localisationService.getText("customisation-suit_lacks_upd_or_stack_property", relatedItem._tpl), + ); } - if (relatedItem.upd.StackObjectsCount > clothingItem.count) - { + if (relatedItem.upd.StackObjectsCount > clothingItem.count) { relatedItem.upd.StackObjectsCount -= clothingItem.count; output.profileChanges[sessionId].items.change.push({ _id: relatedItem._id, @@ -227,15 +211,12 @@ export class CustomizationController } } - protected getAllTraderSuits(sessionID: string): ISuit[] - { + protected getAllTraderSuits(sessionID: string): ISuit[] { const traders = this.databaseService.getTraders(); let result: ISuit[] = []; - for (const traderID in traders) - { - if (traders[traderID].base.customization_seller === true) - { + for (const traderID in traders) { + if (traders[traderID].base.customization_seller === true) { result = [...result, ...this.getTraderSuits(traderID, sessionID)]; } } diff --git a/project/src/controllers/DialogueController.ts b/project/src/controllers/DialogueController.ts index e5e5f88c..341a0d52 100644 --- a/project/src/controllers/DialogueController.ts +++ b/project/src/controllers/DialogueController.ts @@ -1,4 +1,3 @@ -import { inject, injectAll, injectable } from "tsyringe"; import { IDialogueChatBot } from "@spt/helpers/Dialogue/IDialogueChatBot"; import { DialogueHelper } from "@spt/helpers/DialogueHelper"; import { IFriendRequestData } from "@spt/models/eft/dialog/IFriendRequestData"; @@ -18,10 +17,10 @@ import { SaveServer } from "@spt/servers/SaveServer"; import { LocalisationService } from "@spt/services/LocalisationService"; import { MailSendService } from "@spt/services/MailSendService"; import { TimeUtil } from "@spt/utils/TimeUtil"; +import { inject, injectAll, injectable } from "tsyringe"; @injectable() -export class DialogueController -{ +export class DialogueController { constructor( @inject("PrimaryLogger") protected logger: ILogger, @inject("SaveServer") protected saveServer: SaveServer, @@ -31,37 +30,36 @@ export class DialogueController @inject("LocalisationService") protected localisationService: LocalisationService, @inject("ConfigServer") protected configServer: ConfigServer, @injectAll("DialogueChatBot") protected dialogueChatBots: IDialogueChatBot[], - ) - { + ) { const coreConfigs = this.configServer.getConfig(ConfigTypes.CORE); // if give command is disabled or commando commands are disabled - if (!coreConfigs.features?.chatbotFeatures?.commandoEnabled) - { - const sptCommando = this.dialogueChatBots.find((c) => c.getChatBot()._id.toLocaleLowerCase() === "sptcommando")!; + if (!coreConfigs.features?.chatbotFeatures?.commandoEnabled) { + const sptCommando = this.dialogueChatBots.find( + (c) => c.getChatBot()._id.toLocaleLowerCase() === "sptcommando", + )!; this.dialogueChatBots.splice(this.dialogueChatBots.indexOf(sptCommando), 1); } - if (!coreConfigs.features?.chatbotFeatures?.sptFriendEnabled) - { - const sptFriend = this.dialogueChatBots.find((c) => c.getChatBot()._id.toLocaleLowerCase() === "sptFriend")!; + if (!coreConfigs.features?.chatbotFeatures?.sptFriendEnabled) { + const sptFriend = this.dialogueChatBots.find( + (c) => c.getChatBot()._id.toLocaleLowerCase() === "sptFriend", + )!; this.dialogueChatBots.splice(this.dialogueChatBots.indexOf(sptFriend), 1); } } - public registerChatBot(chatBot: IDialogueChatBot): void - { - if (this.dialogueChatBots.some((cb) => cb.getChatBot()._id === chatBot.getChatBot()._id)) - { - throw new Error(this.localisationService.getText("dialog-chatbot_id_already_exists", chatBot.getChatBot()._id)); + public registerChatBot(chatBot: IDialogueChatBot): void { + if (this.dialogueChatBots.some((cb) => cb.getChatBot()._id === chatBot.getChatBot()._id)) { + throw new Error( + this.localisationService.getText("dialog-chatbot_id_already_exists", chatBot.getChatBot()._id), + ); } this.dialogueChatBots.push(chatBot); } /** Handle onUpdate spt event */ - public update(): void - { + public update(): void { const profiles = this.saveServer.getProfiles(); - for (const sessionID in profiles) - { + for (const sessionID in profiles) { this.removeExpiredItemsFromMessages(sessionID); } } @@ -70,8 +68,7 @@ export class DialogueController * Handle client/friend/list * @returns IGetFriendListDataResponse */ - public getFriendList(sessionID: string): IGetFriendListDataResponse - { + public getFriendList(sessionID: string): IGetFriendListDataResponse { // Force a fake friend called SPT into friend list return { Friends: this.dialogueChatBots.map((v) => v.getChatBot()), Ignore: [], InIgnoreList: [] }; } @@ -83,11 +80,9 @@ export class DialogueController * @param sessionID Session Id * @returns array of dialogs */ - public generateDialogueList(sessionID: string): DialogueInfo[] - { + public generateDialogueList(sessionID: string): DialogueInfo[] { const data: DialogueInfo[] = []; - for (const dialogueId in this.dialogueHelper.getDialogsForProfile(sessionID)) - { + for (const dialogueId in this.dialogueHelper.getDialogsForProfile(sessionID)) { data.push(this.getDialogueInfo(dialogueId, sessionID)); } @@ -100,8 +95,7 @@ export class DialogueController * @param sessionID Session Id * @returns DialogueInfo */ - public getDialogueInfo(dialogueID: string, sessionID: string): DialogueInfo - { + public getDialogueInfo(dialogueID: string, sessionID: string): DialogueInfo { const dialogs = this.dialogueHelper.getDialogsForProfile(sessionID); const dialogue = dialogs[dialogueID]; @@ -125,18 +119,19 @@ export class DialogueController * @param sessionID Player id * @returns IUserDialogInfo array */ - public getDialogueUsers(dialog: Dialogue, messageType: MessageType, sessionID: string): IUserDialogInfo[] | undefined - { + public getDialogueUsers( + dialog: Dialogue, + messageType: MessageType, + sessionID: string, + ): IUserDialogInfo[] | undefined { const profile = this.saveServer.getProfile(sessionID); // User to user messages are special in that they need the player to exist in them, add if they don't if ( - messageType === MessageType.USER_MESSAGE - && !dialog.Users?.some((userDialog) => userDialog._id === profile.characters.pmc.sessionId) - ) - { - if (!dialog.Users) - { + messageType === MessageType.USER_MESSAGE && + !dialog.Users?.some((userDialog) => userDialog._id === profile.characters.pmc.sessionId) + ) { + if (!dialog.Users) { dialog.Users = []; } @@ -168,8 +163,7 @@ export class DialogueController public generateDialogueView( request: IGetMailDialogViewRequestData, sessionId: string, - ): IGetMailDialogViewResponseData - { + ): IGetMailDialogViewResponseData { const dialogueId = request.dialogId; const fullProfile = this.saveServer.getProfile(sessionId); const dialogue = this.getDialogByIdFromProfile(fullProfile, request); @@ -193,10 +187,8 @@ export class DialogueController * @param request get dialog request (params used when dialog doesnt exist in profile) * @returns Dialogue */ - protected getDialogByIdFromProfile(profile: ISptProfile, request: IGetMailDialogViewRequestData): Dialogue - { - if (!profile.dialogues[request.dialogId]) - { + protected getDialogByIdFromProfile(profile: ISptProfile, request: IGetMailDialogViewRequestData): Dialogue { + if (!profile.dialogues[request.dialogId]) { profile.dialogues[request.dialogId] = { _id: request.dialogId, attachmentsNew: 0, @@ -206,14 +198,11 @@ export class DialogueController type: request.type, }; - if (request.type === MessageType.USER_MESSAGE) - { + if (request.type === MessageType.USER_MESSAGE) { profile.dialogues[request.dialogId].Users = []; const chatBot = this.dialogueChatBots.find((cb) => cb.getChatBot()._id === request.dialogId); - if (chatBot) - { - if (!profile.dialogues[request.dialogId].Users) - { + if (chatBot) { + if (!profile.dialogues[request.dialogId].Users) { profile.dialogues[request.dialogId].Users = []; } profile.dialogues[request.dialogId].Users!.push(chatBot.getChatBot()); @@ -230,15 +219,12 @@ export class DialogueController * @param dialogUsers The participants of the mail * @returns IUserDialogInfo array */ - protected getProfilesForMail(fullProfile: ISptProfile, dialogUsers?: IUserDialogInfo[]): IUserDialogInfo[] - { + protected getProfilesForMail(fullProfile: ISptProfile, dialogUsers?: IUserDialogInfo[]): IUserDialogInfo[] { const result: IUserDialogInfo[] = []; - if (dialogUsers) - { + if (dialogUsers) { result.push(...dialogUsers); - if (!result.some((userDialog) => userDialog._id === fullProfile.info.id)) - { + if (!result.some((userDialog) => userDialog._id === fullProfile.info.id)) { // Player doesnt exist, add them in before returning const pmcProfile = fullProfile.characters.pmc; result.push({ @@ -264,14 +250,11 @@ export class DialogueController * @param dialogueID Dialog id * @returns Count of messages with attachments */ - protected getUnreadMessagesWithAttachmentsCount(sessionID: string, dialogueID: string): number - { + protected getUnreadMessagesWithAttachmentsCount(sessionID: string, dialogueID: string): number { let newAttachmentCount = 0; const activeMessages = this.getActiveMessagesFromDialog(sessionID, dialogueID); - for (const message of activeMessages) - { - if (message.hasRewards && !message.rewardCollected) - { + for (const message of activeMessages) { + if (message.hasRewards && !message.rewardCollected) { newAttachmentCount++; } } @@ -284,8 +267,7 @@ export class DialogueController * @param messages Messages to check * @returns true if uncollected rewards found */ - protected messagesHaveUncollectedRewards(messages: Message[]): boolean - { + protected messagesHaveUncollectedRewards(messages: Message[]): boolean { return messages.some((message) => (message.items?.data?.length ?? 0) > 0); } @@ -295,13 +277,16 @@ export class DialogueController * @param dialogueId id of the dialog to remove * @param sessionId Player id */ - public removeDialogue(dialogueId: string, sessionId: string): void - { + public removeDialogue(dialogueId: string, sessionId: string): void { const profile = this.saveServer.getProfile(sessionId); const dialog = profile.dialogues[dialogueId]; - if (!dialog) - { - this.logger.error(this.localisationService.getText("dialogue-unable_to_find_in_profile", { sessionId: sessionId, dialogueId: dialogueId })); + if (!dialog) { + this.logger.error( + this.localisationService.getText("dialogue-unable_to_find_in_profile", { + sessionId: sessionId, + dialogueId: dialogueId, + }), + ); return; } @@ -310,12 +295,15 @@ export class DialogueController } /** Handle client/mail/dialog/pin && Handle client/mail/dialog/unpin */ - public setDialoguePin(dialogueId: string, shouldPin: boolean, sessionId: string): void - { + public setDialoguePin(dialogueId: string, shouldPin: boolean, sessionId: string): void { const dialog = this.dialogueHelper.getDialogsForProfile(sessionId)[dialogueId]; - if (!dialog) - { - this.logger.error(this.localisationService.getText("dialogue-unable_to_find_in_profile", { sessionId: sessionId, dialogueId: dialogueId })); + if (!dialog) { + this.logger.error( + this.localisationService.getText("dialogue-unable_to_find_in_profile", { + sessionId: sessionId, + dialogueId: dialogueId, + }), + ); return; } @@ -329,18 +317,19 @@ export class DialogueController * @param dialogueIds Dialog ids to set as read * @param sessionId Player profile id */ - public setRead(dialogueIds: string[], sessionId: string): void - { + public setRead(dialogueIds: string[], sessionId: string): void { const dialogs = this.dialogueHelper.getDialogsForProfile(sessionId); - if (!dialogs) - { - this.logger.error(this.localisationService.getText("dialogue-unable_to_find_dialogs_in_profile", { sessionId: sessionId })); + if (!dialogs) { + this.logger.error( + this.localisationService.getText("dialogue-unable_to_find_dialogs_in_profile", { + sessionId: sessionId, + }), + ); return; } - for (const dialogId of dialogueIds) - { + for (const dialogId of dialogueIds) { dialogs[dialogId].new = 0; dialogs[dialogId].attachmentsNew = 0; } @@ -353,13 +342,16 @@ export class DialogueController * @param sessionId Session id * @returns IGetAllAttachmentsResponse */ - public getAllAttachments(dialogueId: string, sessionId: string): IGetAllAttachmentsResponse | undefined - { + public getAllAttachments(dialogueId: string, sessionId: string): IGetAllAttachmentsResponse | undefined { const dialogs = this.dialogueHelper.getDialogsForProfile(sessionId); const dialog = dialogs[dialogueId]; - if (!dialog) - { - this.logger.error(this.localisationService.getText("dialogue-unable_to_find_in_profile", { sessionId: sessionId, dialogueId: dialogueId })); + if (!dialog) { + this.logger.error( + this.localisationService.getText("dialogue-unable_to_find_in_profile", { + sessionId: sessionId, + dialogueId: dialogueId, + }), + ); return undefined; } @@ -378,8 +370,7 @@ export class DialogueController } /** client/mail/msg/send */ - public sendMessage(sessionId: string, request: ISendMessageRequest): string - { + public sendMessage(sessionId: string, request: ISendMessageRequest): string { this.mailSendService.sendPlayerMessageToNpc(sessionId, request.dialogId, request.text); return ( @@ -395,8 +386,7 @@ export class DialogueController * @param dialogueId Dialog to get mail attachments from * @returns Message array */ - protected getActiveMessagesFromDialog(sessionId: string, dialogueId: string): Message[] - { + protected getActiveMessagesFromDialog(sessionId: string, dialogueId: string): Message[] { const timeNow = this.timeUtil.getTimestamp(); const dialogs = this.dialogueHelper.getDialogsForProfile(sessionId); return dialogs[dialogueId].messages.filter((message) => timeNow < message.dt + (message.maxStorageTime ?? 0)); @@ -407,8 +397,7 @@ export class DialogueController * @param messages Messages to parse * @returns messages with items to collect */ - protected getMessagesWithAttachments(messages: Message[]): Message[] - { + protected getMessagesWithAttachments(messages: Message[]): Message[] { return messages.filter((message) => (message.items?.data?.length ?? 0) > 0); } @@ -416,10 +405,8 @@ export class DialogueController * Delete expired items from all messages in player profile. triggers when updating traders. * @param sessionId Session id */ - protected removeExpiredItemsFromMessages(sessionId: string): void - { - for (const dialogueId in this.dialogueHelper.getDialogsForProfile(sessionId)) - { + protected removeExpiredItemsFromMessages(sessionId: string): void { + for (const dialogueId in this.dialogueHelper.getDialogsForProfile(sessionId)) { this.removeExpiredItemsFromMessage(sessionId, dialogueId); } } @@ -429,19 +416,15 @@ export class DialogueController * @param sessionId Session id * @param dialogueId Dialog id */ - protected removeExpiredItemsFromMessage(sessionId: string, dialogueId: string): void - { + protected removeExpiredItemsFromMessage(sessionId: string, dialogueId: string): void { const dialogs = this.dialogueHelper.getDialogsForProfile(sessionId); const dialog = dialogs[dialogueId]; - if (!dialog.messages) - { + if (!dialog.messages) { return; } - for (const message of dialog.messages) - { - if (this.messageHasExpired(message)) - { + for (const message of dialog.messages) { + if (this.messageHasExpired(message)) { message.items = {}; } } @@ -452,14 +435,12 @@ export class DialogueController * @param message Message to check expiry of * @returns true or false */ - protected messageHasExpired(message: Message): boolean - { + protected messageHasExpired(message: Message): boolean { return this.timeUtil.getTimestamp() > message.dt + (message.maxStorageTime ?? 0); } /** Handle client/friend/request/send */ - public sendFriendRequest(sessionID: string, request: IFriendRequestData): IFriendRequestSendResponse - { + public sendFriendRequest(sessionID: string, request: IFriendRequestData): IFriendRequestSendResponse { return { status: 0, requestId: "12345", retryAfter: 600 }; } } diff --git a/project/src/controllers/GameController.ts b/project/src/controllers/GameController.ts index aae2ce94..c08ce4e7 100644 --- a/project/src/controllers/GameController.ts +++ b/project/src/controllers/GameController.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { ApplicationContext } from "@spt/context/ApplicationContext"; import { ContextVariableType } from "@spt/context/ContextVariableType"; import { HideoutHelper } from "@spt/helpers/HideoutHelper"; @@ -44,14 +43,14 @@ import { ProfileActivityService } from "@spt/services/ProfileActivityService"; import { ProfileFixerService } from "@spt/services/ProfileFixerService"; import { RaidTimeAdjustmentService } from "@spt/services/RaidTimeAdjustmentService"; import { SeasonalEventService } from "@spt/services/SeasonalEventService"; -import { ICloner } from "@spt/utils/cloners/ICloner"; import { HashUtil } from "@spt/utils/HashUtil"; import { RandomUtil } from "@spt/utils/RandomUtil"; import { TimeUtil } from "@spt/utils/TimeUtil"; +import { ICloner } from "@spt/utils/cloners/ICloner"; +import { inject, injectable } from "tsyringe"; @injectable() -export class GameController -{ +export class GameController { protected httpConfig: IHttpConfig; protected coreConfig: ICoreConfig; protected locationConfig: ILocationConfig; @@ -83,8 +82,7 @@ export class GameController @inject("ApplicationContext") protected applicationContext: ApplicationContext, @inject("ConfigServer") protected configServer: ConfigServer, @inject("PrimaryCloner") protected cloner: ICloner, - ) - { + ) { this.httpConfig = this.configServer.getConfig(ConfigTypes.HTTP); this.coreConfig = this.configServer.getConfig(ConfigTypes.CORE); this.locationConfig = this.configServer.getConfig(ConfigTypes.LOCATION); @@ -95,8 +93,7 @@ export class GameController this.botConfig = this.configServer.getConfig(ConfigTypes.BOT); } - public load(): void - { + public load(): void { // Regenerate base cache now mods are loaded and game is starting // Mods that add items and use the baseClass service generate the cache including their items, the next mod that // add items gets left out,causing warnings @@ -107,30 +104,25 @@ export class GameController /** * Handle client/game/start */ - public gameStart(_url: string, _info: IEmptyRequestData, sessionID: string, startTimeStampMS: number): void - { + public gameStart(_url: string, _info: IEmptyRequestData, sessionID: string, startTimeStampMS: number): void { // Store client start time in app context this.applicationContext.addValue(ContextVariableType.CLIENT_START_TIMESTAMP, startTimeStampMS); this.profileActivityService.setActivityTimestamp(sessionID); - if (this.coreConfig.fixes.fixShotgunDispersion) - { + if (this.coreConfig.fixes.fixShotgunDispersion) { this.fixShotgunDispersions(); } - if (this.locationConfig.addOpenZonesToAllMaps) - { + if (this.locationConfig.addOpenZonesToAllMaps) { this.openZoneService.applyZoneChangesToAllMaps(); } - if (this.locationConfig.addCustomBotWavesToMaps) - { + if (this.locationConfig.addCustomBotWavesToMaps) { this.customLocationWaveService.applyWaveChangesToAllMaps(); } - if (this.locationConfig.enableBotTypeLimits) - { + if (this.locationConfig.enableBotTypeLimits) { this.adjustMapBotLimits(); } @@ -143,22 +135,18 @@ export class GameController // repeatableQuests are stored by in profile.Quests due to the responses of the client (e.g. Quests in // offraidData). Since we don't want to clutter the Quests list, we need to remove all completed (failed or // successful) repeatable quests. We also have to remove the Counters from the repeatableQuests - if (sessionID) - { + if (sessionID) { const fullProfile = this.profileHelper.getFullProfile(sessionID); - if (fullProfile.info.wipe) - { + if (fullProfile.info.wipe) { // Don't bother doing any fixes, we're resetting profile return; } - if (Array.isArray(fullProfile.characters.pmc.WishList)) - { + if (Array.isArray(fullProfile.characters.pmc.WishList)) { fullProfile.characters.pmc.WishList = {}; } - if (Array.isArray(fullProfile.characters.scav.WishList)) - { + if (Array.isArray(fullProfile.characters.scav.WishList)) { fullProfile.characters.scav.WishList = {}; } @@ -167,34 +155,28 @@ export class GameController this.logger.debug(`Started game with sessionId: ${sessionID} ${pmcProfile.Info?.Nickname}`); // Migrate aki object data into spt for 3.9.0 release - if ((fullProfile as any).aki) - { + if ((fullProfile as any).aki) { fullProfile.spt = this.cloner.clone((fullProfile as any).aki); delete (fullProfile as any).aki; } - if (this.coreConfig.fixes.fixProfileBreakingInventoryItemIssues) - { + if (this.coreConfig.fixes.fixProfileBreakingInventoryItemIssues) { this.profileFixerService.fixProfileBreakingInventoryItemIssues(pmcProfile); } - if (pmcProfile.Health) - { + if (pmcProfile.Health) { this.updateProfileHealthValues(pmcProfile); } - if (this.locationConfig.fixEmptyBotWavesSettings.enabled) - { + if (this.locationConfig.fixEmptyBotWavesSettings.enabled) { this.fixBrokenOfflineMapWaves(); } - if (this.locationConfig.rogueLighthouseSpawnTimeSettings.enabled) - { + if (this.locationConfig.rogueLighthouseSpawnTimeSettings.enabled) { this.fixRoguesSpawningInstantlyOnLighthouse(); } - if (this.locationConfig.splitWaveIntoSingleSpawnsSettings.enabled) - { + if (this.locationConfig.splitWaveIntoSingleSpawnsSettings.enabled) { this.splitBotWavesIntoSingleWaves(); } @@ -202,8 +184,7 @@ export class GameController this.profileFixerService.addMissingHideoutAreasToProfile(fullProfile); - if (pmcProfile.Inventory) - { + if (pmcProfile.Inventory) { // MUST occur prior to `profileFixerService.checkForAndFixPmcProfileIssues()` this.profileFixerService.fixIncorrectAidValue(fullProfile); @@ -218,8 +199,7 @@ export class GameController this.profileFixerService.addMissingSptVersionTagToProfile(fullProfile); - if (pmcProfile.Hideout) - { + if (pmcProfile.Hideout) { this.profileFixerService.addMissingHideoutBonusesToProfile(pmcProfile); this.profileFixerService.addMissingUpgradesPropertyToHideout(pmcProfile); this.hideoutHelper.setHideoutImprovementsToCompleted(pmcProfile); @@ -241,40 +221,33 @@ export class GameController this.validateQuestAssortUnlocksExist(); - if (pmcProfile.Info) - { + if (pmcProfile.Info) { this.addPlayerToPMCNames(pmcProfile); this.checkForAndRemoveUndefinedDialogs(fullProfile); } - if (this.seasonalEventService.isAutomaticEventDetectionEnabled()) - { + if (this.seasonalEventService.isAutomaticEventDetectionEnabled()) { this.seasonalEventService.enableSeasonalEvents(sessionID); } - if (pmcProfile?.Skills?.Common) - { + if (pmcProfile?.Skills?.Common) { this.warnOnActiveBotReloadSkill(pmcProfile); } // Flea bsg blacklist is off - if (!this.ragfairConfig.dynamic.blacklist.enableBsgList) - { + if (!this.ragfairConfig.dynamic.blacklist.enableBsgList) { this.setAllDbItemsAsSellableOnFlea(); } } } - protected adjustHideoutCraftTimes(overrideSeconds: number): void - { - if (overrideSeconds === -1) - { + protected adjustHideoutCraftTimes(overrideSeconds: number): void { + if (overrideSeconds === -1) { return; } - for (const craft of this.databaseService.getHideout().production) - { + for (const craft of this.databaseService.getHideout().production) { // Only adjust crafts ABOVE the override craft.productionTime = Math.min(craft.productionTime, overrideSeconds); } @@ -283,32 +256,25 @@ export class GameController /** * Adjust all hideout craft times to be no higher than the override */ - protected adjustHideoutBuildTimes(overrideSeconds: number): void - { - if (overrideSeconds === -1) - { + protected adjustHideoutBuildTimes(overrideSeconds: number): void { + if (overrideSeconds === -1) { return; } - for (const area of this.databaseService.getHideout().areas) - { - for (const stage of Object.values(area.stages)) - { + for (const area of this.databaseService.getHideout().areas) { + for (const stage of Object.values(area.stages)) { // Only adjust crafts ABOVE the override stage.constructionTime = Math.min(stage.constructionTime, overrideSeconds); } } } - protected adjustLocationBotValues(): void - { + protected adjustLocationBotValues(): void { const mapsDb = this.databaseService.getLocations(); - for (const locationKey in this.botConfig.maxBotCap) - { + for (const locationKey in this.botConfig.maxBotCap) { const map: ILocation = mapsDb[locationKey]; - if (!map) - { + if (!map) { continue; } @@ -322,15 +288,16 @@ export class GameController /** * Out of date/incorrectly made trader mods forget this data */ - protected checkTraderRepairValuesExist(): void - { + protected checkTraderRepairValuesExist(): void { const traders = this.databaseService.getTraders(); - for (const trader of Object.values(traders)) - { - if (!trader?.base?.repair) - { - this.logger.warning(this.localisationService.getText("trader-missing_repair_property_using_default", - { traderId: trader.base._id, nickname: trader.base.nickname })); + for (const trader of Object.values(traders)) { + if (!trader?.base?.repair) { + this.logger.warning( + this.localisationService.getText("trader-missing_repair_property_using_default", { + traderId: trader.base._id, + nickname: trader.base.nickname, + }), + ); // use ragfair trader as a default trader.base.repair = this.cloner.clone(traders.ragfair.base.repair); @@ -338,49 +305,46 @@ export class GameController return; } - if (trader.base.repair?.quality === undefined) - { - this.logger.warning(this.localisationService.getText("trader-missing_repair_quality_property_using_default", - { traderId: trader.base._id, nickname: trader.base.nickname })); + if (trader.base.repair?.quality === undefined) { + this.logger.warning( + this.localisationService.getText("trader-missing_repair_quality_property_using_default", { + traderId: trader.base._id, + nickname: trader.base.nickname, + }), + ); // use ragfair trader as a default - trader.base.repair.quality = this.cloner.clone( - traders.ragfair.base.repair.quality, - ); + trader.base.repair.quality = this.cloner.clone(traders.ragfair.base.repair.quality); trader.base.repair.quality = traders.ragfair.base.repair.quality; } } } - protected addCustomLooseLootPositions(): void - { + protected addCustomLooseLootPositions(): void { const looseLootPositionsToAdd = this.lootConfig.looseLoot; - for (const [mapId, positionsToAdd] of Object.entries(looseLootPositionsToAdd)) - { - if (!mapId) - { - this.logger.warning(this.localisationService.getText("location-unable_to_add_custom_loot_position", mapId)); + for (const [mapId, positionsToAdd] of Object.entries(looseLootPositionsToAdd)) { + if (!mapId) { + this.logger.warning( + this.localisationService.getText("location-unable_to_add_custom_loot_position", mapId), + ); continue; } const mapLooseLoot = this.databaseService.getLocation(mapId).looseLoot; - if (!mapLooseLoot) - { + if (!mapLooseLoot) { this.logger.warning(this.localisationService.getText("location-map_has_no_loose_loot_data", mapId)); continue; } - for (const positionToAdd of positionsToAdd) - { + for (const positionToAdd of positionsToAdd) { // Exists already, add new items to existing positions pool const existingLootPosition = mapLooseLoot.spawnpoints.find( (x) => x.template.Id === positionToAdd.template.Id, ); - if (existingLootPosition) - { + if (existingLootPosition) { existingLootPosition.template.Items.push(...positionToAdd.template.Items); existingLootPosition.itemDistribution.push(...positionToAdd.itemDistribution); @@ -393,27 +357,27 @@ export class GameController } } - protected adjustLooseLootSpawnProbabilities(): void - { + protected adjustLooseLootSpawnProbabilities(): void { const adjustments = this.lootConfig.looseLootSpawnPointAdjustments; - for (const [mapId, mapAdjustments] of Object.entries(adjustments)) - { + for (const [mapId, mapAdjustments] of Object.entries(adjustments)) { const mapLooseLootData = this.databaseService.getLocation(mapId).looseLoot; - if (!mapLooseLootData) - { + if (!mapLooseLootData) { this.logger.warning(this.localisationService.getText("location-map_has_no_loose_loot_data", mapId)); continue; } - for (const [lootKey, newChanceValue] of Object.entries(mapAdjustments)) - { - const lootPostionToAdjust = mapLooseLootData.spawnpoints - .find((spawnPoint) => spawnPoint.template.Id === lootKey); - if (!lootPostionToAdjust) - { - this.logger.warning(this.localisationService.getText("location-unable_to_adjust_loot_position_on_map", - { lootKey: lootKey, mapId: mapId })); + for (const [lootKey, newChanceValue] of Object.entries(mapAdjustments)) { + const lootPostionToAdjust = mapLooseLootData.spawnpoints.find( + (spawnPoint) => spawnPoint.template.Id === lootKey, + ); + if (!lootPostionToAdjust) { + this.logger.warning( + this.localisationService.getText("location-unable_to_adjust_loot_position_on_map", { + lootKey: lootKey, + mapId: mapId, + }), + ); continue; } @@ -424,36 +388,28 @@ export class GameController } /** Apply custom limits on bot types as defined in configs/location.json/botTypeLimits */ - protected adjustMapBotLimits(): void - { + protected adjustMapBotLimits(): void { const mapsDb = this.databaseService.getLocations(); - if (!this.locationConfig.botTypeLimits) - { + if (!this.locationConfig.botTypeLimits) { return; } - for (const mapId in this.locationConfig.botTypeLimits) - { + for (const mapId in this.locationConfig.botTypeLimits) { const map: ILocation = mapsDb[mapId]; - if (!map) - { + if (!map) { this.logger.warning( this.localisationService.getText("bot-unable_to_edit_limits_of_unknown_map", mapId), ); } - for (const botToLimit of this.locationConfig.botTypeLimits[mapId]) - { + for (const botToLimit of this.locationConfig.botTypeLimits[mapId]) { const index = map.base.MinMaxBots.findIndex((x) => x.WildSpawnType === botToLimit.type); - if (index !== -1) - { + if (index !== -1) { // Existing bot type found in MinMaxBots array, edit const limitObjectToUpdate = map.base.MinMaxBots[index]; limitObjectToUpdate.min = botToLimit.min; limitObjectToUpdate.max = botToLimit.max; - } - else - { + } else { // Bot type not found, add new object map.base.MinMaxBots.push({ // Bot type not found, add new object @@ -469,11 +425,10 @@ export class GameController /** * Handle client/game/config */ - public getGameConfig(sessionID: string): IGameConfigResponse - { + public getGameConfig(sessionID: string): IGameConfigResponse { const profile = this.profileHelper.getPmcProfile(sessionID); - const gameTime - = profile.Stats?.Eft.OverallCounters.Items?.find( + const gameTime = + profile.Stats?.Eft.OverallCounters.Items?.find( (counter) => counter.Key.includes("LifeTime") && counter.Key.includes("Pmc"), )?.Value ?? 0; @@ -504,40 +459,35 @@ export class GameController /** * Handle client/game/mode */ - public getGameMode(sessionID: string, info: IGameModeRequestData): any - { + public getGameMode(sessionID: string, info: IGameModeRequestData): any { return { gameMode: ESessionMode.PVE, backendUrl: this.httpServerHelper.getBackendUrl() }; } /** * Handle client/server/list */ - public getServer(sessionId: string): IServerDetails[] - { + public getServer(sessionId: string): IServerDetails[] { return [{ ip: this.httpConfig.backendIp, port: Number.parseInt(this.httpConfig.backendPort) }]; } /** * Handle client/match/group/current */ - public getCurrentGroup(sessionId: string): ICurrentGroupResponse - { + public getCurrentGroup(sessionId: string): ICurrentGroupResponse { return { squad: [] }; } /** * Handle client/checkVersion */ - public getValidGameVersion(sessionId: string): ICheckVersionResponse - { + public getValidGameVersion(sessionId: string): ICheckVersionResponse { return { isvalid: true, latestVersion: this.coreConfig.compatibleTarkovVersion }; } /** * Handle client/game/keepalive */ - public getKeepAlive(sessionId: string): IGameKeepAliveResponse - { + public getKeepAlive(sessionId: string): IGameKeepAliveResponse { this.profileActivityService.setActivityTimestamp(sessionId); return { msg: "OK", utc_time: new Date().getTime() / 1000 }; } @@ -545,8 +495,7 @@ export class GameController /** * Handle singleplayer/settings/getRaidTime */ - public getRaidTime(sessionId: string, request: IGetRaidTimeRequest): IGetRaidTimeResponse - { + public getRaidTime(sessionId: string, request: IGetRaidTimeRequest): IGetRaidTimeResponse { // Set interval times to in-raid value this.ragfairConfig.runIntervalSeconds = this.ragfairConfig.runIntervalValues.inRaid; @@ -558,19 +507,12 @@ export class GameController /** * BSG have two values for shotgun dispersion, we make sure both have the same value */ - protected fixShotgunDispersions(): void - { + protected fixShotgunDispersions(): void { const itemDb = this.databaseService.getItems(); - const shotguns = [ - Weapons.SHOTGUN_12G_SAIGA_12K, - Weapons.SHOTGUN_20G_TOZ_106, - Weapons.SHOTGUN_12G_M870, - ]; - for (const shotgunId of shotguns) - { - if (itemDb[shotgunId]._props.ShotgunDispersion) - { + const shotguns = [Weapons.SHOTGUN_12G_SAIGA_12K, Weapons.SHOTGUN_20G_TOZ_106, Weapons.SHOTGUN_12G_M870]; + for (const shotgunId of shotguns) { + if (itemDb[shotgunId]._props.ShotgunDispersion) { itemDb[shotgunId]._props.shotgunDispersion = itemDb[shotgunId]._props.ShotgunDispersion; } } @@ -580,22 +522,17 @@ export class GameController * Players set botReload to a high value and don't expect the crazy fast reload speeds, give them a warn about it * @param pmcProfile Player profile */ - protected warnOnActiveBotReloadSkill(pmcProfile: IPmcData): void - { + protected warnOnActiveBotReloadSkill(pmcProfile: IPmcData): void { const botReloadSkill = this.profileHelper.getSkillFromProfile(pmcProfile, SkillTypes.BOT_RELOAD); - if (botReloadSkill?.Progress > 0) - { + if (botReloadSkill?.Progress > 0) { this.logger.warning(this.localisationService.getText("server_start_player_active_botreload_skill")); } } - protected setAllDbItemsAsSellableOnFlea(): void - { + protected setAllDbItemsAsSellableOnFlea(): void { const dbItems = Object.values(this.databaseService.getItems()); - for (const item of dbItems) - { - if (item._type === "Item" && !item._props?.CanSellOnRagfair) - { + for (const item of dbItems) { + if (item._type === "Item" && !item._props?.CanSellOnRagfair) { item._props.CanSellOnRagfair = true; } } @@ -605,15 +542,13 @@ export class GameController * When player logs in, iterate over all active effects and reduce timer * @param pmcProfile Profile to adjust values for */ - protected updateProfileHealthValues(pmcProfile: IPmcData): void - { + protected updateProfileHealthValues(pmcProfile: IPmcData): void { const healthLastUpdated = pmcProfile.Health.UpdateTime; const currentTimeStamp = this.timeUtil.getTimestamp(); const diffSeconds = currentTimeStamp - healthLastUpdated; // Last update is in past - if (healthLastUpdated < currentTimeStamp) - { + if (healthLastUpdated < currentTimeStamp) { // Base values let energyRegenPerHour = 60; let hydrationRegenPerHour = 60; @@ -632,53 +567,42 @@ export class GameController ); // Player has energy deficit - if (pmcProfile.Health.Energy.Current !== pmcProfile.Health.Energy.Maximum) - { + if (pmcProfile.Health.Energy.Current !== pmcProfile.Health.Energy.Maximum) { // Set new value, whatever is smallest pmcProfile.Health.Energy.Current += Math.round(energyRegenPerHour * (diffSeconds / 3600)); - if (pmcProfile.Health.Energy.Current > pmcProfile.Health.Energy.Maximum) - { + if (pmcProfile.Health.Energy.Current > pmcProfile.Health.Energy.Maximum) { pmcProfile.Health.Energy.Current = pmcProfile.Health.Energy.Maximum; } } // Player has hydration deficit - if (pmcProfile.Health.Hydration.Current !== pmcProfile.Health.Hydration.Maximum) - { + if (pmcProfile.Health.Hydration.Current !== pmcProfile.Health.Hydration.Maximum) { pmcProfile.Health.Hydration.Current += Math.round(hydrationRegenPerHour * (diffSeconds / 3600)); - if (pmcProfile.Health.Hydration.Current > pmcProfile.Health.Hydration.Maximum) - { + if (pmcProfile.Health.Hydration.Current > pmcProfile.Health.Hydration.Maximum) { pmcProfile.Health.Hydration.Current = pmcProfile.Health.Hydration.Maximum; } } // Check all body parts - for (const bodyPartKey in pmcProfile.Health.BodyParts) - { + for (const bodyPartKey in pmcProfile.Health.BodyParts) { const bodyPart = pmcProfile.Health.BodyParts[bodyPartKey] as BodyPartHealth; // Check part hp - if (bodyPart.Health.Current < bodyPart.Health.Maximum) - { + if (bodyPart.Health.Current < bodyPart.Health.Maximum) { bodyPart.Health.Current += Math.round(hpRegenPerHour * (diffSeconds / 3600)); } - if (bodyPart.Health.Current > bodyPart.Health.Maximum) - { + if (bodyPart.Health.Current > bodyPart.Health.Maximum) { bodyPart.Health.Current = bodyPart.Health.Maximum; } // Look for effects - if (Object.keys(bodyPart.Effects ?? {}).length > 0) - { + if (Object.keys(bodyPart.Effects ?? {}).length > 0) { // Decrement effect time value by difference between current time and time health was last updated - for (const effectKey in bodyPart.Effects) - { + for (const effectKey in bodyPart.Effects) { // remove effects below 1, .e.g. bleeds at -1 - if (bodyPart.Effects[effectKey].Time < 1) - { + if (bodyPart.Effects[effectKey].Time < 1) { // More than 30 mins has passed - if (diffSeconds > 1800) - { + if (diffSeconds > 1800) { delete bodyPart.Effects[effectKey]; } @@ -686,8 +610,7 @@ export class GameController } bodyPart.Effects[effectKey].Time -= diffSeconds; - if (bodyPart.Effects[effectKey].Time < 1) - { + if (bodyPart.Effects[effectKey].Time < 1) { // effect time was sub 1, set floor it can be bodyPart.Effects[effectKey].Time = 1; } @@ -701,31 +624,25 @@ export class GameController /** * Waves with an identical min/max values spawn nothing, the number of bots that spawn is the difference between min and max */ - protected fixBrokenOfflineMapWaves(): void - { + protected fixBrokenOfflineMapWaves(): void { const locations = this.databaseService.getLocations(); - for (const locationKey in locations) - { + for (const locationKey in locations) { // Skip ignored maps - if (this.locationConfig.fixEmptyBotWavesSettings.ignoreMaps.includes(locationKey)) - { + if (this.locationConfig.fixEmptyBotWavesSettings.ignoreMaps.includes(locationKey)) { continue; } // Loop over all of the locations waves and look for waves with identical min and max slots const location: ILocation = locations[locationKey]; - if (!location.base) - { + if (!location.base) { this.logger.warning( this.localisationService.getText("location-unable_to_fix_broken_waves_missing_base", locationKey), ); continue; } - for (const wave of location.base.waves ?? []) - { - if (wave.slots_max - wave.slots_min === 0) - { + for (const wave of location.base.waves ?? []) { + if (wave.slots_max - wave.slots_min === 0) { this.logger.debug( `Fixed ${wave.WildSpawnType} Spawn: ${locationKey} wave: ${wave.number} of type: ${wave.WildSpawnType} in zone: ${wave.SpawnPoints} with Max Slots of ${wave.slots_max}`, ); @@ -738,21 +655,18 @@ export class GameController /** * Make Rogues spawn later to allow for scavs to spawn first instead of rogues filling up all spawn positions */ - protected fixRoguesSpawningInstantlyOnLighthouse(): void - { + protected fixRoguesSpawningInstantlyOnLighthouse(): void { const rogueSpawnDelaySeconds = this.locationConfig.rogueLighthouseSpawnTimeSettings.waitTimeSeconds; const lighthouse = this.databaseService.getLocations().lighthouse?.base; - if (!lighthouse) - { + if (!lighthouse) { return; } // Find Rogues that spawn instantly - const instantRogueBossSpawns = lighthouse.BossLocationSpawn - .filter((spawn) => spawn.BossName === "exUsec" - && spawn.Time === -1); - for (const wave of instantRogueBossSpawns) - { + const instantRogueBossSpawns = lighthouse.BossLocationSpawn.filter( + (spawn) => spawn.BossName === "exUsec" && spawn.Time === -1, + ); + for (const wave of instantRogueBossSpawns) { wave.Time = rogueSpawnDelaySeconds; } } @@ -761,21 +675,18 @@ export class GameController * Send starting gifts to profile after x days * @param pmcProfile Profile to add gifts to */ - protected sendPraporGiftsToNewProfiles(pmcProfile: IPmcData): void - { + protected sendPraporGiftsToNewProfiles(pmcProfile: IPmcData): void { const timeStampProfileCreated = pmcProfile.Info.RegistrationDate; const oneDaySeconds = this.timeUtil.getHoursAsSeconds(24); const currentTimeStamp = this.timeUtil.getTimestamp(); // One day post-profile creation - if (currentTimeStamp > timeStampProfileCreated + oneDaySeconds) - { + if (currentTimeStamp > timeStampProfileCreated + oneDaySeconds) { this.giftService.sendPraporStartingGift(pmcProfile.sessionId, 1); } // Two day post-profile creation - if (currentTimeStamp > timeStampProfileCreated + oneDaySeconds * 2) - { + if (currentTimeStamp > timeStampProfileCreated + oneDaySeconds * 2) { this.giftService.sendPraporStartingGift(pmcProfile.sessionId, 2); } } @@ -784,26 +695,21 @@ export class GameController * Find and split waves with large numbers of bots into smaller waves - BSG appears to reduce the size of these * waves to one bot when they're waiting to spawn for too long */ - protected splitBotWavesIntoSingleWaves(): void - { + protected splitBotWavesIntoSingleWaves(): void { const locations = this.databaseService.getLocations(); - for (const locationKey in locations) - { - if (this.locationConfig.splitWaveIntoSingleSpawnsSettings.ignoreMaps.includes(locationKey)) - { + for (const locationKey in locations) { + if (this.locationConfig.splitWaveIntoSingleSpawnsSettings.ignoreMaps.includes(locationKey)) { continue; } // Iterate over all maps const location: ILocation = locations[locationKey]; - for (const wave of location.base.waves) - { + for (const wave of location.base.waves) { // Wave has size that makes it candidate for splitting if ( - wave.slots_max - wave.slots_min - >= this.locationConfig.splitWaveIntoSingleSpawnsSettings.waveSizeThreshold - ) - { + wave.slots_max - wave.slots_min >= + this.locationConfig.splitWaveIntoSingleSpawnsSettings.waveSizeThreshold + ) { // Get count of bots to be spawned in wave const waveSize = wave.slots_max - wave.slots_min; @@ -819,14 +725,12 @@ export class GameController // Add new waves to fill gap from bots we removed in above wave let wavesAddedCount = 0; - for (let index = indexOfWaveToSplit + 1; index < indexOfWaveToSplit + waveSize; index++) - { + for (let index = indexOfWaveToSplit + 1; index < indexOfWaveToSplit + waveSize; index++) { // Clone wave ready to insert into array const waveToAddClone = this.cloner.clone(wave); // Some waves have value of 0 for some reason, preserve - if (waveToAddClone.number !== 0) - { + if (waveToAddClone.number !== 0) { // Update wave number to new location in array waveToAddClone.number = index; } @@ -841,11 +745,9 @@ export class GameController let index = indexOfWaveToSplit + wavesAddedCount + 1; index < location.base.waves.length; index++ - ) - { + ) { // Some waves have value of 0, leave them as-is - if (location.base.waves[index].number !== 0) - { + if (location.base.waves[index].number !== 0) { location.base.waves[index].number += wavesAddedCount; } } @@ -858,28 +760,24 @@ export class GameController * Get a list of installed mods and save their details to the profile being used * @param fullProfile Profile to add mod details to */ - protected saveActiveModsToProfile(fullProfile: ISptProfile): void - { + protected saveActiveModsToProfile(fullProfile: ISptProfile): void { // Add empty mod array if undefined - if (!fullProfile.spt.mods) - { + if (!fullProfile.spt.mods) { fullProfile.spt.mods = []; } // Get active mods const activeMods = this.preSptModLoader.getImportedModDetails(); - for (const modKey in activeMods) - { + for (const modKey in activeMods) { const modDetails = activeMods[modKey]; if ( fullProfile.spt.mods.some( (mod) => - mod.author === modDetails.author - && mod.name === modDetails.name - && mod.version === modDetails.version, + mod.author === modDetails.author && + mod.name === modDetails.name && + mod.version === modDetails.version, ) - ) - { + ) { // Exists already, skip continue; } @@ -897,17 +795,14 @@ export class GameController /** * Check for any missing assorts inside each traders assort.json data, checking against traders questassort.json */ - protected validateQuestAssortUnlocksExist(): void - { + protected validateQuestAssortUnlocksExist(): void { const db = this.databaseService.getTables(); const traders = db.traders!; const quests = db.templates!.quests; - for (const traderId of Object.values(Traders)) - { + for (const traderId of Object.values(Traders)) { const traderData = traders[traderId]; const traderAssorts = traderData?.assort; - if (!traderAssorts) - { + if (!traderAssorts) { continue; } @@ -919,11 +814,9 @@ export class GameController }; // Loop over all assorts for trader - for (const [assortKey, questKey] of Object.entries(mergedQuestAssorts)) - { + for (const [assortKey, questKey] of Object.entries(mergedQuestAssorts)) { // Does assort key exist in trader assort file - if (!traderAssorts.loyal_level_items[assortKey]) - { + if (!traderAssorts.loyal_level_items[assortKey]) { // Reverse lookup of enum key by value const messageValues = { traderName: Object.keys(Traders)[Object.values(Traders).indexOf(traderId)], @@ -941,20 +834,16 @@ export class GameController * Add the logged in players name to PMC name pool * @param pmcProfile Profile of player to get name from */ - protected addPlayerToPMCNames(pmcProfile: IPmcData): void - { + protected addPlayerToPMCNames(pmcProfile: IPmcData): void { const playerName = pmcProfile.Info.Nickname; - if (playerName) - { + if (playerName) { const bots = this.databaseService.getBots().types; - if (bots.bear) - { + if (bots.bear) { bots.bear.firstName.push(playerName); } - if (bots.usec) - { + if (bots.usec) { bots.usec.firstName.push(playerName); } } @@ -964,11 +853,9 @@ export class GameController * Check for a dialog with the key 'undefined', and remove it * @param fullProfile Profile to check for dialog in */ - protected checkForAndRemoveUndefinedDialogs(fullProfile: ISptProfile): void - { + protected checkForAndRemoveUndefinedDialogs(fullProfile: ISptProfile): void { const undefinedDialog = fullProfile.dialogues.undefined; - if (undefinedDialog) - { + if (undefinedDialog) { delete fullProfile.dialogues.undefined; } } @@ -976,12 +863,10 @@ export class GameController /** * Blank out the "test" mail message from prapor */ - protected removePraporTestMessage(): void - { + protected removePraporTestMessage(): void { // Iterate over all languages (e.g. "en", "fr") const locales = this.databaseService.getLocales(); - for (const localeKey in locales.global) - { + for (const localeKey in locales.global) { locales.global[localeKey]["61687e2c3e526901fa76baf9"] = ""; } } @@ -989,24 +874,21 @@ export class GameController /** * Make non-trigger-spawned raiders spawn earlier + always */ - protected adjustLabsRaiderSpawnRate(): void - { + protected adjustLabsRaiderSpawnRate(): void { const labsBase = this.databaseService.getLocations().laboratory!.base; // Find spawns with empty string for triggerId/TriggerName - const nonTriggerLabsBossSpawns = labsBase.BossLocationSpawn - .filter((bossSpawn) => !bossSpawn.TriggerId - && !bossSpawn.TriggerName); + const nonTriggerLabsBossSpawns = labsBase.BossLocationSpawn.filter( + (bossSpawn) => !bossSpawn.TriggerId && !bossSpawn.TriggerName, + ); - for (const boss of nonTriggerLabsBossSpawns) - { + for (const boss of nonTriggerLabsBossSpawns) { boss.BossChance = 100; boss.Time /= 10; } } - protected logProfileDetails(fullProfile: ISptProfile): void - { + protected logProfileDetails(fullProfile: ISptProfile): void { this.logger.debug(`Profile made with: ${fullProfile.spt.version}`); this.logger.debug( `Server version: ${globalThis.G_SPTVERSION || this.coreConfig.sptVersion} ${globalThis.G_COMMIT}`, diff --git a/project/src/controllers/HandbookController.ts b/project/src/controllers/HandbookController.ts index c50129e9..c511e7e7 100644 --- a/project/src/controllers/HandbookController.ts +++ b/project/src/controllers/HandbookController.ts @@ -1,18 +1,15 @@ -import { inject, injectable } from "tsyringe"; import { HandbookHelper } from "@spt/helpers/HandbookHelper"; import { DatabaseServer } from "@spt/servers/DatabaseServer"; +import { inject, injectable } from "tsyringe"; @injectable() -export class HandbookController -{ +export class HandbookController { constructor( @inject("DatabaseServer") protected databaseServer: DatabaseServer, @inject("HandbookHelper") protected handbookHelper: HandbookHelper, - ) - {} + ) {} - public load(): void - { + public load(): void { return; } } diff --git a/project/src/controllers/HealthController.ts b/project/src/controllers/HealthController.ts index 6b5f1b45..8a785741 100644 --- a/project/src/controllers/HealthController.ts +++ b/project/src/controllers/HealthController.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { HealthHelper } from "@spt/helpers/HealthHelper"; import { InventoryHelper } from "@spt/helpers/InventoryHelper"; import { ItemHelper } from "@spt/helpers/ItemHelper"; @@ -15,12 +14,12 @@ import { ILogger } from "@spt/models/spt/utils/ILogger"; import { EventOutputHolder } from "@spt/routers/EventOutputHolder"; import { LocalisationService } from "@spt/services/LocalisationService"; import { PaymentService } from "@spt/services/PaymentService"; -import { ICloner } from "@spt/utils/cloners/ICloner"; import { HttpResponseUtil } from "@spt/utils/HttpResponseUtil"; +import { ICloner } from "@spt/utils/cloners/ICloner"; +import { inject, injectable } from "tsyringe"; @injectable() -export class HealthController -{ +export class HealthController { constructor( @inject("PrimaryLogger") protected logger: ILogger, @inject("EventOutputHolder") protected eventOutputHolder: EventOutputHolder, @@ -31,8 +30,7 @@ export class HealthController @inject("HttpResponseUtil") protected httpResponse: HttpResponseUtil, @inject("HealthHelper") protected healthHelper: HealthHelper, @inject("PrimaryCloner") protected cloner: ICloner, - ) - {} + ) {} /** * stores in-raid player health @@ -48,8 +46,7 @@ export class HealthController sessionID: string, addEffects = true, deleteExistingEffects = true, - ): void - { + ): void { this.healthHelper.saveVitality(pmcData, info, sessionID, addEffects, deleteExistingEffects); } @@ -64,14 +61,12 @@ export class HealthController pmcData: IPmcData, request: IOffraidHealRequestData, sessionID: string, - ): IItemEventRouterResponse - { + ): IItemEventRouterResponse { const output = this.eventOutputHolder.getOutput(sessionID); // Update medkit used (hpresource) const healingItemToUse = pmcData.Inventory.items.find((item) => item._id === request.item); - if (!healingItemToUse) - { + if (!healingItemToUse) { const errorMessage = this.localisationService.getText( "health-healing_item_not_found", healingItemToUse._id, @@ -84,20 +79,16 @@ export class HealthController // Ensure item has a upd object this.itemHelper.addUpdObjectToItem(healingItemToUse); - if (healingItemToUse.upd.MedKit) - { + if (healingItemToUse.upd.MedKit) { healingItemToUse.upd.MedKit.HpResource -= request.count; - } - else - { + } else { // Get max healing from db const maxhp = this.itemHelper.getItem(healingItemToUse._tpl)[1]._props.MaxHpResource; healingItemToUse.upd.MedKit = { HpResource: maxhp - request.count }; // Subtract amout used from max } // Resource in medkit is spent, delete it - if (healingItemToUse.upd.MedKit.HpResource <= 0) - { + if (healingItemToUse.upd.MedKit.HpResource <= 0) { this.inventoryHelper.removeItem(pmcData, request.item, sessionID, output); } @@ -112,14 +103,12 @@ export class HealthController * @param sessionID Session id * @returns IItemEventRouterResponse */ - public offraidEat(pmcData: IPmcData, request: IOffraidEatRequestData, sessionID: string): IItemEventRouterResponse - { + public offraidEat(pmcData: IPmcData, request: IOffraidEatRequestData, sessionID: string): IItemEventRouterResponse { const output = this.eventOutputHolder.getOutput(sessionID); let resourceLeft = 0; const itemToConsume = pmcData.Inventory.items.find((item) => item._id === request.item); - if (!itemToConsume) - { + if (!itemToConsume) { // Item not found, very bad return this.httpResponse.appendErrorToOutput( output, @@ -128,17 +117,13 @@ export class HealthController } const consumedItemMaxResource = this.itemHelper.getItem(itemToConsume._tpl)[1]._props.MaxResource; - if (consumedItemMaxResource > 1) - { + if (consumedItemMaxResource > 1) { // Ensure item has a upd object this.itemHelper.addUpdObjectToItem(itemToConsume); - if (itemToConsume.upd.FoodDrink === undefined) - { + if (itemToConsume.upd.FoodDrink === undefined) { itemToConsume.upd.FoodDrink = { HpPercent: consumedItemMaxResource - request.count }; - } - else - { + } else { itemToConsume.upd.FoodDrink.HpPercent -= request.count; } @@ -146,8 +131,7 @@ export class HealthController } // Remove item from inventory if resource has dropped below threshold - if (consumedItemMaxResource === 1 || resourceLeft < 1) - { + if (consumedItemMaxResource === 1 || resourceLeft < 1) { this.inventoryHelper.removeItem(pmcData, request.item, sessionID, output); } @@ -166,8 +150,7 @@ export class HealthController pmcData: IPmcData, healthTreatmentRequest: IHealthTreatmentRequestData, sessionID: string, - ): IItemEventRouterResponse - { + ): IItemEventRouterResponse { const output = this.eventOutputHolder.getOutput(sessionID); const payMoneyRequest: IProcessBuyTradeRequestData = { Action: healthTreatmentRequest.Action, @@ -180,36 +163,30 @@ export class HealthController }; this.paymentService.payMoney(pmcData, payMoneyRequest, sessionID, output); - if (output.warnings.length > 0) - { + if (output.warnings.length > 0) { return output; } - for (const bodyPartKey in healthTreatmentRequest.difference.BodyParts) - { + for (const bodyPartKey in healthTreatmentRequest.difference.BodyParts) { // Get body part from request + from pmc profile const partRequest: BodyPart = healthTreatmentRequest.difference.BodyParts[bodyPartKey]; const profilePart = pmcData.Health.BodyParts[bodyPartKey]; // Bodypart healing is chosen when part request hp is above 0 - if (partRequest.Health > 0) - { + if (partRequest.Health > 0) { // Heal bodypart profilePart.Health.Current = profilePart.Health.Maximum; } // Check for effects to remove - if (partRequest.Effects?.length > 0) - { + if (partRequest.Effects?.length > 0) { // Found some, loop over them and remove from pmc profile - for (const effect of partRequest.Effects) - { + for (const effect of partRequest.Effects) { delete pmcData.Health.BodyParts[bodyPartKey].Effects[effect]; } // Remove empty effect object - if (Object.keys(pmcData.Health.BodyParts[bodyPartKey].Effects).length === 0) - { + if (Object.keys(pmcData.Health.BodyParts[bodyPartKey].Effects).length === 0) { delete pmcData.Health.BodyParts[bodyPartKey].Effects; } } @@ -227,8 +204,7 @@ export class HealthController * @param info Request data * @param sessionID */ - public applyWorkoutChanges(pmcData: IPmcData, info: IWorkoutData, sessionId: string): void - { + public applyWorkoutChanges(pmcData: IPmcData, info: IWorkoutData, sessionId: string): void { // https://dev.sp-tarkov.com/SPT/Server/issues/2674 // TODO: // Health effects (fractures etc) are handled in /player/health/sync. diff --git a/project/src/controllers/HideoutController.ts b/project/src/controllers/HideoutController.ts index 8b90f929..117d73e8 100644 --- a/project/src/controllers/HideoutController.ts +++ b/project/src/controllers/HideoutController.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { ScavCaseRewardGenerator } from "@spt/generators/ScavCaseRewardGenerator"; import { HideoutHelper } from "@spt/helpers/HideoutHelper"; import { InventoryHelper } from "@spt/helpers/InventoryHelper"; @@ -7,12 +6,7 @@ import { PaymentHelper } from "@spt/helpers/PaymentHelper"; import { PresetHelper } from "@spt/helpers/PresetHelper"; import { ProfileHelper } from "@spt/helpers/ProfileHelper"; import { IPmcData } from "@spt/models/eft/common/IPmcData"; -import { - HideoutArea, - ITaskConditionCounter, - Product, - ScavCase, -} from "@spt/models/eft/common/tables/IBotBase"; +import { HideoutArea, ITaskConditionCounter, Product, ScavCase } from "@spt/models/eft/common/tables/IBotBase"; import { Item } from "@spt/models/eft/common/tables/IItem"; import { HideoutUpgradeCompleteRequestData } from "@spt/models/eft/hideout/HideoutUpgradeCompleteRequestData"; import { IHandleQTEEventRequestData } from "@spt/models/eft/hideout/IHandleQTEEventRequestData"; @@ -47,15 +41,15 @@ import { FenceService } from "@spt/services/FenceService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { PlayerService } from "@spt/services/PlayerService"; import { ProfileActivityService } from "@spt/services/ProfileActivityService"; -import { ICloner } from "@spt/utils/cloners/ICloner"; import { HashUtil } from "@spt/utils/HashUtil"; import { HttpResponseUtil } from "@spt/utils/HttpResponseUtil"; import { RandomUtil } from "@spt/utils/RandomUtil"; import { TimeUtil } from "@spt/utils/TimeUtil"; +import { ICloner } from "@spt/utils/cloners/ICloner"; +import { inject, injectable } from "tsyringe"; @injectable() -export class HideoutController -{ +export class HideoutController { /** Key used in TaskConditionCounters array */ protected static nameTaskConditionCountersCrafting = "CounterHoursCrafting"; protected hideoutConfig: IHideoutConfig; @@ -82,8 +76,7 @@ export class HideoutController @inject("ConfigServer") protected configServer: ConfigServer, @inject("FenceService") protected fenceService: FenceService, @inject("PrimaryCloner") protected cloner: ICloner, - ) - { + ) { this.hideoutConfig = this.configServer.getConfig(ConfigTypes.HIDEOUT); } @@ -100,19 +93,15 @@ export class HideoutController request: IHideoutUpgradeRequestData, sessionID: string, output: IItemEventRouterResponse, - ): void - { - const items = request.items.map((reqItem) => - { + ): void { + const items = request.items.map((reqItem) => { const item = pmcData.Inventory.items.find((invItem) => invItem._id === reqItem.id); return { inventoryItem: item, requestedItem: reqItem }; }); // If it's not money, its construction / barter items - for (const item of items) - { - if (!item.inventoryItem) - { + for (const item of items) { + if (!item.inventoryItem) { this.logger.error( this.localisationService.getText("hideout-unable_to_find_item_in_inventory", item.requestedItem.id), ); @@ -122,24 +111,20 @@ export class HideoutController } if ( - this.paymentHelper.isMoneyTpl(item.inventoryItem._tpl) - && item.inventoryItem.upd - && item.inventoryItem.upd.StackObjectsCount - && item.inventoryItem.upd.StackObjectsCount > item.requestedItem.count - ) - { + this.paymentHelper.isMoneyTpl(item.inventoryItem._tpl) && + item.inventoryItem.upd && + item.inventoryItem.upd.StackObjectsCount && + item.inventoryItem.upd.StackObjectsCount > item.requestedItem.count + ) { item.inventoryItem.upd.StackObjectsCount -= item.requestedItem.count; - } - else - { + } else { this.inventoryHelper.removeItem(pmcData, item.inventoryItem._id, sessionID, output); } } // Construction time management const profileHideoutArea = pmcData.Hideout.Areas.find((area) => area.type === request.areaType); - if (!profileHideoutArea) - { + if (!profileHideoutArea) { this.logger.error(this.localisationService.getText("hideout-unable_to_find_area", request.areaType)); this.httpResponse.appendErrorToOutput(output); @@ -149,8 +134,7 @@ export class HideoutController const hideoutDataDb = this.databaseService .getTables() .hideout.areas.find((area) => area.type === request.areaType); - if (!hideoutDataDb) - { + if (!hideoutDataDb) { this.logger.error( this.localisationService.getText("hideout-unable_to_find_area_in_database", request.areaType), ); @@ -160,10 +144,8 @@ export class HideoutController } let ctime = hideoutDataDb.stages[profileHideoutArea.level + 1].constructionTime; - if (ctime > 0) - { - if (this.profileHelper.isDeveloperAccount(sessionID)) - { + if (ctime > 0) { + if (this.profileHelper.isDeveloperAccount(sessionID)) { ctime = 40; } const timestamp = this.timeUtil.getTimestamp(); @@ -186,14 +168,12 @@ export class HideoutController request: HideoutUpgradeCompleteRequestData, sessionID: string, output: IItemEventRouterResponse, - ): void - { + ): void { const hideout = this.databaseService.getHideout(); const globals = this.databaseService.getGlobals(); const profileHideoutArea = pmcData.Hideout.Areas.find((area) => area.type === request.areaType); - if (!profileHideoutArea) - { + if (!profileHideoutArea) { this.logger.error(this.localisationService.getText("hideout-unable_to_find_area", request.areaType)); this.httpResponse.appendErrorToOutput(output); @@ -206,8 +186,7 @@ export class HideoutController profileHideoutArea.constructing = false; const hideoutData = hideout.areas.find((area) => area.type === profileHideoutArea.type); - if (!hideoutData) - { + if (!hideoutData) { this.logger.error( this.localisationService.getText("hideout-unable_to_find_area_in_database", request.areaType), ); @@ -219,17 +198,14 @@ export class HideoutController // Apply bonuses const hideoutStage = hideoutData.stages[profileHideoutArea.level]; const bonuses = hideoutStage.bonuses; - if (bonuses?.length > 0) - { - for (const bonus of bonuses) - { + if (bonuses?.length > 0) { + for (const bonus of bonuses) { this.hideoutHelper.applyPlayerUpgradesBonuses(pmcData, bonus); } } // Upgrade includes a container improvement/addition - if (hideoutStage?.container) - { + if (hideoutStage?.container) { this.addContainerImprovementToProfile( output, sessionID, @@ -242,10 +218,9 @@ export class HideoutController // Upgrading water collector / med station if ( - profileHideoutArea.type === HideoutAreas.WATER_COLLECTOR - || profileHideoutArea.type === HideoutAreas.MEDSTATION - ) - { + profileHideoutArea.type === HideoutAreas.WATER_COLLECTOR || + profileHideoutArea.type === HideoutAreas.MEDSTATION + ) { this.checkAndUpgradeWall(pmcData); } @@ -261,15 +236,12 @@ export class HideoutController * Upgrade wall status to visible in profile if medstation/water collector are both level 1 * @param pmcData Player profile */ - protected checkAndUpgradeWall(pmcData: IPmcData): void - { + protected checkAndUpgradeWall(pmcData: IPmcData): void { const medStation = pmcData.Hideout.Areas.find((area) => area.type === HideoutAreas.MEDSTATION); const waterCollector = pmcData.Hideout.Areas.find((area) => area.type === HideoutAreas.WATER_COLLECTOR); - if (medStation?.level >= 1 && waterCollector?.level >= 1) - { + if (medStation?.level >= 1 && waterCollector?.level >= 1) { const wall = pmcData.Hideout.Areas.find((area) => area.type === HideoutAreas.EMERGENCY_WALL); - if (wall?.level === 0) - { + if (wall?.level === 0) { wall.level = 3; } } @@ -290,11 +262,9 @@ export class HideoutController profileParentHideoutArea: HideoutArea, dbHideoutArea: IHideoutArea, hideoutStage: Stage, - ): void - { + ): void { // Add key/value to `hideoutAreaStashes` dictionary - used to link hideout area to inventory stash by its id - if (!pmcData.Inventory.hideoutAreaStashes[dbHideoutArea.type]) - { + if (!pmcData.Inventory.hideoutAreaStashes[dbHideoutArea.type]) { pmcData.Inventory.hideoutAreaStashes[dbHideoutArea.type] = dbHideoutArea._id; } @@ -302,29 +272,24 @@ export class HideoutController this.addUpdateInventoryItemToProfile(pmcData, dbHideoutArea, hideoutStage); // Dont inform client when upgraded area is hall of fame, BSG doesnt inform client upgrade has occurred, will break client if data is sent - if (dbHideoutArea.type !== HideoutAreas.PLACE_OF_FAME) - { + if (dbHideoutArea.type !== HideoutAreas.PLACE_OF_FAME) { // Inform client of changes this.addContainerUpgradeToClientOutput(output, sessionID, dbHideoutArea.type, dbHideoutArea, hideoutStage); } // Some areas like gun stand have a child area linked to it, it needs to do the same as above - const childDbArea = this.databaseService.getHideout().areas - .find((area) => area.parentArea === dbHideoutArea._id); - if (childDbArea) - { + const childDbArea = this.databaseService + .getHideout() + .areas.find((area) => area.parentArea === dbHideoutArea._id); + if (childDbArea) { // Add key/value to `hideoutAreaStashes` dictionary - used to link hideout area to inventory stash by its id - if (!pmcData.Inventory.hideoutAreaStashes[childDbArea.type]) - { + if (!pmcData.Inventory.hideoutAreaStashes[childDbArea.type]) { pmcData.Inventory.hideoutAreaStashes[childDbArea.type] = childDbArea._id; } // Set child area level to same as parent area - pmcData.Hideout.Areas - .find((hideoutArea) => hideoutArea.type === childDbArea.type).level - = pmcData.Hideout.Areas - .find((x) => x.type === profileParentHideoutArea.type, - ).level; + pmcData.Hideout.Areas.find((hideoutArea) => hideoutArea.type === childDbArea.type).level = + pmcData.Hideout.Areas.find((x) => x.type === profileParentHideoutArea.type).level; // Add/upgrade stash item in player inventory const childDbAreaStage = childDbArea.stages[profileParentHideoutArea.level]; @@ -345,11 +310,9 @@ export class HideoutController pmcData: IPmcData, dbHideoutData: IHideoutArea, hideoutStage: Stage, - ): void - { + ): void { const existingInventoryItem = pmcData.Inventory.items.find((item) => item._id === dbHideoutData._id); - if (existingInventoryItem) - { + if (existingInventoryItem) { // Update existing items container tpl to point to new id (tpl) existingInventoryItem._tpl = hideoutStage.container; @@ -373,10 +336,8 @@ export class HideoutController areaType: HideoutAreas, hideoutDbData: IHideoutArea, hideoutStage: Stage, - ): void - { - if (!output.profileChanges[sessionID].changedHideoutStashes) - { + ): void { + if (!output.profileChanges[sessionID].changedHideoutStashes) { output.profileChanges[sessionID].changedHideoutStashes = {}; } @@ -398,19 +359,16 @@ export class HideoutController pmcData: IPmcData, addItemToHideoutRequest: IHideoutPutItemInRequestData, sessionID: string, - ): IItemEventRouterResponse - { + ): IItemEventRouterResponse { const output = this.eventOutputHolder.getOutput(sessionID); - const itemsToAdd = Object.entries(addItemToHideoutRequest.items).map((kvp) => - { + const itemsToAdd = Object.entries(addItemToHideoutRequest.items).map((kvp) => { const item = pmcData.Inventory.items.find((invItem) => invItem._id === kvp[1].id); return { inventoryItem: item, requestedItem: kvp[1], slot: kvp[0] }; }); const hideoutArea = pmcData.Hideout.Areas.find((area) => area.type === addItemToHideoutRequest.areaType); - if (!hideoutArea) - { + if (!hideoutArea) { this.logger.error( this.localisationService.getText( "hideout-unable_to_find_area_in_database", @@ -420,10 +378,8 @@ export class HideoutController return this.httpResponse.appendErrorToOutput(output); } - for (const item of itemsToAdd) - { - if (!item.inventoryItem) - { + for (const item of itemsToAdd) { + if (!item.inventoryItem) { this.logger.error( this.localisationService.getText("hideout-unable_to_find_item_in_inventory", { itemId: item.requestedItem.id, @@ -465,19 +421,16 @@ export class HideoutController pmcData: IPmcData, request: IHideoutTakeItemOutRequestData, sessionID: string, - ): IItemEventRouterResponse - { + ): IItemEventRouterResponse { const output = this.eventOutputHolder.getOutput(sessionID); const hideoutArea = pmcData.Hideout.Areas.find((area) => area.type === request.areaType); - if (!hideoutArea) - { + if (!hideoutArea) { this.logger.error(this.localisationService.getText("hideout-unable_to_find_area", request.areaType)); return this.httpResponse.appendErrorToOutput(output); } - if (!hideoutArea.slots || hideoutArea.slots.length === 0) - { + if (!hideoutArea.slots || hideoutArea.slots.length === 0) { this.logger.error( this.localisationService.getText("hideout-unable_to_find_item_to_remove_from_area", hideoutArea.type), ); @@ -492,8 +445,7 @@ export class HideoutController HideoutAreas.GENERATOR, HideoutAreas.BITCOIN_FARM, ].includes(hideoutArea.type) - ) - { + ) { const response = this.removeResourceFromArea(sessionID, pmcData, request, output, hideoutArea); // Force a refresh of productions/hideout areas with resources @@ -521,13 +473,11 @@ export class HideoutController removeResourceRequest: IHideoutTakeItemOutRequestData, output: IItemEventRouterResponse, hideoutArea: HideoutArea, - ): IItemEventRouterResponse - { + ): IItemEventRouterResponse { const slotIndexToRemove = removeResourceRequest.slots[0]; // Assume only one item in slot - const itemToReturn = hideoutArea.slots - .find((slot) => slot.locationIndex === slotIndexToRemove).item[0]; + const itemToReturn = hideoutArea.slots.find((slot) => slot.locationIndex === slotIndexToRemove).item[0]; const request: IAddItemDirectRequest = { itemWithModsToAdd: [itemToReturn], @@ -537,8 +487,7 @@ export class HideoutController }; this.inventoryHelper.addItemToStash(sessionID, request, pmcData, output); - if (output.warnings && output.warnings.length > 0) - { + if (output.warnings && output.warnings.length > 0) { // Adding to stash failed, drop out - dont remove item from hideout area slot return output; } @@ -562,16 +511,14 @@ export class HideoutController pmcData: IPmcData, request: IHideoutToggleAreaRequestData, sessionID: string, - ): IItemEventRouterResponse - { + ): IItemEventRouterResponse { const output = this.eventOutputHolder.getOutput(sessionID); // Force a production update (occur before area is toggled as it could be generator and doing it after generator enabled would cause incorrect calculaton of production progress) this.hideoutHelper.updatePlayerHideout(sessionID); const hideoutArea = pmcData.Hideout.Areas.find((area) => area.type === request.areaType); - if (!hideoutArea) - { + if (!hideoutArea) { this.logger.error(this.localisationService.getText("hideout-unable_to_find_area", request.areaType)); return this.httpResponse.appendErrorToOutput(output); } @@ -593,14 +540,14 @@ export class HideoutController pmcData: IPmcData, body: IHideoutSingleProductionStartRequestData, sessionID: string, - ): IItemEventRouterResponse - { + ): IItemEventRouterResponse { // Start production this.hideoutHelper.registerProduction(pmcData, body, sessionID); // Find the recipe of the production - const recipe = this.databaseService.getHideout().production - .find((production) => production._id === body.recipeId); + const recipe = this.databaseService + .getHideout() + .production.find((production) => production._id === body.recipeId); // Find the actual amount of items we need to remove because body can send weird data const recipeRequirementsClone = this.cloner.clone( @@ -609,8 +556,7 @@ export class HideoutController const output = this.eventOutputHolder.getOutput(sessionID); const itemsToDelete = body.items.concat(body.tools); - for (const itemToDelete of itemsToDelete) - { + for (const itemToDelete of itemsToDelete) { const itemToCheck = pmcData.Inventory.items.find((i) => i._id === itemToDelete.id); const requirement = recipeRequirementsClone.find( (requirement) => requirement.templateId === itemToCheck._tpl, @@ -618,16 +564,14 @@ export class HideoutController // Handle tools not having a `count`, but always only requiring 1 const requiredCount = requirement.count ?? 1; - if (requiredCount <= 0) - { + if (requiredCount <= 0) { continue; } this.inventoryHelper.removeItemByCount(pmcData, itemToDelete.id, requiredCount, sessionID, output); // Tools don't have a count - if (requirement.type !== "Tool") - { + if (requirement.type !== "Tool") { requirement.count -= itemToDelete.count; } } @@ -647,15 +591,12 @@ export class HideoutController pmcData: IPmcData, body: IHideoutScavCaseStartRequestData, sessionID: string, - ): IItemEventRouterResponse - { + ): IItemEventRouterResponse { const output = this.eventOutputHolder.getOutput(sessionID); - for (const requestedItem of body.items) - { + for (const requestedItem of body.items) { const inventoryItem = pmcData.Inventory.items.find((item) => item._id === requestedItem.id); - if (!inventoryItem) - { + if (!inventoryItem) { this.logger.error( this.localisationService.getText( "hideout-unable_to_find_scavcase_requested_item_in_profile_inventory", @@ -665,20 +606,15 @@ export class HideoutController return this.httpResponse.appendErrorToOutput(output); } - if (inventoryItem.upd?.StackObjectsCount && inventoryItem.upd.StackObjectsCount > requestedItem.count) - { + if (inventoryItem.upd?.StackObjectsCount && inventoryItem.upd.StackObjectsCount > requestedItem.count) { inventoryItem.upd.StackObjectsCount -= requestedItem.count; - } - else - { + } else { this.inventoryHelper.removeItem(pmcData, requestedItem.id, sessionID, output); } } - const recipe = this.databaseService.getHideout().scavcase - .find((r) => r._id === body.recipeId); - if (!recipe) - { + const recipe = this.databaseService.getHideout().scavcase.find((r) => r._id === body.recipeId); + if (!recipe) { this.logger.error( this.localisationService.getText("hideout-unable_to_find_scav_case_recipie_in_database", body.recipeId), ); @@ -689,9 +625,9 @@ export class HideoutController // @Important: Here we need to be very exact: // - normal recipe: Production time value is stored in attribute "productionTime" with small "p" // - scav case recipe: Production time value is stored in attribute "ProductionTime" with capital "P" - const adjustedCraftTime - = recipe.ProductionTime - - this.hideoutHelper.getSkillProductionTimeReduction( + const adjustedCraftTime = + recipe.ProductionTime - + this.hideoutHelper.getSkillProductionTimeReduction( pmcData, recipe.ProductionTime, SkillTypes.CRAFTING, @@ -717,11 +653,9 @@ export class HideoutController * @param productionTime Time to complete scav case in seconds * @returns Adjusted scav case time in seconds */ - protected getScavCaseTime(pmcData: IPmcData, productionTime: number): number - { + protected getScavCaseTime(pmcData: IPmcData, productionTime: number): number { const fenceLevel = this.fenceService.getFenceInfo(pmcData); - if (!fenceLevel) - { + if (!fenceLevel) { return productionTime; } @@ -734,8 +668,7 @@ export class HideoutController * @param rewards reward items to add to profile * @param recipeId recipe id to save into Production dict */ - protected addScavCaseRewardsToProfile(pmcData: IPmcData, rewards: Product[], recipeId: string): void - { + protected addScavCaseRewardsToProfile(pmcData: IPmcData, rewards: Product[], recipeId: string): void { pmcData.Hideout.Production[`ScavCase${recipeId}`] = { Products: rewards }; } @@ -750,8 +683,7 @@ export class HideoutController pmcData: IPmcData, request: IHideoutContinuousProductionStartRequestData, sessionID: string, - ): IItemEventRouterResponse - { + ): IItemEventRouterResponse { this.hideoutHelper.registerProduction(pmcData, request, sessionID); return this.eventOutputHolder.getOutput(sessionID); @@ -769,13 +701,11 @@ export class HideoutController pmcData: IPmcData, request: IHideoutTakeProductionRequestData, sessionID: string, - ): IItemEventRouterResponse - { + ): IItemEventRouterResponse { const output = this.eventOutputHolder.getOutput(sessionID); const hideoutDb = this.databaseService.getHideout(); - if (request.recipeId === HideoutHelper.bitcoinFarm) - { + if (request.recipeId === HideoutHelper.bitcoinFarm) { // Ensure server and client are in-sync when player presses 'get items' on farm this.hideoutHelper.updatePlayerHideout(sessionID); this.hideoutHelper.getBTC(pmcData, request, sessionID, output); @@ -784,16 +714,14 @@ export class HideoutController } const recipe = hideoutDb.production.find((r) => r._id === request.recipeId); - if (recipe) - { + if (recipe) { this.handleRecipe(sessionID, recipe, pmcData, request, output); return output; } const scavCase = hideoutDb.scavcase.find((r) => r._id === request.recipeId); - if (scavCase) - { + if (scavCase) { this.handleScavCase(sessionID, pmcData, request, output); return output; @@ -823,24 +751,19 @@ export class HideoutController pmcData: IPmcData, request: IHideoutTakeProductionRequestData, output: IItemEventRouterResponse, - ): void - { + ): void { // Validate that we have a matching production const productionDict = Object.entries(pmcData.Hideout.Production); let prodId: string; - for (const [productionId, production] of productionDict) - { + for (const [productionId, production] of productionDict) { // Skip undefined production objects - if (!production) - { + if (!production) { continue; } - if (this.hideoutHelper.isProductionType(production)) - { + if (this.hideoutHelper.isProductionType(production)) { // Production or ScavCase - if (production.RecipeId === request.recipeId) - { + if (production.RecipeId === request.recipeId) { prodId = productionId; // Set to objects key break; } @@ -848,8 +771,7 @@ export class HideoutController } // If we're unable to find the production, send an error to the client - if (prodId === undefined) - { + if (prodId === undefined) { this.logger.error( this.localisationService.getText( "hideout-unable_to_find_production_in_profile_by_recipie_id", @@ -879,8 +801,7 @@ export class HideoutController // Reward is weapon/armor preset, handle differently compared to 'normal' items const rewardIsPreset = this.presetHelper.hasPreset(recipe.endProduct); - if (rewardIsPreset) - { + if (rewardIsPreset) { const preset = this.presetHelper.getDefaultPreset(recipe.endProduct); // Ensure preset has unique ids and is cloned so we don't alter the preset data stored in memory @@ -893,8 +814,7 @@ export class HideoutController } const rewardIsStackable = this.itemHelper.isItemTplStackable(recipe.endProduct); - if (rewardIsStackable) - { + if (rewardIsStackable) { // Create root item const rewardToAdd: Item = { _id: this.hashUtil.generate(), @@ -905,32 +825,26 @@ export class HideoutController // Split item into separate items with acceptable stack sizes const splitReward = this.itemHelper.splitStackIntoSeparateItems(rewardToAdd); itemAndChildrenToSendToPlayer.push(...splitReward); - } - else - { + } else { // Not stackable, may have to send send multiple of reward // Add the first reward item to array when not a preset (first preset added above earlier) - if (!rewardIsPreset) - { + if (!rewardIsPreset) { itemAndChildrenToSendToPlayer.push([{ _id: this.hashUtil.generate(), _tpl: recipe.endProduct }]); } // Add multiple of item if recipe requests it // Start index at one so we ignore first item in array const countOfItemsToReward = recipe.count; - for (let index = 1; index < countOfItemsToReward; index++) - { + for (let index = 1; index < countOfItemsToReward; index++) { const itemAndMods: Item[] = this.itemHelper.replaceIDs(itemAndChildrenToSendToPlayer[0]); itemAndChildrenToSendToPlayer.push(...[itemAndMods]); } } // Recipe has an `isEncoded` requirement for reward(s), Add `RecodableComponent` property - if (recipe.isEncoded) - { - for (const reward of itemAndChildrenToSendToPlayer) - { + if (recipe.isEncoded) { + for (const reward of itemAndChildrenToSendToPlayer) { this.itemHelper.addUpdObjectToItem(reward[0]); reward[0].upd.RecodableComponent = { IsEncoded: true }; @@ -940,18 +854,15 @@ export class HideoutController // Build an array of the tools that need to be returned to the player const toolsToSendToPlayer: Item[][] = []; const production = pmcData.Hideout.Production[prodId]; - if (production.sptRequiredTools?.length > 0) - { - for (const tool of production.sptRequiredTools) - { + if (production.sptRequiredTools?.length > 0) { + for (const tool of production.sptRequiredTools) { toolsToSendToPlayer.push([tool]); } } // Check if the recipe is the same as the last one - get bonus when crafting same thing multiple times const area = pmcData.Hideout.Areas.find((area) => area.type === recipe.areaType); - if (area && request.recipeId !== area.lastRecipe) - { + if (area && request.recipeId !== area.lastRecipe) { // 1 point per craft upon the end of production for alternating between 2 different crafting recipes in the same module craftingExpAmount += this.hideoutConfig.expCraftAmount; // Default is 10 } @@ -959,8 +870,7 @@ export class HideoutController // Update variable with time spent crafting item(s) // 1 point per 8 hours of crafting hoursCrafting += recipe.productionTime; - if (hoursCrafting / this.hideoutConfig.hoursForSkillCrafting >= 1) - { + if (hoursCrafting / this.hideoutConfig.hoursForSkillCrafting >= 1) { // Spent enough time crafting to get a bonus xp multipler const multiplierCrafting = Math.floor(hoursCrafting / this.hideoutConfig.hoursForSkillCrafting); craftingExpAmount += 1 * multiplierCrafting; @@ -969,8 +879,7 @@ export class HideoutController // Make sure we can fit both the craft result and tools in the stash const totalResultItems = toolsToSendToPlayer.concat(itemAndChildrenToSendToPlayer); - if (!this.inventoryHelper.canPlaceItemsInInventory(sessionID, totalResultItems)) - { + if (!this.inventoryHelper.canPlaceItemsInInventory(sessionID, totalResultItems)) { this.httpResponse.appendErrorToOutput( output, this.localisationService.getText("inventory-no_stash_space"), @@ -980,8 +889,7 @@ export class HideoutController } // Add the tools to the stash, we have to do this individually due to FiR state potentially being different - for (const toolItem of toolsToSendToPlayer) - { + for (const toolItem of toolsToSendToPlayer) { // Note: FIR state will be based on the first item's SpawnedInSession property per item group const addToolsRequest: IAddItemsDirectRequest = { itemsWithModsToAdd: [toolItem], @@ -991,8 +899,7 @@ export class HideoutController }; this.inventoryHelper.addItemsToStash(sessionID, addToolsRequest, pmcData, output); - if (output.warnings.length > 0) - { + if (output.warnings.length > 0) { return; } } @@ -1005,8 +912,7 @@ export class HideoutController callback: undefined, }; this.inventoryHelper.addItemsToStash(sessionID, addItemsRequest, pmcData, output); - if (output.warnings.length > 0) - { + if (output.warnings.length > 0) { return; } @@ -1023,13 +929,11 @@ export class HideoutController ); // Add Crafting skill to player profile - if (craftingExpAmount > 0) - { + if (craftingExpAmount > 0) { this.profileHelper.addSkillPointsToPlayer(pmcData, SkillTypes.CRAFTING, craftingExpAmount); const intellectAmountToGive = 0.5 * Math.round(craftingExpAmount / 15); - if (intellectAmountToGive > 0) - { + if (intellectAmountToGive > 0) { this.profileHelper.addSkillPointsToPlayer(pmcData, SkillTypes.INTELLECT, intellectAmountToGive); } } @@ -1043,8 +947,7 @@ export class HideoutController pmcData.Hideout.Production[prodId].sptIsContinuous = recipe.continuous; // Flag normal (non continious) crafts as complete - if (!recipe.continuous) - { + if (!recipe.continuous) { pmcData.Hideout.Production[prodId].inProgress = false; } } @@ -1058,11 +961,9 @@ export class HideoutController protected getHoursCraftingTaskConditionCounter( pmcData: IPmcData, recipe: IHideoutProduction, - ): ITaskConditionCounter - { + ): ITaskConditionCounter { let counterHoursCrafting = pmcData.TaskConditionCounters[HideoutController.nameTaskConditionCountersCrafting]; - if (!counterHoursCrafting) - { + if (!counterHoursCrafting) { // Doesn't exist, create pmcData.TaskConditionCounters[HideoutController.nameTaskConditionCountersCrafting] = { id: recipe._id, @@ -1087,25 +988,20 @@ export class HideoutController pmcData: IPmcData, request: IHideoutTakeProductionRequestData, output: IItemEventRouterResponse, - ): void - { + ): void { const ongoingProductions = Object.entries(pmcData.Hideout.Production); let prodId: string; - for (const production of ongoingProductions) - { - if (this.hideoutHelper.isProductionType(production[1])) - { + for (const production of ongoingProductions) { + if (this.hideoutHelper.isProductionType(production[1])) { // Production or ScavCase - if ((production[1] as ScavCase).RecipeId === request.recipeId) - { + if ((production[1] as ScavCase).RecipeId === request.recipeId) { prodId = production[0]; // Set to objects key break; } } } - if (prodId === undefined) - { + if (prodId === undefined) { this.logger.error( this.localisationService.getText( "hideout-unable_to_find_production_in_profile_by_recipie_id", @@ -1129,8 +1025,7 @@ export class HideoutController }; this.inventoryHelper.addItemsToStash(sessionID, addItemsRequest, pmcData, output); - if (output.warnings.length > 0) - { + if (output.warnings.length > 0) { return; } @@ -1150,8 +1045,7 @@ export class HideoutController * @param sessionId Session id * @returns IQteData array */ - public getQteList(sessionId: string): IQteData[] - { + public getQteList(sessionId: string): IQteData[] { return this.databaseService.getHideout().qte; } @@ -1167,8 +1061,7 @@ export class HideoutController pmcData: IPmcData, request: IHandleQTEEventRequestData, output: IItemEventRouterResponse, - ): void - { + ): void { // { // "Action": "HideoutQuickTimeEvent", // "results": [true, false, true, true, true, true, true, true, true, false, false, false, false, false, false], @@ -1180,14 +1073,12 @@ export class HideoutController // /client/hideout/workout (applyWorkoutChanges). pmcData.Health.Energy.Current -= 50; - if (pmcData.Health.Energy.Current < 1) - { + if (pmcData.Health.Energy.Current < 1) { pmcData.Health.Energy.Current = 1; } pmcData.Health.Hydration.Current -= 50; - if (pmcData.Health.Hydration.Current < 1) - { + if (pmcData.Health.Hydration.Current < 1) { pmcData.Health.Hydration.Current = 1; } } @@ -1199,15 +1090,13 @@ export class HideoutController * @param request shooting range score request * @returns IItemEventRouterResponse */ - public recordShootingRangePoints(sessionId: string, pmcData: IPmcData, request: IRecordShootingRangePoints): void - { + public recordShootingRangePoints(sessionId: string, pmcData: IPmcData, request: IRecordShootingRangePoints): void { const shootingRangeKey = "ShootingRangePoints"; const overallCounterItems = pmcData.Stats.Eft.OverallCounters.Items; // Find counter by key let shootingRangeHighScore = overallCounterItems.find((counter) => counter.Key.includes(shootingRangeKey)); - if (!shootingRangeHighScore) - { + if (!shootingRangeHighScore) { // Counter not found, add blank one overallCounterItems.push({ Key: [shootingRangeKey], Value: 0 }); shootingRangeHighScore = overallCounterItems.find((counter) => counter.Key.includes(shootingRangeKey)); @@ -1226,22 +1115,18 @@ export class HideoutController sessionId: string, pmcData: IPmcData, request: IHideoutImproveAreaRequestData, - ): IItemEventRouterResponse - { + ): IItemEventRouterResponse { const output = this.eventOutputHolder.getOutput(sessionId); // Create mapping of required item with corrisponding item from player inventory - const items = request.items.map((reqItem) => - { + const items = request.items.map((reqItem) => { const item = pmcData.Inventory.items.find((invItem) => invItem._id === reqItem.id); return { inventoryItem: item, requestedItem: reqItem }; }); // If it's not money, its construction / barter items - for (const item of items) - { - if (!item.inventoryItem) - { + for (const item of items) { + if (!item.inventoryItem) { this.logger.error( this.localisationService.getText("hideout-unable_to_find_item_in_inventory", item.requestedItem.id), ); @@ -1249,31 +1134,25 @@ export class HideoutController } if ( - this.paymentHelper.isMoneyTpl(item.inventoryItem._tpl) - && item.inventoryItem.upd - && item.inventoryItem.upd.StackObjectsCount - && item.inventoryItem.upd.StackObjectsCount > item.requestedItem.count - ) - { + this.paymentHelper.isMoneyTpl(item.inventoryItem._tpl) && + item.inventoryItem.upd && + item.inventoryItem.upd.StackObjectsCount && + item.inventoryItem.upd.StackObjectsCount > item.requestedItem.count + ) { item.inventoryItem.upd.StackObjectsCount -= item.requestedItem.count; - } - else - { + } else { this.inventoryHelper.removeItem(pmcData, item.inventoryItem._id, sessionId, output); } } const profileHideoutArea = pmcData.Hideout.Areas.find((x) => x.type === request.areaType); - if (!profileHideoutArea) - { + if (!profileHideoutArea) { this.logger.error(this.localisationService.getText("hideout-unable_to_find_area", request.areaType)); return this.httpResponse.appendErrorToOutput(output); } - const hideoutDbData = this.databaseService.getHideout().areas - .find((area) => area.type === request.areaType); - if (!hideoutDbData) - { + const hideoutDbData = this.databaseService.getHideout().areas.find((area) => area.type === request.areaType); + if (!hideoutDbData) { this.logger.error( this.localisationService.getText("hideout-unable_to_find_area_in_database", request.areaType), ); @@ -1284,13 +1163,11 @@ export class HideoutController const improvements = hideoutDbData.stages[profileHideoutArea.level].improvements; const timestamp = this.timeUtil.getTimestamp(); - if (!output.profileChanges[sessionId].improvements) - { + if (!output.profileChanges[sessionId].improvements) { output.profileChanges[sessionId].improvements = {}; } - for (const improvement of improvements) - { + for (const improvement of improvements) { const improvementDetails = { completed: false, improveCompleteTimestamp: timestamp + improvement.improvementTime, @@ -1313,13 +1190,11 @@ export class HideoutController sessionId: string, pmcData: IPmcData, request: IHideoutCancelProductionRequestData, - ): IItemEventRouterResponse - { + ): IItemEventRouterResponse { const output = this.eventOutputHolder.getOutput(sessionId); const craftToCancel = pmcData.Hideout.Production[request.recipeId]; - if (!craftToCancel) - { + if (!craftToCancel) { const errorMessage = `Unable to find craft ${request.recipeId} to cancel`; this.logger.error(errorMessage); @@ -1337,18 +1212,15 @@ export class HideoutController /** * Function called every x seconds as part of onUpdate event */ - public update(): void - { - for (const sessionID in this.saveServer.getProfiles()) - { + public update(): void { + for (const sessionID in this.saveServer.getProfiles()) { if ( - "Hideout" in this.saveServer.getProfile(sessionID).characters.pmc - && this.profileActivityService.activeWithinLastMinutes( + "Hideout" in this.saveServer.getProfile(sessionID).characters.pmc && + this.profileActivityService.activeWithinLastMinutes( sessionID, this.hideoutConfig.updateProfileHideoutWhenActiveWithinMinutes, ) - ) - { + ) { this.hideoutHelper.updatePlayerHideout(sessionID); } } diff --git a/project/src/controllers/InraidController.ts b/project/src/controllers/InraidController.ts index 1abe7158..803a8901 100644 --- a/project/src/controllers/InraidController.ts +++ b/project/src/controllers/InraidController.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { ApplicationContext } from "@spt/context/ApplicationContext"; import { ContextVariableType } from "@spt/context/ContextVariableType"; import { ProfileHelper } from "@spt/helpers/ProfileHelper"; @@ -11,13 +10,13 @@ import { ILogger } from "@spt/models/spt/utils/ILogger"; import { ConfigServer } from "@spt/servers/ConfigServer"; import { SaveServer } from "@spt/servers/SaveServer"; import { LocalisationService } from "@spt/services/LocalisationService"; +import { inject, injectable } from "tsyringe"; /** * Logic for handling In Raid callbacks */ @injectable() -export class InraidController -{ +export class InraidController { protected inRaidConfig: IInRaidConfig; protected botConfig: IBotConfig; @@ -28,8 +27,7 @@ export class InraidController @inject("LocalisationService") protected localisationService: LocalisationService, @inject("ApplicationContext") protected applicationContext: ApplicationContext, @inject("ConfigServer") protected configServer: ConfigServer, - ) - { + ) { this.inRaidConfig = this.configServer.getConfig(ConfigTypes.IN_RAID); this.botConfig = this.configServer.getConfig(ConfigTypes.BOT); } @@ -39,18 +37,15 @@ export class InraidController * @param sessionID Session id * @param info Register player request */ - public addPlayer(sessionID: string, info: IRegisterPlayerRequestData): void - { + public addPlayer(sessionID: string, info: IRegisterPlayerRequestData): void { this.applicationContext.addValue(ContextVariableType.REGISTER_PLAYER_REQUEST, info); const profile = this.saveServer.getProfile(sessionID); - if (!profile) - { + if (!profile) { this.logger.error(this.localisationService.getText("inraid-no_profile_found", sessionID)); return; } - if (!profile.inraid) - { + if (!profile.inraid) { profile.inraid = { character: sessionID, location: info.locationId }; return; @@ -66,8 +61,7 @@ export class InraidController * @param offraidData post-raid request data * @param sessionID Session id */ - public savePostRaidProfileForScav(offraidData: IScavSaveRequestData, sessionID: string): void - { + public savePostRaidProfileForScav(offraidData: IScavSaveRequestData, sessionID: string): void { const serverScavProfile = this.profileHelper.getScavProfile(sessionID); serverScavProfile.Inventory.items = offraidData.profile.Inventory.items; @@ -77,18 +71,15 @@ export class InraidController * Get the inraid config from configs/inraid.json * @returns InRaid Config */ - public getInraidConfig(): IInRaidConfig - { + public getInraidConfig(): IInRaidConfig { return this.inRaidConfig; } - public getTraitorScavHostileChance(url: string, sessionID: string): number - { + public getTraitorScavHostileChance(url: string, sessionID: string): number { return this.inRaidConfig.playerScavHostileChancePercent; } - public getBossConvertSettings(url: string, sessionId: string): string[] - { + public getBossConvertSettings(url: string, sessionId: string): string[] { return Object.keys(this.botConfig.assaultToBossConversion.bossesToConvertToWeights); } } diff --git a/project/src/controllers/InsuranceController.ts b/project/src/controllers/InsuranceController.ts index 169f31ef..8f976c44 100644 --- a/project/src/controllers/InsuranceController.ts +++ b/project/src/controllers/InsuranceController.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { DialogueHelper } from "@spt/helpers/DialogueHelper"; import { ItemHelper } from "@spt/helpers/ItemHelper"; import { ProfileHelper } from "@spt/helpers/ProfileHelper"; @@ -26,15 +25,15 @@ import { LocalisationService } from "@spt/services/LocalisationService"; import { MailSendService } from "@spt/services/MailSendService"; import { PaymentService } from "@spt/services/PaymentService"; import { RagfairPriceService } from "@spt/services/RagfairPriceService"; -import { ICloner } from "@spt/utils/cloners/ICloner"; import { HashUtil } from "@spt/utils/HashUtil"; import { MathUtil } from "@spt/utils/MathUtil"; import { ProbabilityObject, ProbabilityObjectArray, RandomUtil } from "@spt/utils/RandomUtil"; import { TimeUtil } from "@spt/utils/TimeUtil"; +import { ICloner } from "@spt/utils/cloners/ICloner"; +import { inject, injectable } from "tsyringe"; @injectable() -export class InsuranceController -{ +export class InsuranceController { protected insuranceConfig: IInsuranceConfig; constructor( @@ -58,8 +57,7 @@ export class InsuranceController @inject("LocalisationService") protected localisationService: LocalisationService, @inject("ConfigServer") protected configServer: ConfigServer, @inject("PrimaryCloner") protected cloner: ICloner, - ) - { + ) { this.insuranceConfig = this.configServer.getConfig(ConfigTypes.INSURANCE); } @@ -68,11 +66,9 @@ export class InsuranceController * * @returns void */ - public processReturn(): void - { + public processReturn(): void { // Process each installed profile. - for (const sessionID in this.saveServer.getProfiles()) - { + for (const sessionID in this.saveServer.getProfiles()) { this.processReturnByProfile(sessionID); } } @@ -82,14 +78,12 @@ export class InsuranceController * * @returns void */ - public processReturnByProfile(sessionID: string): void - { + public processReturnByProfile(sessionID: string): void { // Filter out items that don't need to be processed yet. const insuranceDetails = this.filterInsuredItems(sessionID); // Skip profile if no insured items to process - if (insuranceDetails.length === 0) - { + if (insuranceDetails.length === 0) { return; } @@ -103,14 +97,12 @@ export class InsuranceController * @param time The time to check ready status against. Current time by default. * @returns All insured items that are ready to be processed. */ - protected filterInsuredItems(sessionID: string, time?: number): Insurance[] - { + protected filterInsuredItems(sessionID: string, time?: number): Insurance[] { // Use the current time by default. const insuranceTime = time || this.timeUtil.getTimestamp(); const profileInsuranceDetails = this.saveServer.getProfile(sessionID).insurance; - if (profileInsuranceDetails.length > 0) - { + if (profileInsuranceDetails.length > 0) { this.logger.debug(`Found ${profileInsuranceDetails.length} insurance packages in profile ${sessionID}`); } @@ -124,8 +116,7 @@ export class InsuranceController * @param sessionID The session ID that should receive the processed items. * @returns void */ - protected processInsuredItems(insuranceDetails: Insurance[], sessionID: string): void - { + protected processInsuredItems(insuranceDetails: Insurance[], sessionID: string): void { this.logger.debug( `Processing ${insuranceDetails.length} insurance packages, which includes a total of ${this.countAllInsuranceItems( insuranceDetails, @@ -136,8 +127,7 @@ export class InsuranceController const rootItemParentID = this.insuranceService.getRootItemParentID(sessionID); // Iterate over each of the insurance packages. - for (const insured of insuranceDetails) - { + for (const insured of insuranceDetails) { // Find items that should be deleted from the insured items. const itemsToDelete = this.findItemsToDelete(rootItemParentID, insured); @@ -160,8 +150,7 @@ export class InsuranceController * @param insurance * @returns */ - protected countAllInsuranceItems(insurance: Insurance[]): number - { + protected countAllInsuranceItems(insurance: Insurance[]): number { return this.mathUtil.arraySum(insurance.map((ins) => ins.items.length)); } @@ -172,15 +161,14 @@ export class InsuranceController * @param index The array index of the insurance package to remove. * @returns void */ - protected removeInsurancePackageFromProfile(sessionID: string, insPackage: Insurance): void - { + protected removeInsurancePackageFromProfile(sessionID: string, insPackage: Insurance): void { const profile = this.saveServer.getProfile(sessionID); profile.insurance = profile.insurance.filter( (insurance) => - insurance.traderId !== insPackage.traderId - || insurance.systemData.date !== insPackage.systemData.date - || insurance.systemData.time !== insPackage.systemData.time - || insurance.systemData.location !== insPackage.systemData.location, + insurance.traderId !== insPackage.traderId || + insurance.systemData.date !== insPackage.systemData.date || + insurance.systemData.time !== insPackage.systemData.time || + insurance.systemData.location !== insPackage.systemData.location, ); this.logger.debug(`Removed processed insurance package. Remaining packages: ${profile.insurance.length}`); @@ -193,8 +181,7 @@ export class InsuranceController * @param insured - The insurance object containing the items to evaluate for deletion. * @returns A Set containing the IDs of items that should be deleted. */ - protected findItemsToDelete(rootItemParentID: string, insured: Insurance): Set - { + protected findItemsToDelete(rootItemParentID: string, insured: Insurance): Set { const toDelete = new Set(); // Populate a Map object of items for quick lookup by their ID and use it to populate a Map of main-parent items @@ -208,14 +195,12 @@ export class InsuranceController ); // Process all items that are not attached, attachments; those are handled separately, by value. - if (hasRegularItems) - { + if (hasRegularItems) { this.processRegularItems(insured, toDelete, parentAttachmentsMap); } // Process attached, attachments, by value, only if there are any. - if (parentAttachmentsMap.size > 0) - { + if (parentAttachmentsMap.size > 0) { // Remove attachments that can not be moddable in-raid from the parentAttachmentsMap. We only want to // process moddable attachments from here on out. parentAttachmentsMap = this.removeNonModdableAttachments(parentAttachmentsMap, itemsMap); @@ -224,8 +209,7 @@ export class InsuranceController } // Log the number of items marked for deletion, if any - if (toDelete.size) - { + if (toDelete.size) { this.logger.debug(`Marked ${toDelete.size} items for deletion from insurance.`); } @@ -246,65 +230,58 @@ export class InsuranceController rootItemParentID: string, insured: Insurance, itemsMap: Map, - ): Map - { + ): Map { const mainParentToAttachmentsMap = new Map(); - for (const insuredItem of insured.items) - { + for (const insuredItem of insured.items) { // Use the parent ID from the item to get the parent item. const parentItem = insured.items.find((item) => item._id === insuredItem.parentId); // The parent (not the hideout) could not be found. Skip and warn. - if (!parentItem && insuredItem.parentId !== rootItemParentID) - { - this.logger.warning(this.localisationService - .getText("insurance-unable_to_find_parent_of_item", - { - insuredItemId: insuredItem._id, - insuredItemTpl: insuredItem._tpl, - parentId: insuredItem.parentId, - })); + if (!parentItem && insuredItem.parentId !== rootItemParentID) { + this.logger.warning( + this.localisationService.getText("insurance-unable_to_find_parent_of_item", { + insuredItemId: insuredItem._id, + insuredItemTpl: insuredItem._tpl, + parentId: insuredItem.parentId, + }), + ); continue; } // Check if this is an attachment currently attached to its parent. - if (this.itemHelper.isAttachmentAttached(insuredItem)) - { + if (this.itemHelper.isAttachmentAttached(insuredItem)) { // Make sure the template for the item exists. - if (!this.itemHelper.getItem(insuredItem._tpl)[0]) - { - this.logger.warning(this.localisationService.getText("insurance-unable_to_find_attachment_in_db", - { + if (!this.itemHelper.getItem(insuredItem._tpl)[0]) { + this.logger.warning( + this.localisationService.getText("insurance-unable_to_find_attachment_in_db", { insuredItemId: insuredItem._id, insuredItemTpl: insuredItem._tpl, - })); + }), + ); continue; } // Get the main parent of this attachment. (e.g., The gun that this suppressor is attached to.) const mainParent = this.itemHelper.getAttachmentMainParent(insuredItem._id, itemsMap); - if (!mainParent) - { + if (!mainParent) { // Odd. The parent couldn't be found. Skip this attachment and warn. - this.logger.warning(this.localisationService.getText("insurance-unable_to_find_main_parent_for_attachment", - { + this.logger.warning( + this.localisationService.getText("insurance-unable_to_find_main_parent_for_attachment", { insuredItemId: insuredItem._id, insuredItemTpl: insuredItem._tpl, parentId: insuredItem.parentId, - })); + }), + ); continue; } // Update (or add to) the main-parent to attachments map. - if (mainParentToAttachmentsMap.has(mainParent._id)) - { + if (mainParentToAttachmentsMap.has(mainParent._id)) { mainParentToAttachmentsMap.get(mainParent._id).push(insuredItem); - } - else - { + } else { mainParentToAttachmentsMap.set(mainParent._id, [insuredItem]); } } @@ -323,40 +300,33 @@ export class InsuranceController protected removeNonModdableAttachments( parentAttachmentsMap: Map, itemsMap: Map, - ): Map - { + ): Map { const updatedMap = new Map(); - for (const [parentId, attachmentItems] of parentAttachmentsMap) - { + for (const [parentId, attachmentItems] of parentAttachmentsMap) { const parentItem = itemsMap.get(parentId); const moddableAttachments: Item[] = []; - for (const attachment of attachmentItems) - { + for (const attachment of attachmentItems) { // By default, assume the parent of the current attachment is the main-parent included in the map. let attachmentParentItem = parentItem; // If the attachment includes a parentId, use it to find its direct parent item, even if it's another // attachment on the main-parent. For example, if the attachment is a stock, we need to check to see if // it's moddable in the upper receiver (attachment/parent), which is attached to the gun (main-parent). - if (attachment.parentId) - { + if (attachment.parentId) { const directParentItem = itemsMap.get(attachment.parentId); - if (directParentItem) - { + if (directParentItem) { attachmentParentItem = directParentItem; } } - if (this.itemHelper.isRaidModdable(attachment, attachmentParentItem)) - { + if (this.itemHelper.isRaidModdable(attachment, attachmentParentItem)) { moddableAttachments.push(attachment); } } // If any moddable attachments remain, add them to the updated map. - if (moddableAttachments.length > 0) - { + if (moddableAttachments.length > 0) { updatedMap.set(parentId, moddableAttachments); } } @@ -378,40 +348,32 @@ export class InsuranceController insured: Insurance, toDelete: Set, parentAttachmentsMap: Map, - ): void - { - for (const insuredItem of insured.items) - { + ): void { + for (const insuredItem of insured.items) { // Skip if the item is an attachment. These are handled separately. - if (this.itemHelper.isAttachmentAttached(insuredItem)) - { + if (this.itemHelper.isAttachmentAttached(insuredItem)) { continue; } // Roll for item deletion const itemRoll = this.rollForDelete(insured.traderId, insuredItem); - if (itemRoll) - { + if (itemRoll) { // Check to see if this item is a parent in the parentAttachmentsMap. If so, do a look-up for *all* of // its children and mark them for deletion as well. Additionally remove the parent (and its children) // from the parentAttachmentsMap so that it's children are not rolled for later in the process. - if (parentAttachmentsMap.has(insuredItem._id)) - { + if (parentAttachmentsMap.has(insuredItem._id)) { // This call will also return the parent item itself, queueing it for deletion as well. const itemAndChildren = this.itemHelper.findAndReturnChildrenAsItems( insured.items, insuredItem._id, ); - for (const item of itemAndChildren) - { + for (const item of itemAndChildren) { toDelete.add(item._id); } // Remove the parent (and its children) from the parentAttachmentsMap. parentAttachmentsMap.delete(insuredItem._id); - } - else - { + } else { // This item doesn't have any children. Simply mark it for deletion. toDelete.add(insuredItem._id); } @@ -432,14 +394,11 @@ export class InsuranceController itemsMap: Map, traderId: string, toDelete: Set, - ): void - { - for (const [parentId, attachmentItems] of mainParentToAttachmentsMap) - { + ): void { + for (const [parentId, attachmentItems] of mainParentToAttachmentsMap) { // Skip processing if parentId is already marked for deletion, as all attachments for that parent will // already be marked for deletion as well. - if (toDelete.has(parentId)) - { + if (toDelete.has(parentId)) { continue; } @@ -464,8 +423,7 @@ export class InsuranceController * @param toDelete The array that accumulates the IDs of the items to be deleted. * @returns void */ - protected processAttachmentByParent(attachments: Item[], traderId: string, toDelete: Set): void - { + protected processAttachmentByParent(attachments: Item[], traderId: string, toDelete: Set): void { // Create dict of item ids + their flea/handbook price (highest is chosen) const weightedAttachmentByPrice = this.weightAttachmentsByPrice(attachments); @@ -474,8 +432,7 @@ export class InsuranceController // Create prob array and add all attachments with rouble price as the weight const attachmentsProbabilityArray = new ProbabilityObjectArray(this.mathUtil, this.cloner); - for (const attachmentTpl of Object.keys(weightedAttachmentByPrice)) - { + for (const attachmentTpl of Object.keys(weightedAttachmentByPrice)) { attachmentsProbabilityArray.push( new ProbabilityObject(attachmentTpl, weightedAttachmentByPrice[attachmentTpl]), ); @@ -483,8 +440,7 @@ export class InsuranceController // Draw x attachments from weighted array to remove from parent, remove from pool after being picked const attachmentIdsToRemove = attachmentsProbabilityArray.draw(countOfAttachmentsToRemove, false); - for (const attachmentId of attachmentIdsToRemove) - { + for (const attachmentId of attachmentIdsToRemove) { toDelete.add(attachmentId); } @@ -497,11 +453,9 @@ export class InsuranceController attachmentIdsToRemove: string[], attachments: Item[], attachmentPrices: Record, - ): void - { + ): void { let index = 1; - for (const attachmentId of attachmentIdsToRemove) - { + for (const attachmentId of attachmentIdsToRemove) { this.logger.debug( `Attachment ${index} Id: ${attachmentId} Tpl: ${ attachments.find((x) => x._id === attachmentId)?._tpl @@ -511,16 +465,13 @@ export class InsuranceController } } - protected weightAttachmentsByPrice(attachments: Item[]): Record - { + protected weightAttachmentsByPrice(attachments: Item[]): Record { const result: Record = {}; // Get a dictionary of item tpls + their rouble price - for (const attachment of attachments) - { + for (const attachment of attachments) { const price = this.ragfairPriceService.getDynamicItemPrice(attachment._tpl, Money.ROUBLES); - if (price) - { + if (price) { result[attachment._id] = Math.round(price); } } @@ -536,25 +487,20 @@ export class InsuranceController * @param traderId Trader attachment insured against * @returns Attachment count to remove */ - protected getAttachmentCountToRemove(weightedAttachmentByPrice: Record, traderId: string): number - { + protected getAttachmentCountToRemove(weightedAttachmentByPrice: Record, traderId: string): number { let removeCount = 0; - if (this.randomUtil.getChance100(this.insuranceConfig.chanceNoAttachmentsTakenPercent)) - { + if (this.randomUtil.getChance100(this.insuranceConfig.chanceNoAttachmentsTakenPercent)) { return removeCount; } - for (const attachmentId of Object.keys(weightedAttachmentByPrice)) - { + for (const attachmentId of Object.keys(weightedAttachmentByPrice)) { // Below min price to be taken, skip - if (weightedAttachmentByPrice[attachmentId] < this.insuranceConfig.minAttachmentRoublePriceToBeTaken) - { + if (weightedAttachmentByPrice[attachmentId] < this.insuranceConfig.minAttachmentRoublePriceToBeTaken) { continue; } - if (this.rollForDelete(traderId)) - { + if (this.rollForDelete(traderId)) { removeCount++; } } @@ -569,8 +515,7 @@ export class InsuranceController * @param toDelete The items that should be deleted. * @returns void */ - protected removeItemsFromInsurance(insured: Insurance, toDelete: Set): void - { + protected removeItemsFromInsurance(insured: Insurance, toDelete: Set): void { insured.items = insured.items.filter((item) => !toDelete.has(item._id)); } @@ -581,8 +526,7 @@ export class InsuranceController * @param insurance The context of insurance to use. * @returns void */ - protected sendMail(sessionID: string, insurance: Insurance): void - { + protected sendMail(sessionID: string, insurance: Insurance): void { const labsId = "laboratory"; // After all of the item filtering that we've done, if there are no items remaining, the insurance has // successfully "failed" to return anything and an appropriate message should be sent to the player. @@ -590,21 +534,17 @@ export class InsuranceController // Map is labs + insurance is disabled in base.json if ( - insurance.systemData?.location?.toLowerCase() === labsId - && !(this.databaseService.getLocation(labsId).base.Insurance) - ) - { + insurance.systemData?.location?.toLowerCase() === labsId && + !this.databaseService.getLocation(labsId).base.Insurance + ) { // Trader has labs-specific messages // Wipe out returnable items - if (traderDialogMessages.insuranceFailedLabs?.length > 0) - { + if (traderDialogMessages.insuranceFailedLabs?.length > 0) { const insuranceFailedLabTemplates = traderDialogMessages.insuranceFailedLabs; insurance.messageTemplateId = this.randomUtil.getArrayValue(insuranceFailedLabTemplates); insurance.items = []; } - } - else if (insurance.items.length === 0) - { + } else if (insurance.items.length === 0) { // Not labs and no items to return const insuranceFailedTemplates = traderDialogMessages.insuranceFailed; insurance.messageTemplateId = this.randomUtil.getArrayValue(insuranceFailedTemplates); @@ -630,11 +570,9 @@ export class InsuranceController * @param insuredItem Optional. The item to roll for. Only used for logging. * @returns true if the insured item should be removed from inventory, false otherwise, or undefined on error. */ - protected rollForDelete(traderId: string, insuredItem?: Item): boolean | undefined - { + protected rollForDelete(traderId: string, insuredItem?: Item): boolean | undefined { const trader = this.traderHelper.getTraderById(traderId); - if (!trader) - { + if (!trader) { return undefined; } @@ -664,26 +602,25 @@ export class InsuranceController * @param sessionID Session id * @returns IItemEventRouterResponse object to send to client */ - public insure(pmcData: IPmcData, body: IInsureRequestData, sessionID: string): IItemEventRouterResponse - { + public insure(pmcData: IPmcData, body: IInsureRequestData, sessionID: string): IItemEventRouterResponse { const output = this.eventOutputHolder.getOutput(sessionID); const itemsToInsureCount = body.items.length; const itemsToPay = []; const inventoryItemsHash = {}; // Create hash of player inventory items (keyed by item id) - for (const item of pmcData.Inventory.items) - { + for (const item of pmcData.Inventory.items) { inventoryItemsHash[item._id] = item; } // Get price of all items being insured - for (const key of body.items) - { + for (const key of body.items) { itemsToPay.push({ id: Money.ROUBLES, // TODO: update to handle different currencies count: this.insuranceService.getRoublePriceToInsureItemWithTrader( - pmcData, inventoryItemsHash[key], - body.tid), + pmcData, + inventoryItemsHash[key], + body.tid, + ), }); } @@ -699,14 +636,12 @@ export class InsuranceController // pay for the item insurance this.paymentService.payMoney(pmcData, options, sessionID, output); - if (output.warnings.length > 0) - { + if (output.warnings.length > 0) { return output; } // add items to InsuredItems list once money has been paid - for (const key of body.items) - { + for (const key of body.items) { pmcData.InsuredItems.push({ tid: body.tid, itemId: inventoryItemsHash[key]._id }); } @@ -723,33 +658,30 @@ export class InsuranceController * @param sessionID session id * @returns IGetInsuranceCostResponseData object to send to client */ - public cost(request: IGetInsuranceCostRequestData, sessionID: string): IGetInsuranceCostResponseData - { + public cost(request: IGetInsuranceCostRequestData, sessionID: string): IGetInsuranceCostResponseData { const response: IGetInsuranceCostResponseData = {}; const pmcData = this.profileHelper.getPmcProfile(sessionID); const inventoryItemsHash: Record = {}; - for (const item of pmcData.Inventory.items) - { + for (const item of pmcData.Inventory.items) { inventoryItemsHash[item._id] = item; } // Loop over each trader in request - for (const trader of request.traders) - { + for (const trader of request.traders) { const items: Record = {}; - for (const itemId of request.items) - { + for (const itemId of request.items) { // Ensure hash has item in it - if (!inventoryItemsHash[itemId]) - { + if (!inventoryItemsHash[itemId]) { this.logger.debug(`Item with id: ${itemId} missing from player inventory, skipping`); continue; } items[inventoryItemsHash[itemId]._tpl] = this.insuranceService.getRoublePriceToInsureItemWithTrader( - pmcData, inventoryItemsHash[itemId], - trader); + pmcData, + inventoryItemsHash[itemId], + trader, + ); } response[trader] = items; @@ -760,8 +692,7 @@ export class InsuranceController } // Represents an insurance item that has had it's common locale-name and value added to it. -interface EnrichedItem extends Item -{ - name: string - dynamicPrice: number +interface EnrichedItem extends Item { + name: string; + dynamicPrice: number; } diff --git a/project/src/controllers/InventoryController.ts b/project/src/controllers/InventoryController.ts index 7fdf5ace..dfa53bcc 100644 --- a/project/src/controllers/InventoryController.ts +++ b/project/src/controllers/InventoryController.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { LootGenerator } from "@spt/generators/LootGenerator"; import { HideoutHelper } from "@spt/helpers/HideoutHelper"; import { InventoryHelper } from "@spt/helpers/InventoryHelper"; @@ -44,14 +43,14 @@ import { LocalisationService } from "@spt/services/LocalisationService"; import { MapMarkerService } from "@spt/services/MapMarkerService"; import { PlayerService } from "@spt/services/PlayerService"; import { RagfairOfferService } from "@spt/services/RagfairOfferService"; -import { ICloner } from "@spt/utils/cloners/ICloner"; import { HashUtil } from "@spt/utils/HashUtil"; import { HttpResponseUtil } from "@spt/utils/HttpResponseUtil"; import { RandomUtil } from "@spt/utils/RandomUtil"; +import { ICloner } from "@spt/utils/cloners/ICloner"; +import { inject, injectable } from "tsyringe"; @injectable() -export class InventoryController -{ +export class InventoryController { constructor( @inject("PrimaryLogger") protected logger: ILogger, @inject("HashUtil") protected hashUtil: HashUtil, @@ -74,8 +73,7 @@ export class InventoryController @inject("EventOutputHolder") protected eventOutputHolder: EventOutputHolder, @inject("HttpResponseUtil") protected httpResponseUtil: HttpResponseUtil, @inject("PrimaryCloner") protected cloner: ICloner, - ) - {} + ) {} /** * Move Item @@ -92,28 +90,23 @@ export class InventoryController moveRequest: IInventoryMoveRequestData, sessionID: string, output: IItemEventRouterResponse, - ): void - { - if (output.warnings.length > 0) - { + ): void { + if (output.warnings.length > 0) { return; } // Changes made to result apply to character inventory const ownerInventoryItems = this.inventoryHelper.getOwnerInventoryItems(moveRequest, sessionID); - if (ownerInventoryItems.sameInventory) - { + if (ownerInventoryItems.sameInventory) { // Dont move items from trader to profile, this can happen when editing a traders preset weapons - if (moveRequest.fromOwner?.type === "Trader" && !ownerInventoryItems.isMail) - { + if (moveRequest.fromOwner?.type === "Trader" && !ownerInventoryItems.isMail) { this.appendTraderExploitErrorResponse(output); return; } // Check for item in inventory before allowing internal transfer const originalItemLocation = ownerInventoryItems.from.find((item) => item._id === moveRequest.item); - if (!originalItemLocation) - { + if (!originalItemLocation) { // Internal item move but item never existed, possible dupe glitch this.appendTraderExploitErrorResponse(output); return; @@ -122,20 +115,16 @@ export class InventoryController const originalLocationSlotId = originalItemLocation?.slotId; const moveResult = this.inventoryHelper.moveItemInternal(pmcData, ownerInventoryItems.from, moveRequest); - if (!moveResult.success) - { + if (!moveResult.success) { this.httpResponseUtil.appendErrorToOutput(output, moveResult.errorMessage); return; } // Item is moving into or out of place of fame dogtag slot - if (moveRequest.to.container.startsWith("dogtag") || originalLocationSlotId?.startsWith("dogtag")) - { + if (moveRequest.to.container.startsWith("dogtag") || originalLocationSlotId?.startsWith("dogtag")) { this.hideoutHelper.applyPlaceOfFameDogtagBonus(pmcData); } - } - else - { + } else { this.inventoryHelper.moveItemToProfile(ownerInventoryItems.from, ownerInventoryItems.to, moveRequest); } } @@ -145,8 +134,7 @@ export class InventoryController * @param output Item event router response * @returns Item event router response */ - protected appendTraderExploitErrorResponse(output: IItemEventRouterResponse): void - { + protected appendTraderExploitErrorResponse(output: IItemEventRouterResponse): void { this.httpResponseUtil.appendErrorToOutput( output, this.localisationService.getText("inventory-edit_trader_item"), @@ -164,17 +152,15 @@ export class InventoryController request: IInventoryRemoveRequestData, sessionID: string, output: IItemEventRouterResponse, - ): void - { - if (request.fromOwner?.type === "Mail") - { + ): void { + if (request.fromOwner?.type === "Mail") { this.inventoryHelper.removeItemAndChildrenFromMailRewards(sessionID, request, output); return; } - const profileToRemoveItemFrom - = !request.fromOwner || request.fromOwner.id === pmcData._id + const profileToRemoveItemFrom = + !request.fromOwner || request.fromOwner.id === pmcData._id ? pmcData : this.profileHelper.getFullProfile(sessionID).characters.scav; @@ -195,22 +181,19 @@ export class InventoryController request: IInventorySplitRequestData, sessionID: string, output: IItemEventRouterResponse, - ): IItemEventRouterResponse - { + ): IItemEventRouterResponse { // Changes made to result apply to character inventory const inventoryItems = this.inventoryHelper.getOwnerInventoryItems(request, sessionID); // Handle cartridge edge-case - if (!request.container.location && request.container.container === "cartridges") - { + if (!request.container.location && request.container.container === "cartridges") { const matchingItems = inventoryItems.to.filter((x) => x.parentId === request.container.id); request.container.location = matchingItems.length; // Wrong location for first cartridge } // The item being merged has three possible sources: pmc, scav or mail, getOwnerInventoryItems() handles getting correct one const itemToSplit = inventoryItems.from.find((x) => x._id === request.splitItem); - if (!itemToSplit) - { + if (!itemToSplit) { const errorMessage = `Unable to split stack as source item: ${request.splitItem} cannot be found`; this.logger.error(errorMessage); @@ -258,15 +241,13 @@ export class InventoryController body: IInventoryMergeRequestData, sessionID: string, output: IItemEventRouterResponse, - ): IItemEventRouterResponse - { + ): IItemEventRouterResponse { // Changes made to result apply to character inventory const inventoryItems = this.inventoryHelper.getOwnerInventoryItems(body, sessionID); // Get source item (can be from player or trader or mail) const sourceItem = inventoryItems.from.find((x) => x._id === body.item); - if (!sourceItem) - { + if (!sourceItem) { const errorMessage = `Unable to merge stacks as source item: ${body.with} cannot be found`; this.logger.error(errorMessage); @@ -277,8 +258,7 @@ export class InventoryController // Get item being merged into const destinationItem = inventoryItems.to.find((x) => x._id === body.with); - if (!destinationItem) - { + if (!destinationItem) { const errorMessage = `Unable to merge stacks as destination item: ${body.with} cannot be found`; this.logger.error(errorMessage); @@ -287,25 +267,20 @@ export class InventoryController return output; } - if (!destinationItem.upd?.StackObjectsCount) - { + if (!destinationItem.upd?.StackObjectsCount) { // No stackcount on destination, add one destinationItem.upd = { StackObjectsCount: 1 }; } - if (!sourceItem.upd) - { + if (!sourceItem.upd) { sourceItem.upd = { StackObjectsCount: 1 }; - } - else if (!sourceItem.upd.StackObjectsCount) - { + } else if (!sourceItem.upd.StackObjectsCount) { // Items pulled out of raid can have no stackcount if the stack should be 1 sourceItem.upd.StackObjectsCount = 1; } // Remove FiR status from destination stack when source stack has no FiR but destination does - if (!sourceItem.upd.SpawnedInSession && destinationItem.upd.SpawnedInSession) - { + if (!sourceItem.upd.SpawnedInSession && destinationItem.upd.SpawnedInSession) { delete destinationItem.upd.SpawnedInSession; } @@ -313,8 +288,7 @@ export class InventoryController output.profileChanges[sessionID].items.del.push({ _id: sourceItem._id }); // Inform client source item being deleted const indexOfItemToRemove = inventoryItems.from.findIndex((x) => x._id === sourceItem._id); - if (indexOfItemToRemove === -1) - { + if (indexOfItemToRemove === -1) { const errorMessage = `Unable to find item: ${sourceItem._id} to remove from sender inventory`; this.logger.error(errorMessage); @@ -342,14 +316,12 @@ export class InventoryController body: IInventoryTransferRequestData, sessionID: string, output: IItemEventRouterResponse, - ): IItemEventRouterResponse - { + ): IItemEventRouterResponse { const inventoryItems = this.inventoryHelper.getOwnerInventoryItems(body, sessionID); const sourceItem = inventoryItems.from.find((item) => item._id === body.item); const destinationItem = inventoryItems.to.find((item) => item._id === body.with); - if (!sourceItem) - { + if (!sourceItem) { const errorMessage = `Unable to transfer stack, cannot find source: ${body.item}`; this.logger.error(errorMessage); @@ -358,8 +330,7 @@ export class InventoryController return output; } - if (!destinationItem) - { + if (!destinationItem) { const errorMessage = `Unable to transfer stack, cannot find destination: ${body.with} `; this.logger.error(errorMessage); @@ -368,25 +339,20 @@ export class InventoryController return output; } - if (!sourceItem.upd) - { + if (!sourceItem.upd) { sourceItem.upd = { StackObjectsCount: 1 }; } const sourceStackCount = sourceItem.upd.StackObjectsCount; - if (sourceStackCount > body.count) - { + if (sourceStackCount > body.count) { // Source items stack count greater than new desired count sourceItem.upd.StackObjectsCount = sourceStackCount - body.count; - } - else - { + } else { // Moving a full stack onto a smaller stack sourceItem.upd.StackObjectsCount = sourceStackCount - 1; } - if (!destinationItem.upd) - { + if (!destinationItem.upd) { destinationItem.upd = { StackObjectsCount: 1 }; } const destinationStackCount = destinationItem.upd.StackObjectsCount; @@ -404,25 +370,31 @@ export class InventoryController pmcData: IPmcData, request: IInventorySwapRequestData, sessionID: string, - ): IItemEventRouterResponse - { + ): IItemEventRouterResponse { // During post-raid scav transfer, the swap may be in the scav inventory let playerData = pmcData; - if (request.fromOwner?.type === "Profile" && request.fromOwner.id !== playerData._id) - { + if (request.fromOwner?.type === "Profile" && request.fromOwner.id !== playerData._id) { playerData = this.profileHelper.getScavProfile(sessionID); } const itemOne = playerData.Inventory.items.find((x) => x._id === request.item); - if (!itemOne) - { - this.logger.error(this.localisationService.getText("inventory-unable_to_find_item_to_swap", { item1Id: request.item, item2Id: request.item2 })); + if (!itemOne) { + this.logger.error( + this.localisationService.getText("inventory-unable_to_find_item_to_swap", { + item1Id: request.item, + item2Id: request.item2, + }), + ); } const itemTwo = playerData.Inventory.items.find((x) => x._id === request.item2); - if (!itemTwo) - { - this.logger.error(this.localisationService.getText("inventory-unable_to_find_item_to_swap", { item1Id: request.item2, item2Id: request.item })); + if (!itemTwo) { + this.logger.error( + this.localisationService.getText("inventory-unable_to_find_item_to_swap", { + item1Id: request.item2, + item2Id: request.item, + }), + ); } // to.id is the parentid @@ -432,23 +404,17 @@ export class InventoryController itemOne.slotId = request.to.container; // Request object has location data, add it in, otherwise remove existing location from object - if (request.to.location) - { + if (request.to.location) { itemOne.location = request.to.location; - } - else - { + } else { delete itemOne.location; } itemTwo.parentId = request.to2.id; itemTwo.slotId = request.to2.container; - if (request.to2.location) - { + if (request.to2.location) { itemTwo.location = request.to2.location; - } - else - { + } else { delete itemTwo.location; } @@ -463,22 +429,21 @@ export class InventoryController pmcData: IPmcData, request: IInventoryFoldRequestData, sessionID: string, - ): IItemEventRouterResponse - { + ): IItemEventRouterResponse { // May need to reassign to scav profile let playerData = pmcData; // We may be folding data on scav profile, get that profile instead - if (request.fromOwner?.type === "Profile" && request.fromOwner.id !== playerData._id) - { + if (request.fromOwner?.type === "Profile" && request.fromOwner.id !== playerData._id) { playerData = this.profileHelper.getScavProfile(sessionID); } const itemToFold = playerData.Inventory.items.find((item) => item?._id === request.item); - if (!itemToFold) - { + if (!itemToFold) { // Item not found - this.logger.warning(this.localisationService.getText("inventory-unable_to_fold_item_not_found_in_inventory", request.item)); + this.logger.warning( + this.localisationService.getText("inventory-unable_to_fold_item_not_found_in_inventory", request.item), + ); return { warnings: [], profileChanges: {} }; } @@ -502,20 +467,17 @@ export class InventoryController pmcData: IPmcData, body: IInventoryToggleRequestData, sessionID: string, - ): IItemEventRouterResponse - { + ): IItemEventRouterResponse { // May need to reassign to scav profile let playerData = pmcData; // Fix for toggling items while on they're in the Scav inventory - if (body.fromOwner?.type === "Profile" && body.fromOwner.id !== playerData._id) - { + if (body.fromOwner?.type === "Profile" && body.fromOwner.id !== playerData._id) { playerData = this.profileHelper.getScavProfile(sessionID); } const itemToToggle = playerData.Inventory.items.find((x) => x._id === body.item); - if (itemToToggle) - { + if (itemToToggle) { this.itemHelper.addUpdObjectToItem( itemToToggle, this.localisationService.getText("inventory-item_to_toggle_missing_upd", itemToToggle._id), @@ -538,16 +500,13 @@ export class InventoryController * @param sessionID session id * @returns client response object */ - public tagItem(pmcData: IPmcData, body: IInventoryTagRequestData, sessionID: string): IItemEventRouterResponse - { + public tagItem(pmcData: IPmcData, body: IInventoryTagRequestData, sessionID: string): IItemEventRouterResponse { const itemToTag = pmcData.Inventory.items.find((item) => item._id === body.item); - if (!itemToTag) - { + if (!itemToTag) { return { warnings: [], profileChanges: {} }; } - if (!itemToTag.upd) - { + if (!itemToTag.upd) { itemToTag.upd = {}; } @@ -564,14 +523,11 @@ export class InventoryController * @param sessionID Session id * @returns IItemEventRouterResponse */ - public bindItem(pmcData: IPmcData, bindRequest: IInventoryBindRequestData, sessionID: string): void - { + public bindItem(pmcData: IPmcData, bindRequest: IInventoryBindRequestData, sessionID: string): void { // TODO - replace with single .find() call - for (const index in pmcData.Inventory.fastPanel) - { + for (const index in pmcData.Inventory.fastPanel) { // Find item with existing item in it and remove existing binding, you cant have same item bound to more than 1 slot - if (pmcData.Inventory.fastPanel[index] === bindRequest.item) - { + if (pmcData.Inventory.fastPanel[index] === bindRequest.item) { pmcData.Inventory.fastPanel[index] = ""; break; @@ -595,8 +551,7 @@ export class InventoryController request: IInventoryBindRequestData, sessionID: string, output: IItemEventRouterResponse, - ): void - { + ): void { // Remove kvp from requested fast panel index delete pmcData.Inventory.fastPanel[request.index]; } @@ -614,48 +569,37 @@ export class InventoryController body: IInventoryExamineRequestData, sessionID: string, output: IItemEventRouterResponse, - ): IItemEventRouterResponse - { + ): IItemEventRouterResponse { let itemId = ""; - if ("fromOwner" in body) - { - try - { + if ("fromOwner" in body) { + try { itemId = this.getExaminedItemTpl(body); - } - catch - { + } catch { this.logger.error(this.localisationService.getText("inventory-examine_item_does_not_exist", body.item)); } // get hideout item - if (body.fromOwner.type === "HideoutProduction") - { + if (body.fromOwner.type === "HideoutProduction") { itemId = body.item; } } - if (!itemId) - { + if (!itemId) { // item template - if (body.item in this.databaseService.getItems()) - { + if (body.item in this.databaseService.getItems()) { itemId = body.item; } } - if (!itemId) - { + if (!itemId) { // Player inventory const target = pmcData.Inventory.items.find((item) => item._id === body.item); - if (target) - { + if (target) { itemId = target._tpl; } } - if (itemId) - { + if (itemId) { const fullProfile = this.profileHelper.getFullProfile(sessionID); this.flagItemsAsInspectedAndRewardXp([itemId], fullProfile); } @@ -668,14 +612,13 @@ export class InventoryController * @param itemTpls Inspected item tpls * @param fullProfile Profile to add xp to */ - protected flagItemsAsInspectedAndRewardXp(itemTpls: string[], fullProfile: ISptProfile): void - { - for (const itemTpl of itemTpls) - { + protected flagItemsAsInspectedAndRewardXp(itemTpls: string[], fullProfile: ISptProfile): void { + for (const itemTpl of itemTpls) { const item = this.itemHelper.getItem(itemTpl); - if (!item[0]) - { - this.logger.warning(this.localisationService.getText("inventory-unable_to_inspect_item_not_in_db", itemTpl)); + if (!item[0]) { + this.logger.warning( + this.localisationService.getText("inventory-unable_to_inspect_item_not_in_db", itemTpl), + ); return; } @@ -700,47 +643,40 @@ export class InventoryController * @param request Response request * @returns tplId */ - protected getExaminedItemTpl(request: IInventoryExamineRequestData): string - { - if (this.presetHelper.isPreset(request.item)) - { + protected getExaminedItemTpl(request: IInventoryExamineRequestData): string { + if (this.presetHelper.isPreset(request.item)) { return this.presetHelper.getBaseItemTpl(request.item); } - if (request.fromOwner.id === Traders.FENCE) - { + if (request.fromOwner.id === Traders.FENCE) { // Get tpl from fence assorts return this.fenceService.getRawFenceAssorts().items.find((x) => x._id === request.item)?._tpl; } - if (request.fromOwner.type === "Trader") - { + if (request.fromOwner.type === "Trader") { // Not fence // get tpl from trader assort - return this.databaseService.getTrader(request.fromOwner.id).assort.items - .find((item) => item._id === request.item)?._tpl; + return this.databaseService + .getTrader(request.fromOwner.id) + .assort.items.find((item) => item._id === request.item)?._tpl; } - if (request.fromOwner.type === "RagFair") - { + if (request.fromOwner.type === "RagFair") { // Try to get tplid from items.json first const item = this.itemHelper.getItem(request.item); - if (item[0]) - { + if (item[0]) { return item[1]._id; } // Try alternate way of getting offer if first approach fails let offer = this.ragfairOfferService.getOfferByOfferId(request.item); - if (!offer) - { + if (!offer) { offer = this.ragfairOfferService.getOfferByOfferId(request.fromOwner.id); } // Try find examine item inside offer items array const matchingItem = offer.items.find((offerItem) => offerItem._id === request.item); - if (matchingItem) - { + if (matchingItem) { return matchingItem._tpl; } @@ -753,10 +689,8 @@ export class InventoryController pmcData: IPmcData, body: IInventoryReadEncyclopediaRequestData, sessionID: string, - ): IItemEventRouterResponse - { - for (const id of body.ids) - { + ): IItemEventRouterResponse { + for (const id of body.ids) { pmcData.Encyclopedia[id] = true; } @@ -770,26 +704,22 @@ export class InventoryController * @param request sort request * @param sessionID Session id */ - public sortInventory(pmcData: IPmcData, request: IInventorySortRequestData, sessionID: string): void - { - for (const change of request.changedItems) - { + public sortInventory(pmcData: IPmcData, request: IInventorySortRequestData, sessionID: string): void { + for (const change of request.changedItems) { const inventoryItem = pmcData.Inventory.items.find((item) => item._id === change._id); - if (!inventoryItem) - { - this.logger.error(this.localisationService.getText("inventory-unable_to_sort_inventory_restart_game", change._id)); + if (!inventoryItem) { + this.logger.error( + this.localisationService.getText("inventory-unable_to_sort_inventory_restart_game", change._id), + ); continue; } inventoryItem.parentId = change.parentId; inventoryItem.slotId = change.slotId; - if (change.location) - { + if (change.location) { inventoryItem.location = change.location; - } - else - { + } else { delete inventoryItem.location; } } @@ -808,8 +738,7 @@ export class InventoryController request: IInventoryCreateMarkerRequestData, sessionID: string, output: IItemEventRouterResponse, - ): void - { + ): void { const adjustedMapItem = this.mapMarkerService.createMarkerOnMap(pmcData, request); // Sync with client @@ -828,8 +757,7 @@ export class InventoryController request: IInventoryDeleteMarkerRequestData, sessionID: string, output: IItemEventRouterResponse, - ): void - { + ): void { const mapItem = this.mapMarkerService.deleteMarkerFromMap(pmcData, request); // sync with client @@ -848,8 +776,7 @@ export class InventoryController request: IInventoryEditMarkerRequestData, sessionID: string, output: IItemEventRouterResponse, - ): void - { + ): void { const mapItem = this.mapMarkerService.editMarkerOnMap(pmcData, request); // sync with client @@ -869,8 +796,7 @@ export class InventoryController body: IOpenRandomLootContainerRequestData, sessionID: string, output: IItemEventRouterResponse, - ): void - { + ): void { /** Container player opened in their inventory */ const openedItem = pmcData.Inventory.items.find((item) => item._id === body.item); const containerDetailsDb = this.itemHelper.getItem(openedItem._tpl); @@ -878,37 +804,32 @@ export class InventoryController let foundInRaid = openedItem.upd?.SpawnedInSession; const rewards: Item[][] = []; - const unlockedWeaponCrates = ["665829424de4820934746ce6", "665732e7ac60f009f270d1ef", "665888282c4a1b73af576b77"];// Temp fix for unlocked weapon crate hideout craft - if (isSealedWeaponBox || unlockedWeaponCrates.includes(containerDetailsDb[1]._id)) - { + const unlockedWeaponCrates = [ + "665829424de4820934746ce6", + "665732e7ac60f009f270d1ef", + "665888282c4a1b73af576b77", + ]; // Temp fix for unlocked weapon crate hideout craft + if (isSealedWeaponBox || unlockedWeaponCrates.includes(containerDetailsDb[1]._id)) { const containerSettings = this.inventoryHelper.getInventoryConfig().sealedAirdropContainer; rewards.push(...this.lootGenerator.getSealedWeaponCaseLoot(containerSettings)); - if (containerSettings.foundInRaid) - { + if (containerSettings.foundInRaid) { foundInRaid = containerSettings.foundInRaid; } - } - else - { + } else { const rewardContainerDetails = this.inventoryHelper.getRandomLootContainerRewardDetails(openedItem._tpl); - if (!rewardContainerDetails || !rewardContainerDetails.rewardCount) - { + if (!rewardContainerDetails || !rewardContainerDetails.rewardCount) { this.logger.error(`Unable to add loot to container: ${openedItem._tpl}, no rewards found`); - } - else - { + } else { rewards.push(...this.lootGenerator.getRandomLootContainerLoot(rewardContainerDetails)); - if (rewardContainerDetails.foundInRaid) - { + if (rewardContainerDetails.foundInRaid) { foundInRaid = rewardContainerDetails.foundInRaid; } } } - if (rewards.length > 0) - { + if (rewards.length > 0) { const addItemsRequest: IAddItemsDirectRequest = { itemsWithModsToAdd: rewards, foundInRaid: foundInRaid, @@ -916,8 +837,7 @@ export class InventoryController useSortingTable: true, }; this.inventoryHelper.addItemsToStash(sessionID, addItemsRequest, pmcData, output); - if (output.warnings.length > 0) - { + if (output.warnings.length > 0) { return; } } @@ -926,19 +846,16 @@ export class InventoryController this.inventoryHelper.removeItem(pmcData, body.item, sessionID, output); } - public redeemProfileReward(pmcData: IPmcData, request: IRedeemProfileRequestData, sessionId: string): void - { + public redeemProfileReward(pmcData: IPmcData, request: IRedeemProfileRequestData, sessionId: string): void { const fullProfile = this.profileHelper.getFullProfile(sessionId); - for (const event of request.events) - { + for (const event of request.events) { // Hard coded to `SYSTEM` for now // TODO: make this dynamic const dialog = fullProfile.dialogues["59e7125688a45068a6249071"]; const mail = dialog.messages.find((message) => message._id === event.MessageId); const mailEvent = mail.profileChangeEvents.find((changeEvent) => changeEvent._id === event.EventId); - switch (mailEvent.Type) - { + switch (mailEvent.Type) { case "TraderSalesSum": pmcData.TradersInfo[mailEvent.entity].salesSum = mailEvent.value; this.traderHelper.lvlUp(mailEvent.entity, pmcData); @@ -955,11 +872,9 @@ export class InventoryController this.traderHelper.validateTraderStandingsAndPlayerLevelForProfile(sessionId); this.logger.success(`Set profile xp to: ${mailEvent.value}`); break; - case "SkillPoints": - { + case "SkillPoints": { const profileSkill = pmcData.Skills.Common.find((x) => x.Id === mailEvent.entity); - if (!profileSkill) - { + if (!profileSkill) { this.logger.warning(`Unable to find skill with name: ${mailEvent.entity}`); continue; } @@ -967,8 +882,7 @@ export class InventoryController this.logger.success(`Set profile skill: ${mailEvent.entity} to: ${mailEvent.value}`); break; } - case "ExamineAllItems": - { + case "ExamineAllItems": { const itemsToInspect = this.itemHelper.getItems().filter((x) => x._type !== "Node"); this.flagItemsAsInspectedAndRewardXp( itemsToInspect.map((x) => x._id), @@ -984,8 +898,7 @@ export class InventoryController break; case "AssortmentUnlockRule": - if (!fullProfile.spt.blacklistedItemTpls) - { + if (!fullProfile.spt.blacklistedItemTpls) { fullProfile.spt.blacklistedItemTpls = []; } fullProfile.spt.blacklistedItemTpls.push(mailEvent.entity); @@ -996,11 +909,9 @@ export class InventoryController const areaName = mailEvent.entity; const newValue = mailEvent.value; const hideoutAreaCode = HideoutAreas[areaName.toUpperCase()]; - if (hideoutAreaCode !== undefined) - { + if (hideoutAreaCode !== undefined) { const desiredArea = pmcData.Hideout.Areas.find((area) => area.type === hideoutAreaCode); - if (desiredArea) - { + if (desiredArea) { desiredArea.level = newValue; } } @@ -1014,23 +925,17 @@ export class InventoryController } } - public setFavoriteItem(pmcData: IPmcData, request: ISetFavoriteItems, sessionId: string): void - { - if (!pmcData.Inventory.favoriteItems) - { + public setFavoriteItem(pmcData: IPmcData, request: ISetFavoriteItems, sessionId: string): void { + if (!pmcData.Inventory.favoriteItems) { pmcData.Inventory.favoriteItems = []; } - for (const itemId of request.items) - { + for (const itemId of request.items) { // If id already exists in array, we're removing it const indexOfItemAlreadyFavorited = pmcData.Inventory.favoriteItems.findIndex((x) => x === itemId); - if (indexOfItemAlreadyFavorited > -1) - { + if (indexOfItemAlreadyFavorited > -1) { pmcData.Inventory.favoriteItems.splice(indexOfItemAlreadyFavorited, 1); - } - else - { + } else { pmcData.Inventory.favoriteItems.push(itemId); } } diff --git a/project/src/controllers/LauncherController.ts b/project/src/controllers/LauncherController.ts index 9b797732..b5045fe9 100644 --- a/project/src/controllers/LauncherController.ts +++ b/project/src/controllers/LauncherController.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { HttpServerHelper } from "@spt/helpers/HttpServerHelper"; import { ProfileHelper } from "@spt/helpers/ProfileHelper"; import { PreSptModLoader } from "@spt/loaders/PreSptModLoader"; @@ -18,10 +17,10 @@ import { LocalisationService } from "@spt/services/LocalisationService"; import { HashUtil } from "@spt/utils/HashUtil"; import { RandomUtil } from "@spt/utils/RandomUtil"; import { TimeUtil } from "@spt/utils/TimeUtil"; +import { inject, injectable } from "tsyringe"; @injectable() -export class LauncherController -{ +export class LauncherController { protected coreConfig: ICoreConfig; constructor( @@ -36,16 +35,15 @@ export class LauncherController @inject("LocalisationService") protected localisationService: LocalisationService, @inject("PreSptModLoader") protected preSptModLoader: PreSptModLoader, @inject("ConfigServer") protected configServer: ConfigServer, - ) - { + ) { this.coreConfig = this.configServer.getConfig(ConfigTypes.CORE); } - public connect(): IConnectResponse - { + public connect(): IConnectResponse { // Get all possible profile types + filter out any that are blacklisted - const profileKeys = Object.keys(this.databaseService.getProfiles()) - .filter((key) => !this.coreConfig.features.createNewProfileTypesBlacklist.includes(key)); + const profileKeys = Object.keys(this.databaseService.getProfiles()).filter( + (key) => !this.coreConfig.features.createNewProfileTypesBlacklist.includes(key), + ); return { backendUrl: this.httpServerHelper.getBackendUrl(), @@ -59,15 +57,12 @@ export class LauncherController * Get descriptive text for each of the profile edtions a player can choose, keyed by profile.json profile type e.g. "Edge Of Darkness" * @returns Dictionary of profile types with related descriptive text */ - protected getProfileDescriptions(): Record - { + protected getProfileDescriptions(): Record { const result = {}; const dbProfiles = this.databaseService.getProfiles(); - for (const profileKey in dbProfiles) - { + for (const profileKey in dbProfiles) { const localeKey = dbProfiles[profileKey]?.descriptionLocaleKey; - if (!localeKey) - { + if (!localeKey) { this.logger.warning(this.localisationService.getText("launcher-missing_property", profileKey)); continue; } @@ -78,18 +73,14 @@ export class LauncherController return result; } - public find(sessionId: string): Info - { + public find(sessionId: string): Info { return this.saveServer.getProfiles()[sessionId]?.info; } - public login(info: ILoginRequestData): string - { - for (const sessionID in this.saveServer.getProfiles()) - { + public login(info: ILoginRequestData): string { + for (const sessionID in this.saveServer.getProfiles()) { const account = this.saveServer.getProfile(sessionID).info; - if (info.username === account.username) - { + if (info.username === account.username) { return sessionID; } } @@ -97,12 +88,9 @@ export class LauncherController return ""; } - public register(info: IRegisterData): string - { - for (const sessionID in this.saveServer.getProfiles()) - { - if (info.username === this.saveServer.getProfile(sessionID).info.username) - { + public register(info: IRegisterData): string { + for (const sessionID in this.saveServer.getProfiles()) { + if (info.username === this.saveServer.getProfile(sessionID).info.username) { return ""; } } @@ -110,8 +98,7 @@ export class LauncherController return this.createAccount(info); } - protected createAccount(info: IRegisterData): string - { + protected createAccount(info: IRegisterData): string { const profileId = this.generateProfileId(); const scavId = this.generateProfileId(); const newProfileDetails: Info = { @@ -131,39 +118,33 @@ export class LauncherController return profileId; } - protected generateProfileId(): string - { + protected generateProfileId(): string { const timestamp = this.timeUtil.getTimestamp(); return this.formatID(timestamp, timestamp * this.randomUtil.getInt(1, 1000000)); } - protected formatID(timeStamp: number, counter: number): string - { + protected formatID(timeStamp: number, counter: number): string { const timeStampStr = timeStamp.toString(16).padStart(8, "0"); const counterStr = counter.toString(16).padStart(16, "0"); return timeStampStr.toLowerCase() + counterStr.toLowerCase(); } - public changeUsername(info: IChangeRequestData): string - { + public changeUsername(info: IChangeRequestData): string { const sessionID = this.login(info); - if (sessionID) - { + if (sessionID) { this.saveServer.getProfile(sessionID).info.username = info.change; } return sessionID; } - public changePassword(info: IChangeRequestData): string - { + public changePassword(info: IChangeRequestData): string { const sessionID = this.login(info); - if (sessionID) - { + if (sessionID) { this.saveServer.getProfile(sessionID).info.password = info.change; } @@ -175,17 +156,14 @@ export class LauncherController * @param info IRegisterData * @returns Session id */ - public wipe(info: IRegisterData): string - { - if (!this.coreConfig.allowProfileWipe) - { + public wipe(info: IRegisterData): string { + if (!this.coreConfig.allowProfileWipe) { return; } const sessionID = this.login(info); - if (sessionID) - { + if (sessionID) { const profile = this.saveServer.getProfile(sessionID); profile.info.edition = info.edition; profile.info.wipe = true; @@ -194,8 +172,7 @@ export class LauncherController return sessionID; } - public getCompatibleTarkovVersion(): string - { + public getCompatibleTarkovVersion(): string { return this.coreConfig.compatibleTarkovVersion; } @@ -203,8 +180,7 @@ export class LauncherController * Get the mods the server has currently loaded * @returns Dictionary of mod name and mod details */ - public getLoadedServerMods(): Record - { + public getLoadedServerMods(): Record { return this.preSptModLoader.getImportedModDetails(); } @@ -213,12 +189,10 @@ export class LauncherController * @param sessionId Player id * @returns Array of mod details */ - public getServerModsProfileUsed(sessionId: string): ModDetails[] - { + public getServerModsProfileUsed(sessionId: string): ModDetails[] { const profile = this.profileHelper.getFullProfile(sessionId); - if (profile?.spt?.mods) - { + if (profile?.spt?.mods) { return this.preSptModLoader.getProfileModsGroupedByModName(profile?.spt?.mods); } diff --git a/project/src/controllers/LocationController.ts b/project/src/controllers/LocationController.ts index 9690f30c..a439dfb2 100644 --- a/project/src/controllers/LocationController.ts +++ b/project/src/controllers/LocationController.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { ILocationsGenerateAllResponse } from "@spt/models/eft/common/ILocationsSourceDestinationBase"; import { IGetAirdropLootResponse } from "@spt/models/eft/location/IGetAirdropLootResponse"; import { ConfigTypes } from "@spt/models/enums/ConfigTypes"; @@ -9,10 +8,10 @@ import { ConfigServer } from "@spt/servers/ConfigServer"; import { AirdropService } from "@spt/services/AirdropService"; import { DatabaseService } from "@spt/services/DatabaseService"; import { ICloner } from "@spt/utils/cloners/ICloner"; +import { inject, injectable } from "tsyringe"; @injectable() -export class LocationController -{ +export class LocationController { protected locationConfig: ILocationConfig; constructor( @@ -21,8 +20,7 @@ export class LocationController @inject("AirdropService") protected airdropService: AirdropService, @inject("ConfigServer") protected configServer: ConfigServer, @inject("PrimaryCloner") protected cloner: ICloner, - ) - { + ) { this.locationConfig = this.configServer.getConfig(ConfigTypes.LOCATION); } @@ -32,15 +30,12 @@ export class LocationController * @param sessionId Players Id * @returns ILocationsGenerateAllResponse */ - public generateAll(sessionId: string): ILocationsGenerateAllResponse - { + public generateAll(sessionId: string): ILocationsGenerateAllResponse { const locationsFromDb = this.databaseService.getLocations(); const locations: ILocations = {}; - for (const mapName in locationsFromDb) - { + for (const mapName in locationsFromDb) { const mapBase = locationsFromDb[mapName]?.base; - if (!mapBase) - { + if (!mapBase) { this.logger.debug(`Map: ${mapName} has no base json file, skipping generation`); continue; } @@ -55,8 +50,7 @@ export class LocationController } /** Handle client/airdrop/loot */ - public getAirdropLoot(): IGetAirdropLootResponse - { + public getAirdropLoot(): IGetAirdropLootResponse { return this.airdropService.generateAirdropLoot(); } } diff --git a/project/src/controllers/MatchController.ts b/project/src/controllers/MatchController.ts index 99888419..1f38825d 100644 --- a/project/src/controllers/MatchController.ts +++ b/project/src/controllers/MatchController.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { ApplicationContext } from "@spt/context/ApplicationContext"; import { ContextVariableType } from "@spt/context/ContextVariableType"; import { IEndLocalRaidRequestData } from "@spt/models/eft/match/IEndLocalRaidRequestData"; @@ -19,10 +18,10 @@ import { LocationLifecycleService } from "@spt/services/LocationLifecycleService import { MatchLocationService } from "@spt/services/MatchLocationService"; import { ProfileSnapshotService } from "@spt/services/ProfileSnapshotService"; import { ICloner } from "@spt/utils/cloners/ICloner"; +import { inject, injectable } from "tsyringe"; @injectable() -export class MatchController -{ +export class MatchController { protected matchConfig: IMatchConfig; protected pmcConfig: IPmcConfig; @@ -35,26 +34,22 @@ export class MatchController @inject("ApplicationContext") protected applicationContext: ApplicationContext, @inject("LocationLifecycleService") protected locationLifecycleService: LocationLifecycleService, @inject("PrimaryCloner") protected cloner: ICloner, - ) - { + ) { this.matchConfig = this.configServer.getConfig(ConfigTypes.MATCH); this.pmcConfig = this.configServer.getConfig(ConfigTypes.PMC); } - public getEnabled(): boolean - { + public getEnabled(): boolean { return this.matchConfig.enabled; } /** Handle client/match/group/delete */ - public deleteGroup(info: any): void - { + public deleteGroup(info: any): void { this.matchLocationService.deleteGroup(info); } /** Handle match/group/start_game */ - public joinMatch(info: IMatchGroupStartGameRequest, sessionId: string): IProfileStatusResponse - { + public joinMatch(info: IMatchGroupStartGameRequest, sessionId: string): IProfileStatusResponse { const output: IProfileStatusResponse = { maxPveCountExceeded: false, profiles: [] }; // get list of players joining into the match @@ -77,8 +72,7 @@ export class MatchController } /** Handle client/match/group/status */ - public getGroupStatus(info: IMatchGroupStatusRequest): IMatchGroupStatusResponse - { + public getGroupStatus(info: IMatchGroupStatusRequest): IMatchGroupStatusResponse { return { players: [], maxPveCountExceeded: false }; } @@ -87,16 +81,14 @@ export class MatchController * @param request Raid config request * @param sessionID Session id */ - public configureOfflineRaid(request: IGetRaidConfigurationRequestData, sessionID: string): void - { + public configureOfflineRaid(request: IGetRaidConfigurationRequestData, sessionID: string): void { // Store request data for access during bot generation this.applicationContext.addValue(ContextVariableType.RAID_CONFIGURATION, request); // TODO: add code to strip PMC of equipment now they've started the raid // Set pmcs to difficulty set in pre-raid screen if override in bot config isnt enabled - if (!this.pmcConfig.useDifficultyOverride) - { + if (!this.pmcConfig.useDifficultyOverride) { this.pmcConfig.difficulty = this.convertDifficultyDropdownIntoBotDifficulty( request.wavesSettings.botDifficulty, ); @@ -112,11 +104,9 @@ export class MatchController * @param botDifficulty dropdown difficulty value * @returns bot difficulty */ - protected convertDifficultyDropdownIntoBotDifficulty(botDifficulty: string): string - { + protected convertDifficultyDropdownIntoBotDifficulty(botDifficulty: string): string { // Edge case medium - must be altered - if (botDifficulty.toLowerCase() === "medium") - { + if (botDifficulty.toLowerCase() === "medium") { return "normal"; } @@ -124,14 +114,12 @@ export class MatchController } /** Handle client/match/local/start */ - public startLocalRaid(sessionId: string, request: IStartLocalRaidRequestData): IStartLocalRaidResponseData - { + public startLocalRaid(sessionId: string, request: IStartLocalRaidRequestData): IStartLocalRaidResponseData { return this.locationLifecycleService.startLocalRaid(sessionId, request); } /** Handle client/match/local/end */ - public endLocalRaid(sessionId: string, request: IEndLocalRaidRequestData): void - { + public endLocalRaid(sessionId: string, request: IEndLocalRaidRequestData): void { return this.locationLifecycleService.endLocalRaid(sessionId, request); } } diff --git a/project/src/controllers/NoteController.ts b/project/src/controllers/NoteController.ts index 3676a42b..d175275f 100644 --- a/project/src/controllers/NoteController.ts +++ b/project/src/controllers/NoteController.ts @@ -1,26 +1,22 @@ -import { inject, injectable } from "tsyringe"; import { IPmcData } from "@spt/models/eft/common/IPmcData"; import { Note } from "@spt/models/eft/common/tables/IBotBase"; import { IItemEventRouterResponse } from "@spt/models/eft/itemEvent/IItemEventRouterResponse"; import { INoteActionData } from "@spt/models/eft/notes/INoteActionData"; import { EventOutputHolder } from "@spt/routers/EventOutputHolder"; +import { inject, injectable } from "tsyringe"; @injectable() -export class NoteController -{ - constructor(@inject("EventOutputHolder") protected eventOutputHolder: EventOutputHolder) - {} +export class NoteController { + constructor(@inject("EventOutputHolder") protected eventOutputHolder: EventOutputHolder) {} - public addNote(pmcData: IPmcData, body: INoteActionData, sessionID: string): IItemEventRouterResponse - { + public addNote(pmcData: IPmcData, body: INoteActionData, sessionID: string): IItemEventRouterResponse { const newNote: Note = { Time: body.note.Time, Text: body.note.Text }; pmcData.Notes.Notes.push(newNote); return this.eventOutputHolder.getOutput(sessionID); } - public editNote(pmcData: IPmcData, body: INoteActionData, sessionID: string): IItemEventRouterResponse - { + public editNote(pmcData: IPmcData, body: INoteActionData, sessionID: string): IItemEventRouterResponse { const noteToEdit: Note = pmcData.Notes.Notes[body.index]; noteToEdit.Time = body.note.Time; noteToEdit.Text = body.note.Text; @@ -28,8 +24,7 @@ export class NoteController return this.eventOutputHolder.getOutput(sessionID); } - public deleteNote(pmcData: IPmcData, body: INoteActionData, sessionID: string): IItemEventRouterResponse - { + public deleteNote(pmcData: IPmcData, body: INoteActionData, sessionID: string): IItemEventRouterResponse { pmcData.Notes.Notes.splice(body.index, 1); return this.eventOutputHolder.getOutput(sessionID); } diff --git a/project/src/controllers/NotifierController.ts b/project/src/controllers/NotifierController.ts index 2199b483..f842d37c 100644 --- a/project/src/controllers/NotifierController.ts +++ b/project/src/controllers/NotifierController.ts @@ -1,12 +1,11 @@ -import { inject, injectable } from "tsyringe"; import { HttpServerHelper } from "@spt/helpers/HttpServerHelper"; import { NotifierHelper } from "@spt/helpers/NotifierHelper"; import { INotifierChannel } from "@spt/models/eft/notifier/INotifier"; import { NotificationService } from "@spt/services/NotificationService"; +import { inject, injectable } from "tsyringe"; @injectable() -export class NotifierController -{ +export class NotifierController { protected pollInterval = 300; protected timeout = 15000; @@ -14,8 +13,7 @@ export class NotifierController @inject("NotifierHelper") protected notifierHelper: NotifierHelper, @inject("HttpServerHelper") protected httpServerHelper: HttpServerHelper, @inject("NotificationService") protected notificationService: NotificationService, - ) - {} + ) {} /** * Resolve an array of session notifications. @@ -24,10 +22,8 @@ export class NotifierController * one or more appear or when a timeout expires. * If no notifications are available after the timeout, use a default message. */ - public async notifyAsync(sessionID: string): Promise - { - return new Promise((resolve) => - { + public async notifyAsync(sessionID: string): Promise { + return new Promise((resolve) => { // keep track of our timeout let counter = 0; @@ -35,17 +31,14 @@ export class NotifierController * Check for notifications, resolve if any, otherwise poll * intermittently for a period of time. */ - const checkNotifications = () => - { + const checkNotifications = () => { /** * If there are no pending messages we should either check again later * or timeout now with a default response. */ - if (!this.notificationService.has(sessionID)) - { + if (!this.notificationService.has(sessionID)) { // have we exceeded timeout? if so reply with default ping message - if (counter > this.timeout) - { + if (counter > this.timeout) { return resolve([this.notifierHelper.getDefaultNotification()]); } @@ -71,14 +64,12 @@ export class NotifierController }); } - public getServer(sessionID: string): string - { + public getServer(sessionID: string): string { return `${this.httpServerHelper.getBackendUrl()}/notifierServer/get/${sessionID}`; } /** Handle client/notifier/channel/create */ - public getChannel(sessionID: string): INotifierChannel - { + public getChannel(sessionID: string): INotifierChannel { return { server: this.httpServerHelper.buildUrl(), channel_id: sessionID, diff --git a/project/src/controllers/PresetController.ts b/project/src/controllers/PresetController.ts index f4032479..60af08ee 100644 --- a/project/src/controllers/PresetController.ts +++ b/project/src/controllers/PresetController.ts @@ -1,28 +1,23 @@ -import { inject, injectable } from "tsyringe"; import { PresetHelper } from "@spt/helpers/PresetHelper"; import { IPreset } from "@spt/models/eft/common/IGlobals"; import { ILogger } from "@spt/models/spt/utils/ILogger"; import { DatabaseService } from "@spt/services/DatabaseService"; +import { inject, injectable } from "tsyringe"; @injectable() -export class PresetController -{ +export class PresetController { constructor( @inject("PrimaryLogger") protected logger: ILogger, @inject("PresetHelper") protected presetHelper: PresetHelper, @inject("DatabaseService") protected databaseService: DatabaseService, - ) - {} + ) {} - public initialize(): void - { + public initialize(): void { const presets: [string, IPreset][] = Object.entries(this.databaseService.getGlobals().ItemPresets); const reverse: Record = {}; - for (const [id, preset] of presets) - { - if (id !== preset._id) - { + for (const [id, preset] of presets) { + if (id !== preset._id) { this.logger.error( `Preset for template tpl: '${preset._items[0]._tpl} ${preset._name}' has invalid key: (${id} != ${preset._id}). Skipping`, ); @@ -32,8 +27,7 @@ export class PresetController const tpl = preset._items[0]._tpl; - if (!(tpl in reverse)) - { + if (!(tpl in reverse)) { reverse[tpl] = []; } diff --git a/project/src/controllers/ProfileController.ts b/project/src/controllers/ProfileController.ts index 237ce166..5908a255 100644 --- a/project/src/controllers/ProfileController.ts +++ b/project/src/controllers/ProfileController.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { PlayerScavGenerator } from "@spt/generators/PlayerScavGenerator"; import { DialogueHelper } from "@spt/helpers/DialogueHelper"; import { ItemHelper } from "@spt/helpers/ItemHelper"; @@ -31,13 +30,13 @@ import { LocalisationService } from "@spt/services/LocalisationService"; import { MailSendService } from "@spt/services/MailSendService"; import { ProfileFixerService } from "@spt/services/ProfileFixerService"; import { SeasonalEventService } from "@spt/services/SeasonalEventService"; -import { ICloner } from "@spt/utils/cloners/ICloner"; import { HashUtil } from "@spt/utils/HashUtil"; import { TimeUtil } from "@spt/utils/TimeUtil"; +import { ICloner } from "@spt/utils/cloners/ICloner"; +import { inject, injectable } from "tsyringe"; @injectable() -export class ProfileController -{ +export class ProfileController { constructor( @inject("PrimaryLogger") protected logger: ILogger, @inject("HashUtil") protected hashUtil: HashUtil, @@ -56,14 +55,12 @@ export class ProfileController @inject("DialogueHelper") protected dialogueHelper: DialogueHelper, @inject("QuestHelper") protected questHelper: QuestHelper, @inject("ProfileHelper") protected profileHelper: ProfileHelper, - ) - {} + ) {} /** * Handle /launcher/profiles */ - public getMiniProfiles(): IMiniProfile[] - { + public getMiniProfiles(): IMiniProfile[] { const allProfiles = Object.keys(this.saveServer.getProfiles()); return allProfiles.map((sessionId) => this.getMiniProfile(sessionId)); @@ -72,11 +69,9 @@ export class ProfileController /** * Handle launcher/profile/info */ - public getMiniProfile(sessionID: string): IMiniProfile - { + public getMiniProfile(sessionID: string): IMiniProfile { const profile = this.saveServer.getProfile(sessionID); - if (!profile || !profile.characters) - { + if (!profile || !profile.characters) { throw new Error(`Unable to find character data for id: ${sessionID}. Profile may be corrupt`); } @@ -84,8 +79,7 @@ export class ProfileController const maxlvl = this.profileHelper.getMaxLevel(); // Player hasn't completed profile creation process, send defaults - if (!pmc?.Info?.Level) - { + if (!pmc?.Info?.Level) { return { username: profile.info?.username ?? "", nickname: "unknown", @@ -109,9 +103,7 @@ export class ProfileController side: pmc.Info.Side, currlvl: pmc.Info.Level, currexp: pmc.Info.Experience ?? 0, - prevexp: currlvl === 0 - ? 0 - : this.profileHelper.getExperience(currlvl), + prevexp: currlvl === 0 ? 0 : this.profileHelper.getExperience(currlvl), nextlvl: nextlvl, maxlvl: maxlvl, edition: profile.info?.edition ?? "", @@ -123,8 +115,7 @@ export class ProfileController /** * Handle client/game/profile/list */ - public getCompleteProfile(sessionID: string): IPmcData[] - { + public getCompleteProfile(sessionID: string): IPmcData[] { return this.profileHelper.getCompleteProfile(sessionID); } @@ -134,11 +125,11 @@ export class ProfileController * @param sessionID Player id * @returns Profiles _id value */ - public createProfile(info: IProfileCreateRequestData, sessionID: string): string - { + public createProfile(info: IProfileCreateRequestData, sessionID: string): string { const account = this.saveServer.getProfile(sessionID).info; - const profileTemplate: ITemplateSide - = this.cloner.clone(this.databaseService.getProfiles()[account.edition][info.side.toLowerCase()]); + const profileTemplate: ITemplateSide = this.cloner.clone( + this.databaseService.getProfiles()[account.edition][info.side.toLowerCase()], + ); const pmcData = profileTemplate.character; // Delete existing profile @@ -166,8 +157,7 @@ export class ProfileController this.updateInventoryEquipmentId(pmcData); - if (!pmcData.UnlockedInfo) - { + if (!pmcData.UnlockedInfo) { pmcData.UnlockedInfo = { unlockedProductionRecipe: [] }; } @@ -200,14 +190,12 @@ export class ProfileController this.saveServer.addProfile(profileDetails); - if (profileTemplate.trader.setQuestsAvailableForStart) - { + if (profileTemplate.trader.setQuestsAvailableForStart) { this.questHelper.addAllQuestsToProfile(profileDetails.characters.pmc, [QuestStatus.AvailableForStart]); } // Profile is flagged as wanting quests set to ready to hand in and collect rewards - if (profileTemplate.trader.setQuestsAvailableForFinish) - { + if (profileTemplate.trader.setQuestsAvailableForFinish) { this.questHelper.addAllQuestsToProfile(profileDetails.characters.pmc, [ QuestStatus.AvailableForStart, QuestStatus.Started, @@ -234,8 +222,7 @@ export class ProfileController this.saveServer.saveProfile(sessionID); // Requires to enable seasonal changes after creating fresh profile - if (this.seasonalEventService.isAutomaticEventDetectionEnabled()) - { + if (this.seasonalEventService.isAutomaticEventDetectionEnabled()) { this.seasonalEventService.enableSeasonalEvents(sessionID); } @@ -246,22 +233,18 @@ export class ProfileController * make profiles pmcData.Inventory.equipment unique * @param pmcData Profile to update */ - protected updateInventoryEquipmentId(pmcData: IPmcData): void - { + protected updateInventoryEquipmentId(pmcData: IPmcData): void { const oldEquipmentId = pmcData.Inventory.equipment; pmcData.Inventory.equipment = this.hashUtil.generate(); - for (const item of pmcData.Inventory.items) - { - if (item.parentId === oldEquipmentId) - { + for (const item of pmcData.Inventory.items) { + if (item.parentId === oldEquipmentId) { item.parentId = pmcData.Inventory.equipment; continue; } - if (item._id === oldEquipmentId) - { + if (item._id === oldEquipmentId) { item._id = pmcData.Inventory.equipment; } } @@ -271,14 +254,10 @@ export class ProfileController * Delete a profile * @param sessionID Id of profile to delete */ - protected deleteProfileBySessionId(sessionID: string): void - { - if (sessionID in this.saveServer.getProfiles()) - { + protected deleteProfileBySessionId(sessionID: string): void { + if (sessionID in this.saveServer.getProfiles()) { this.saveServer.deleteProfileById(sessionID); - } - else - { + } else { this.logger.warning( this.localisationService.getText("profile-unable_to_find_profile_by_id_cannot_delete", sessionID), ); @@ -296,10 +275,8 @@ export class ProfileController profileDetails: ISptProfile, sessionID: string, response: IItemEventRouterResponse, - ): void - { - for (const quest of profileDetails.characters.pmc.Quests) - { + ): void { + for (const quest of profileDetails.characters.pmc.Quests) { const questFromDb = this.questHelper.getQuestFromDb(quest.qid, profileDetails.characters.pmc); // Get messageId of text to send to player as text message in game @@ -331,10 +308,8 @@ export class ProfileController * For each trader reset their state to what a level 1 player would see * @param sessionId Session id of profile to reset */ - protected resetAllTradersInProfile(sessionId: string): void - { - for (const traderId in this.databaseService.getTraders()) - { + protected resetAllTradersInProfile(sessionId: string): void { + for (const traderId in this.databaseService.getTraders()) { this.traderHelper.resetTrader(sessionId, traderId); } } @@ -345,23 +320,19 @@ export class ProfileController * @param sessionID * @returns IPmcData object */ - public generatePlayerScav(sessionID: string): IPmcData - { + public generatePlayerScav(sessionID: string): IPmcData { return this.playerScavGenerator.generate(sessionID); } /** * Handle client/game/profile/nickname/validate */ - public validateNickname(info: IValidateNicknameRequestData, sessionID: string): string - { - if (info.nickname.length < 3) - { + public validateNickname(info: IValidateNicknameRequestData, sessionID: string): string { + if (info.nickname.length < 3) { return "tooshort"; } - if (this.profileHelper.isNicknameTaken(info, sessionID)) - { + if (this.profileHelper.isNicknameTaken(info, sessionID)) { return "taken"; } @@ -372,12 +343,10 @@ export class ProfileController * Handle client/game/profile/nickname/change event * Client allows player to adjust their profile name */ - public changeNickname(info: IProfileChangeNicknameRequestData, sessionID: string): string - { + public changeNickname(info: IProfileChangeNicknameRequestData, sessionID: string): string { const output = this.validateNickname(info, sessionID); - if (output === "OK") - { + if (output === "OK") { const pmcData = this.profileHelper.getPmcProfile(sessionID); pmcData.Info.Nickname = info.nickname; @@ -390,8 +359,7 @@ export class ProfileController /** * Handle client/game/profile/voice/change event */ - public changeVoice(info: IProfileChangeVoiceRequestData, sessionID: string): void - { + public changeVoice(info: IProfileChangeVoiceRequestData, sessionID: string): void { const pmcData = this.profileHelper.getPmcProfile(sessionID); pmcData.Info.Voice = info.voice; } @@ -399,8 +367,7 @@ export class ProfileController /** * Handle client/game/profile/search */ - public getFriends(info: ISearchFriendRequestData, sessionID: string): ISearchFriendResponse[] - { + public getFriends(info: ISearchFriendRequestData, sessionID: string): ISearchFriendResponse[] { const profile = this.saveServer.getProfile(sessionID); // return some of the current player info for now @@ -421,8 +388,7 @@ export class ProfileController /** * Handle client/profile/status */ - public getProfileStatus(sessionId: string): GetProfileStatusResponseData - { + public getProfileStatus(sessionId: string): GetProfileStatusResponseData { const account = this.saveServer.getProfile(sessionId).info; const response: GetProfileStatusResponseData = { maxPveCountExceeded: false, @@ -442,8 +408,7 @@ export class ProfileController return response; } - public getOtherProfile(sessionId: string, request: IGetOtherProfileRequest): IGetOtherProfileResponse - { + public getOtherProfile(sessionId: string, request: IGetOtherProfileRequest): IGetOtherProfileResponse { const player = this.profileHelper.getFullProfile(sessionId); const playerPmc = player.characters.pmc; const playerScav = player.characters.scav; @@ -493,21 +458,17 @@ export class ProfileController /** * Handle client/profile/settings */ - public setChosenProfileIcon(sessionId: string, request: IGetProfileSettingsRequest): boolean - { + public setChosenProfileIcon(sessionId: string, request: IGetProfileSettingsRequest): boolean { const profileToUpdate = this.profileHelper.getPmcProfile(sessionId); - if (!profileToUpdate) - { + if (!profileToUpdate) { return false; } - if (request.memberCategory !== null) - { + if (request.memberCategory !== null) { profileToUpdate.Info.SelectedMemberCategory = request.memberCategory; } - if (request.squadInviteRestriction !== null) - { + if (request.squadInviteRestriction !== null) { profileToUpdate.Info.SquadInviteRestriction = request.squadInviteRestriction; } diff --git a/project/src/controllers/QuestController.ts b/project/src/controllers/QuestController.ts index f38be134..8e81d558 100644 --- a/project/src/controllers/QuestController.ts +++ b/project/src/controllers/QuestController.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { DialogueHelper } from "@spt/helpers/DialogueHelper"; import { ItemHelper } from "@spt/helpers/ItemHelper"; import { ProfileHelper } from "@spt/helpers/ProfileHelper"; @@ -27,13 +26,13 @@ import { LocaleService } from "@spt/services/LocaleService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { MailSendService } from "@spt/services/MailSendService"; import { PlayerService } from "@spt/services/PlayerService"; -import { ICloner } from "@spt/utils/cloners/ICloner"; import { HttpResponseUtil } from "@spt/utils/HttpResponseUtil"; import { TimeUtil } from "@spt/utils/TimeUtil"; +import { ICloner } from "@spt/utils/cloners/ICloner"; +import { inject, injectable } from "tsyringe"; @injectable() -export class QuestController -{ +export class QuestController { protected questConfig: IQuestConfig; constructor( @@ -54,8 +53,7 @@ export class QuestController @inject("LocalisationService") protected localisationService: LocalisationService, @inject("ConfigServer") protected configServer: ConfigServer, @inject("PrimaryCloner") protected cloner: ICloner, - ) - { + ) { this.questConfig = this.configServer.getConfig(ConfigTypes.QUEST); } @@ -66,44 +64,37 @@ export class QuestController * @param sessionID session id * @returns array of IQuest */ - public getClientQuests(sessionID: string): IQuest[] - { + public getClientQuests(sessionID: string): IQuest[] { const questsToShowPlayer: IQuest[] = []; const allQuests = this.questHelper.getQuestsFromDb(); const profile: IPmcData = this.profileHelper.getPmcProfile(sessionID); - for (const quest of allQuests) - { + for (const quest of allQuests) { // Player already accepted the quest, show it regardless of status const questInProfile = profile.Quests.find((x) => x.qid === quest._id); - if (questInProfile) - { + if (questInProfile) { quest.sptStatus = questInProfile.status; questsToShowPlayer.push(quest); continue; } // Filter out bear quests for usec and vice versa - if (this.questHelper.questIsForOtherSide(profile.Info.Side, quest._id)) - { + if (this.questHelper.questIsForOtherSide(profile.Info.Side, quest._id)) { continue; } - if (!this.questHelper.showEventQuestToPlayer(quest._id)) - { + if (!this.questHelper.showEventQuestToPlayer(quest._id)) { continue; } // Don't add quests that have a level higher than the user's - if (!this.playerLevelFulfillsQuestRequirement(quest, profile.Info.Level)) - { + if (!this.playerLevelFulfillsQuestRequirement(quest, profile.Info.Level)) { continue; } // Player can use trader mods then remove them, leaving quests behind const trader = profile.TradersInfo[quest.traderId]; - if (!trader) - { + if (!trader) { this.logger.debug( `Unable to show quest: ${quest.QuestName} as its for a trader: ${quest.traderId} that no longer exists.`, ); @@ -121,11 +112,10 @@ export class QuestController // Quest has no conditions, standing or loyalty conditions, add to visible quest list if ( - questRequirements.length === 0 - && loyaltyRequirements.length === 0 - && standingRequirements.length === 0 - ) - { + questRequirements.length === 0 && + loyaltyRequirements.length === 0 && + standingRequirements.length === 0 + ) { quest.sptStatus = QuestStatus.AvailableForStart; questsToShowPlayer.push(quest); continue; @@ -134,34 +124,29 @@ export class QuestController // Check the status of each quest condition, if any are not completed // then this quest should not be visible let haveCompletedPreviousQuest = true; - for (const conditionToFulfil of questRequirements) - { + for (const conditionToFulfil of questRequirements) { // If the previous quest isn't in the user profile, it hasn't been completed or started const prerequisiteQuest = profile.Quests.find((profileQuest) => conditionToFulfil.target.includes(profileQuest.qid), ); - if (!prerequisiteQuest) - { + if (!prerequisiteQuest) { haveCompletedPreviousQuest = false; break; } // Prereq does not have its status requirement fulfilled // Some bsg status ids are strings, MUST convert to number before doing includes check - if (!conditionToFulfil.status.map((status) => Number(status)).includes(prerequisiteQuest.status)) - { + if (!conditionToFulfil.status.map((status) => Number(status)).includes(prerequisiteQuest.status)) { haveCompletedPreviousQuest = false; break; } // Has a wait timer - if (conditionToFulfil.availableAfter > 0) - { + if (conditionToFulfil.availableAfter > 0) { // Compare current time to unlock time for previous quest const previousQuestCompleteTime = prerequisiteQuest.statusTimers[prerequisiteQuest.status]; const unlockTime = previousQuestCompleteTime + conditionToFulfil.availableAfter; - if (unlockTime > this.timeUtil.getTimestamp()) - { + if (unlockTime > this.timeUtil.getTimestamp()) { this.logger.debug( `Quest ${quest.QuestName} is locked for another ${ unlockTime - this.timeUtil.getTimestamp() @@ -172,33 +157,27 @@ export class QuestController } // Previous quest not completed, skip - if (!haveCompletedPreviousQuest) - { + if (!haveCompletedPreviousQuest) { continue; } let passesLoyaltyRequirements = true; - for (const condition of loyaltyRequirements) - { - if (!this.questHelper.traderLoyaltyLevelRequirementCheck(condition, profile)) - { + for (const condition of loyaltyRequirements) { + if (!this.questHelper.traderLoyaltyLevelRequirementCheck(condition, profile)) { passesLoyaltyRequirements = false; break; } } let passesStandingRequirements = true; - for (const condition of standingRequirements) - { - if (!this.questHelper.traderStandingRequirementCheck(condition, profile)) - { + for (const condition of standingRequirements) { + if (!this.questHelper.traderStandingRequirementCheck(condition, profile)) { passesStandingRequirements = false; break; } } - if (haveCompletedPreviousQuest && passesLoyaltyRequirements && passesStandingRequirements) - { + if (haveCompletedPreviousQuest && passesLoyaltyRequirements && passesStandingRequirements) { quest.sptStatus = QuestStatus.AvailableForStart; questsToShowPlayer.push(quest); } @@ -213,21 +192,16 @@ export class QuestController * @param playerLevel level of player to test against quest * @returns true if quest can be seen/accepted by player of defined level */ - protected playerLevelFulfillsQuestRequirement(quest: IQuest, playerLevel: number): boolean - { - if (!quest.conditions) - { + protected playerLevelFulfillsQuestRequirement(quest: IQuest, playerLevel: number): boolean { + if (!quest.conditions) { // No conditions return true; } const levelConditions = this.questConditionHelper.getLevelConditions(quest.conditions.AvailableForStart); - if (levelConditions.length) - { - for (const levelCondition of levelConditions) - { - if (!this.questHelper.doesPlayerLevelFulfilCondition(playerLevel, levelCondition)) - { + if (levelConditions.length) { + for (const levelCondition of levelConditions) { + if (!this.questHelper.doesPlayerLevelFulfilCondition(playerLevel, levelCondition)) { // Not valid, exit out return false; } @@ -252,23 +226,19 @@ export class QuestController pmcData: IPmcData, acceptedQuest: IAcceptQuestRequestData, sessionID: string, - ): IItemEventRouterResponse - { + ): IItemEventRouterResponse { const acceptQuestResponse = this.eventOutputHolder.getOutput(sessionID); // Does quest exist in profile // Restarting a failed quest can mean quest exists in profile const existingQuestStatus = pmcData.Quests.find((x) => x.qid === acceptedQuest.qid); - if (existingQuestStatus) - { + if (existingQuestStatus) { // Update existing this.questHelper.resetQuestState(pmcData, QuestStatus.Started, acceptedQuest.qid); // Need to send client an empty list of completedConditions (Unsure if this does anything) acceptQuestResponse.profileChanges[sessionID].questsStatus.push(existingQuestStatus); - } - else - { + } else { // Add new quest to server profile const newQuest = this.questHelper.getQuestReadyForProfile(pmcData, QuestStatus.Started, acceptedQuest); pmcData.Quests.push(newQuest); @@ -324,8 +294,7 @@ export class QuestController pmcData: IPmcData, acceptedQuest: IAcceptQuestRequestData, sessionID: string, - ): IItemEventRouterResponse - { + ): IItemEventRouterResponse { // Create and store quest status object inside player profile const newRepeatableQuest = this.questHelper.getQuestReadyForProfile( pmcData, @@ -336,8 +305,7 @@ export class QuestController // Look for the generated quest cache in profile.RepeatableQuests const repeatableQuestProfile = this.getRepeatableQuestFromProfile(pmcData, acceptedQuest); - if (!repeatableQuestProfile) - { + if (!repeatableQuestProfile) { this.logger.error( this.localisationService.getText( "repeatable-accepted_repeatable_quest_not_found_in_active_quests", @@ -350,13 +318,11 @@ export class QuestController // Some scav quests need to be added to scav profile for them to show up in-raid if ( - repeatableQuestProfile.side === "Scav" - && ["PickUp", "Exploration", "Elimination"].includes(repeatableQuestProfile.type) - ) - { + repeatableQuestProfile.side === "Scav" && + ["PickUp", "Exploration", "Elimination"].includes(repeatableQuestProfile.type) + ) { const fullProfile = this.profileHelper.getFullProfile(sessionID); - if (!fullProfile.characters.scav.Quests) - { + if (!fullProfile.characters.scav.Quests) { fullProfile.characters.scav.Quests = []; } @@ -371,20 +337,21 @@ export class QuestController protected createAcceptedQuestClientResponse( sessionID: string, pmcData: IPmcData, - repeatableQuestProfile: IRepeatableQuest): IItemEventRouterResponse - { - const repeatableSettings = pmcData.RepeatableQuests - .find((quest) => quest.name === repeatableQuestProfile.sptRepatableGroupName); + repeatableQuestProfile: IRepeatableQuest, + ): IItemEventRouterResponse { + const repeatableSettings = pmcData.RepeatableQuests.find( + (quest) => quest.name === repeatableQuestProfile.sptRepatableGroupName, + ); const change = {}; change[repeatableQuestProfile._id] = repeatableSettings!.changeRequirement[repeatableQuestProfile._id]; const repeatableData: IPmcDataRepeatableQuest = { id: - repeatableSettings.id - ?? this.questConfig.repeatableQuests - .find((repeatableQuest) => repeatableQuest.name === repeatableQuestProfile.sptRepatableGroupName) - .id, + repeatableSettings.id ?? + this.questConfig.repeatableQuests.find( + (repeatableQuest) => repeatableQuest.name === repeatableQuestProfile.sptRepatableGroupName, + ).id, name: repeatableSettings.name, endTime: repeatableSettings.endTime, changeRequirement: change, @@ -396,8 +363,7 @@ export class QuestController // Nullguard const acceptQuestResponse = this.eventOutputHolder.getOutput(sessionID); - if (!acceptQuestResponse.profileChanges[sessionID].repeatableQuests) - { + if (!acceptQuestResponse.profileChanges[sessionID].repeatableQuests) { acceptQuestResponse.profileChanges[sessionID].repeatableQuests = []; } @@ -416,13 +382,10 @@ export class QuestController protected getRepeatableQuestFromProfile( pmcData: IPmcData, acceptedQuest: IAcceptQuestRequestData, - ): IRepeatableQuest - { - for (const repeatableQuest of pmcData.RepeatableQuests) - { + ): IRepeatableQuest { + for (const repeatableQuest of pmcData.RepeatableQuests) { const matchingQuest = repeatableQuest.activeQuests.find((x) => x._id === acceptedQuest.qid); - if (matchingQuest) - { + if (matchingQuest) { this.logger.debug(`Accepted repeatable quest ${acceptedQuest.qid} from ${repeatableQuest.name}`); matchingQuest.sptRepatableGroupName = repeatableQuest.name; @@ -447,8 +410,7 @@ export class QuestController pmcData: IPmcData, body: ICompleteQuestRequestData, sessionID: string, - ): IItemEventRouterResponse - { + ): IItemEventRouterResponse { const completeQuestResponse = this.eventOutputHolder.getOutput(sessionID); const completedQuest = this.questHelper.getQuestFromDb(body.qid, pmcData); @@ -469,8 +431,7 @@ export class QuestController // Check for linked failed + unrestartable quests (only get quests not already failed const questsToFail = this.getQuestsFailedByCompletingQuest(completedQuestId, pmcData); - if (questsToFail?.length > 0) - { + if (questsToFail?.length > 0) { this.failQuests(sessionID, pmcData, questsToFail, completeQuestResponse); } @@ -487,16 +448,13 @@ export class QuestController completeQuestResponse.profileChanges[sessionID].quests.push(...questDelta); // Check if it's a repeatable quest. If so, remove from Quests - for (const currentRepeatable of pmcData.RepeatableQuests) - { + for (const currentRepeatable of pmcData.RepeatableQuests) { const repeatableQuest = currentRepeatable.activeQuests.find( (activeRepeatable) => activeRepeatable._id === completedQuestId, ); - if (repeatableQuest) - { + if (repeatableQuest) { // Need to remove redundant scav quest object as its no longer necessary, is tracked in pmc profile - if (repeatableQuest.side === "Scav") - { + if (repeatableQuest.side === "Scav") { this.removeQuestFromScavProfile(sessionID, repeatableQuest._id); } } @@ -504,8 +462,7 @@ export class QuestController // Hydrate client response questsStatus array with data const questStatusChanges = this.getQuestsWithDifferentStatuses(preCompleteProfileQuests, pmcData.Quests); - if (questStatusChanges) - { + if (questStatusChanges) { completeQuestResponse.profileChanges[sessionID].questsStatus.push(...questStatusChanges); } @@ -520,14 +477,11 @@ export class QuestController * @param completedQuestId quest completed id * @returns array of IQuest objects */ - protected getQuestsFailedByCompletingQuest(completedQuestId: string, pmcProfile: IPmcData): IQuest[] - { + protected getQuestsFailedByCompletingQuest(completedQuestId: string, pmcProfile: IPmcData): IQuest[] { const questsInDb = this.questHelper.getQuestsFromDb(); - return questsInDb.filter((quest) => - { + return questsInDb.filter((quest) => { // No fail conditions, skip - if (!quest.conditions.Fail || quest.conditions.Fail.length === 0) - { + if (!quest.conditions.Fail || quest.conditions.Fail.length === 0) { return false; } @@ -536,8 +490,7 @@ export class QuestController pmcProfile.Quests.some( (profileQuest) => profileQuest.qid === quest._id && profileQuest.status === QuestStatus.Fail, ) - ) - { + ) { return false; } @@ -550,17 +503,16 @@ export class QuestController * @param sessionId Player id * @param questIdToRemove Qid of quest to remove */ - protected removeQuestFromScavProfile(sessionId: string, questIdToRemove: string): void - { + protected removeQuestFromScavProfile(sessionId: string, questIdToRemove: string): void { const fullProfile = this.profileHelper.getFullProfile(sessionId); const repeatableInScavProfile = fullProfile.characters.scav.Quests?.find((x) => x.qid === questIdToRemove); - if (!repeatableInScavProfile) - { - this.logger.warning(this.localisationService.getText("quest-unable_to_remove_scav_quest_from_profile", - { + if (!repeatableInScavProfile) { + this.logger.warning( + this.localisationService.getText("quest-unable_to_remove_scav_quest_from_profile", { scavQuestId: questIdToRemove, profileId: sessionId, - })); + }), + ); return; } @@ -580,22 +532,18 @@ export class QuestController protected getQuestsWithDifferentStatuses( preQuestStatusus: IQuestStatus[], postQuestStatuses: IQuestStatus[], - ): IQuestStatus[] | undefined - { + ): IQuestStatus[] | undefined { const result: IQuestStatus[] = []; - for (const quest of postQuestStatuses) - { + for (const quest of postQuestStatuses) { // Add quest if status differs or quest not found const preQuest = preQuestStatusus.find((x) => x.qid === quest.qid); - if (!preQuest || preQuest.status !== quest.status) - { + if (!preQuest || preQuest.status !== quest.status) { result.push(quest); } } - if (result.length === 0) - { + if (result.length === 0) { return undefined; } @@ -614,8 +562,7 @@ export class QuestController pmcData: IPmcData, completedQuestId: string, questRewards: Item[], - ): void - { + ): void { const quest = this.questHelper.getQuestFromDb(completedQuestId, pmcData); this.mailSendService.sendLocalisedNpcMessageToPlayer( @@ -634,24 +581,20 @@ export class QuestController * @param quests Quests to look for wait conditions in * @param completedQuestId Quest just completed */ - protected addTimeLockedQuestsToProfile(pmcData: IPmcData, quests: IQuest[], completedQuestId: string): void - { + protected addTimeLockedQuestsToProfile(pmcData: IPmcData, quests: IQuest[], completedQuestId: string): void { // Iterate over quests, look for quests with right criteria - for (const quest of quests) - { + for (const quest of quests) { // If quest has prereq of completed quest + availableAfter value > 0 (quest has wait time) const nextQuestWaitCondition = quest.conditions.AvailableForStart.find( (x) => x.target?.includes(completedQuestId) && x.availableAfter > 0, ); - if (nextQuestWaitCondition) - { + if (nextQuestWaitCondition) { // Now + wait time const availableAfterTimestamp = this.timeUtil.getTimestamp() + nextQuestWaitCondition.availableAfter; // Update quest in profile with status of AvailableAfter const existingQuestInProfile = pmcData.Quests.find((x) => x.qid === quest._id); - if (existingQuestInProfile) - { + if (existingQuestInProfile) { existingQuestInProfile.availableAfter = availableAfterTimestamp; existingQuestInProfile.status = QuestStatus.AvailableAfter; existingQuestInProfile.startTime = 0; @@ -686,21 +629,16 @@ export class QuestController pmcData: IPmcData, questsToFail: IQuest[], output: IItemEventRouterResponse, - ): void - { - for (const questToFail of questsToFail) - { + ): void { + for (const questToFail of questsToFail) { // Skip failing a quest that has a fail status of something other than success - if (questToFail.conditions.Fail?.some((x) => x.status?.some((status) => status !== QuestStatus.Success))) - { + if (questToFail.conditions.Fail?.some((x) => x.status?.some((status) => status !== QuestStatus.Success))) { continue; } const isActiveQuestInPlayerProfile = pmcData.Quests.find((quest) => quest.qid === questToFail._id); - if (isActiveQuestInPlayerProfile) - { - if (isActiveQuestInPlayerProfile.status !== QuestStatus.Fail) - { + if (isActiveQuestInPlayerProfile) { + if (isActiveQuestInPlayerProfile.status !== QuestStatus.Fail) { const failBody: IFailQuestRequestData = { Action: "QuestFail", qid: questToFail._id, @@ -708,9 +646,7 @@ export class QuestController }; this.questHelper.failQuest(pmcData, failBody, sessionID, output); } - } - else - { + } else { // Failing an entirely new quest that doesnt exist in profile const statusTimers = {}; statusTimers[QuestStatus.Fail] = this.timeUtil.getTimestamp(); @@ -736,8 +672,7 @@ export class QuestController pmcData: IPmcData, handoverQuestRequest: IHandoverQuestRequestData, sessionID: string, - ): IItemEventRouterResponse - { + ): IItemEventRouterResponse { const quest = this.questHelper.getQuestFromDb(handoverQuestRequest.qid, pmcData); const handoverQuestTypes = ["HandoverItem", "WeaponAssembly"]; const output = this.eventOutputHolder.getOutput(sessionID); @@ -747,25 +682,22 @@ export class QuestController // Decrement number of items handed in let handoverRequirements: IQuestCondition; - for (const condition of quest.conditions.AvailableForFinish) - { + for (const condition of quest.conditions.AvailableForFinish) { if ( - condition.id === handoverQuestRequest.conditionId - && handoverQuestTypes.includes(condition.conditionType) - ) - { + condition.id === handoverQuestRequest.conditionId && + handoverQuestTypes.includes(condition.conditionType) + ) { handedInCount = Number.parseInt(condition.value); isItemHandoverQuest = condition.conditionType === handoverQuestTypes[0]; handoverRequirements = condition; - const profileCounter - = handoverQuestRequest.conditionId in pmcData.TaskConditionCounters + const profileCounter = + handoverQuestRequest.conditionId in pmcData.TaskConditionCounters ? pmcData.TaskConditionCounters[handoverQuestRequest.conditionId].value : 0; handedInCount -= profileCounter; - if (handedInCount <= 0) - { + if (handedInCount <= 0) { this.logger.error( this.localisationService.getText( "repeatable-quest_handover_failed_condition_already_satisfied", @@ -785,17 +717,14 @@ export class QuestController } } - if (isItemHandoverQuest && handedInCount === 0) - { + if (isItemHandoverQuest && handedInCount === 0) { return this.showRepeatableQuestInvalidConditionError(handoverQuestRequest, output); } let totalItemCountToRemove = 0; - for (const itemHandover of handoverQuestRequest.items) - { + for (const itemHandover of handoverQuestRequest.items) { const matchingItemInProfile = pmcData.Inventory.items.find((item) => item._id === itemHandover.id); - if (!(matchingItemInProfile && handoverRequirements.target.includes(matchingItemInProfile._tpl))) - { + if (!(matchingItemInProfile && handoverRequirements.target.includes(matchingItemInProfile._tpl))) { // Item handed in by player doesnt match what was requested return this.showQuestItemHandoverMatchError( handoverQuestRequest, @@ -808,8 +737,7 @@ export class QuestController // Remove the right quantity of given items const itemCountToRemove = Math.min(itemHandover.count, handedInCount - totalItemCountToRemove); totalItemCountToRemove += itemCountToRemove; - if (itemHandover.count - itemCountToRemove > 0) - { + if (itemHandover.count - itemCountToRemove > 0) { // Remove single item with no children this.questHelper.changeItemStack( pmcData, @@ -818,13 +746,10 @@ export class QuestController sessionID, output, ); - if (totalItemCountToRemove === handedInCount) - { + if (totalItemCountToRemove === handedInCount) { break; } - } - else - { + } else { // Remove item with children const toRemove = this.itemHelper.findAndReturnChildrenByItems(pmcData.Inventory.items, itemHandover.id); let index = pmcData.Inventory.items.length; @@ -833,17 +758,14 @@ export class QuestController output.profileChanges[sessionID].items.del.push({ _id: itemHandover.id }); // Important: loop backward when removing items from the array we're looping on - while (index-- > 0) - { - if (toRemove.includes(pmcData.Inventory.items[index]._id)) - { + while (index-- > 0) { + if (toRemove.includes(pmcData.Inventory.items[index]._id)) { // Remove the item const removedItem = pmcData.Inventory.items.splice(index, 1)[0]; // If the removed item has a numeric `location` property, re-calculate all the child // element `location` properties of the parent so they are sequential, while retaining order - if (typeof removedItem.location === "number") - { + if (typeof removedItem.location === "number") { const childItems = this.itemHelper.findAndReturnChildrenAsItems( pmcData.Inventory.items, removedItem.parentId, @@ -852,8 +774,7 @@ export class QuestController // Sort by the current `location` and update childItems.sort((a, b) => (a.location > b.location ? 1 : -1)); - for (const [index, item] of childItems.entries()) - { + for (const [index, item] of childItems.entries()) { item.location = index; } } @@ -881,8 +802,7 @@ export class QuestController protected showRepeatableQuestInvalidConditionError( handoverQuestRequest: IHandoverQuestRequestData, output: IItemEventRouterResponse, - ): IItemEventRouterResponse - { + ): IItemEventRouterResponse { const errorMessage = this.localisationService.getText("repeatable-quest_handover_failed_condition_invalid", { questId: handoverQuestRequest.qid, conditionId: handoverQuestRequest.conditionId, @@ -905,8 +825,7 @@ export class QuestController itemHandedOver: Item, handoverRequirements: IQuestCondition, output: IItemEventRouterResponse, - ): IItemEventRouterResponse - { + ): IItemEventRouterResponse { const errorMessage = this.localisationService.getText("quest-handover_wrong_item", { questId: handoverQuestRequest.qid, handedInTpl: itemHandedOver?._tpl ?? "UNKNOWN", @@ -930,10 +849,8 @@ export class QuestController conditionId: string, questId: string, counterValue: number, - ): void - { - if (pmcData.TaskConditionCounters[conditionId] !== undefined) - { + ): void { + if (pmcData.TaskConditionCounters[conditionId] !== undefined) { pmcData.TaskConditionCounters[conditionId].value += counterValue; return; @@ -959,8 +876,7 @@ export class QuestController request: IFailQuestRequestData, sessionID: string, output: IItemEventRouterResponse, - ): IItemEventRouterResponse - { + ): IItemEventRouterResponse { this.questHelper.failQuest(pmcData, request, sessionID, output); return output; diff --git a/project/src/controllers/RagfairController.ts b/project/src/controllers/RagfairController.ts index 0439c23b..3949a50f 100644 --- a/project/src/controllers/RagfairController.ts +++ b/project/src/controllers/RagfairController.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { RagfairOfferGenerator } from "@spt/generators/RagfairOfferGenerator"; import { HandbookHelper } from "@spt/helpers/HandbookHelper"; import { InventoryHelper } from "@spt/helpers/InventoryHelper"; @@ -43,13 +42,13 @@ import { RagfairRequiredItemsService } from "@spt/services/RagfairRequiredItemsS import { RagfairTaxService } from "@spt/services/RagfairTaxService"; import { HttpResponseUtil } from "@spt/utils/HttpResponseUtil"; import { TimeUtil } from "@spt/utils/TimeUtil"; +import { inject, injectable } from "tsyringe"; /** * Handle RagfairCallback events */ @injectable() -export class RagfairController -{ +export class RagfairController { protected ragfairConfig: IRagfairConfig; constructor( @@ -78,8 +77,7 @@ export class RagfairController @inject("RagfairOfferGenerator") protected ragfairOfferGenerator: RagfairOfferGenerator, @inject("LocalisationService") protected localisationService: LocalisationService, @inject("ConfigServer") protected configServer: ConfigServer, - ) - { + ) { this.ragfairConfig = this.configServer.getConfig(ConfigTypes.RAGFAIR); } @@ -90,8 +88,7 @@ export class RagfairController * @param searchRequest Search request data * @returns IGetOffersResult */ - public getOffers(sessionID: string, searchRequest: ISearchRequestData): IGetOffersResult - { + public getOffers(sessionID: string, searchRequest: ISearchRequestData): IGetOffersResult { const profile = this.profileHelper.getFullProfile(sessionID); const itemsToAdd = this.ragfairHelper.filterCategories(sessionID, searchRequest); @@ -105,8 +102,7 @@ export class RagfairController result.offers = this.getOffersForSearchType(searchRequest, itemsToAdd, traderAssorts, profile.characters.pmc); // Client requested a category refresh - if (searchRequest.updateOfferCount) - { + if (searchRequest.updateOfferCount) { result.categories = this.getSpecificCategories(profile.characters.pmc, searchRequest, result.offers); } @@ -120,14 +116,11 @@ export class RagfairController ); // Match offers with quests and lock unfinished quests - for (const offer of result.offers) - { - if (offer.user.memberType === MemberCategory.TRADER) - { + for (const offer of result.offers) { + if (offer.user.memberType === MemberCategory.TRADER) { // for the items, check the barter schemes. The method getDisplayableAssorts sets a flag sptQuestLocked // to true if the quest is not completed yet - if (this.ragfairOfferHelper.traderOfferItemQuestLocked(offer, traderAssorts)) - { + if (this.ragfairOfferHelper.traderOfferItemQuestLocked(offer, traderAssorts)) { offer.locked = true; } @@ -140,8 +133,7 @@ export class RagfairController result.offersCount = result.offers.length; // Handle paging before returning results only if searching for general items, not preset items - if (searchRequest.buildCount === 0) - { + if (searchRequest.buildCount === 0) { const start = searchRequest.page * searchRequest.limit; const end = Math.min((searchRequest.page + 1) * searchRequest.limit, result.offers.length); result.offers = result.offers.slice(start, end); @@ -156,8 +148,7 @@ export class RagfairController * @param request Request data * @returns IRagfairOffer */ - public getOfferById(sessionId: string, request: IGetRagfairOfferByIdRequest): IRagfairOffer - { + public getOfferById(sessionId: string, request: IGetRagfairOfferByIdRequest): IRagfairOffer { const offers = this.ragfairOfferService.getOffers(); const offerToReturn = offers.find((offer) => offer.intId === request.id); @@ -177,16 +168,13 @@ export class RagfairController itemsToAdd: string[], traderAssorts: Record, pmcProfile: IPmcData, - ): IRagfairOffer[] - { + ): IRagfairOffer[] { // Searching for items in preset menu - if (searchRequest.buildCount) - { + if (searchRequest.buildCount) { return this.ragfairOfferHelper.getOffersForBuild(searchRequest, itemsToAdd, traderAssorts, pmcProfile); } - if (searchRequest.neededSearchId?.length > 0) - { + if (searchRequest.neededSearchId?.length > 0) { return this.ragfairOfferHelper.getOffersThatRequireItem(searchRequest, pmcProfile); } @@ -204,23 +192,17 @@ export class RagfairController pmcProfile: IPmcData, searchRequest: ISearchRequestData, offers: IRagfairOffer[], - ): Record - { + ): Record { // Linked/required search categories - const playerHasFleaUnlocked - = pmcProfile.Info.Level >= this.databaseService.getGlobals().config.RagFair.minUserLevel; + const playerHasFleaUnlocked = + pmcProfile.Info.Level >= this.databaseService.getGlobals().config.RagFair.minUserLevel; let offerPool = []; - if (this.isLinkedSearch(searchRequest) || this.isRequiredSearch(searchRequest)) - { + if (this.isLinkedSearch(searchRequest) || this.isRequiredSearch(searchRequest)) { offerPool = offers; - } - else if (!(this.isLinkedSearch(searchRequest) || this.isRequiredSearch(searchRequest))) - { + } else if (!(this.isLinkedSearch(searchRequest) || this.isRequiredSearch(searchRequest))) { // Get all categories offerPool = this.ragfairOfferService.getOffers(); - } - else - { + } else { this.logger.error(this.localisationService.getText("ragfair-unable_to_get_categories")); this.logger.debug(JSON.stringify(searchRequest)); return {}; @@ -233,12 +215,10 @@ export class RagfairController * Add index to all offers passed in (0-indexed) * @param offers Offers to add index value to */ - protected addIndexValueToOffers(offers: IRagfairOffer[]): void - { + protected addIndexValueToOffers(offers: IRagfairOffer[]): void { let counter = 0; - for (const offer of offers) - { + for (const offer of offers) { offer.intId = ++counter; offer.items[0].parentId = ""; // Without this it causes error: "Item deserialization error: No parent with id hideout found for item x" } @@ -249,8 +229,7 @@ export class RagfairController * @param offer Flea offer to update * @param fullProfile Players full profile */ - protected setTraderOfferPurchaseLimits(offer: IRagfairOffer, fullProfile: ISptProfile): void - { + protected setTraderOfferPurchaseLimits(offer: IRagfairOffer, fullProfile: ISptProfile): void { // No trader found, create a blank record for them fullProfile.traderPurchases[offer.user.id] ||= {}; @@ -270,14 +249,12 @@ export class RagfairController * Adjust ragfair offer stack count to match same value as traders assort stack count * @param offer Flea offer to adjust stack size of */ - protected setTraderOfferStackSize(offer: IRagfairOffer): void - { + protected setTraderOfferStackSize(offer: IRagfairOffer): void { const firstItem = offer.items[0]; const traderAssorts = this.traderHelper.getTraderAssortsByTraderId(offer.user.id).items; const assortPurchased = traderAssorts.find((x) => x._id === offer.items[0]._id); - if (!assortPurchased) - { + if (!assortPurchased) { this.logger.warning( this.localisationService.getText("ragfair-unable_to_adjust_stack_count_assort_not_found", { offerId: offer.items[0]._id, @@ -296,8 +273,7 @@ export class RagfairController * @param info Search request * @returns True if it is a 'linked' search type */ - protected isLinkedSearch(info: ISearchRequestData): boolean - { + protected isLinkedSearch(info: ISearchRequestData): boolean { return info.linkedSearchId !== ""; } @@ -306,26 +282,22 @@ export class RagfairController * @param info Search request * @returns True if it is a 'required' search type */ - protected isRequiredSearch(info: ISearchRequestData): boolean - { + protected isRequiredSearch(info: ISearchRequestData): boolean { return info.neededSearchId !== ""; } /** * Check all profiles and sell player offers / send player money for listing if it sold */ - public update(): void - { + public update(): void { const profilesDict = this.saveServer.getProfiles(); - for (const sessionID in this.saveServer.getProfiles()) - { + for (const sessionID in this.saveServer.getProfiles()) { // Check profile is capable of creating offers const pmcProfile = profilesDict[sessionID].characters.pmc; if ( - pmcProfile.RagfairInfo !== undefined - && pmcProfile.Info.Level >= this.databaseService.getGlobals().config.RagFair.minUserLevel - ) - { + pmcProfile.RagfairInfo !== undefined && + pmcProfile.Info.Level >= this.databaseService.getGlobals().config.RagFair.minUserLevel + ) { this.ragfairOfferHelper.processOffersOnProfile(sessionID); } } @@ -336,26 +308,22 @@ export class RagfairController * @param getPriceRequest * @returns min/avg/max values for an item based on flea offers available */ - public getItemMinAvgMaxFleaPriceValues(getPriceRequest: IGetMarketPriceRequestData): IGetItemPriceResult - { + public getItemMinAvgMaxFleaPriceValues(getPriceRequest: IGetMarketPriceRequestData): IGetItemPriceResult { // Get all items of tpl const offers = this.ragfairOfferService.getOffersOfType(getPriceRequest.templateId); // Offers exist for item, get averages of what's listed - if (typeof offers === "object" && offers.length > 0) - { + if (typeof offers === "object" && offers.length > 0) { // These get calculated while iterating through the list below let min = Number.MAX_VALUE; let max = 0; // Get the average offer price, excluding barter offers let avgOfferCount = 0; - const avg - = offers.reduce((sum, offer) => - { + const avg = + offers.reduce((sum, offer) => { // Exclude barter items, they tend to have outrageous equivalent prices - if (offer.requirements.some((req) => !this.paymentHelper.isMoneyTpl(req._tpl))) - { + if (offer.requirements.some((req) => !this.paymentHelper.isMoneyTpl(req._tpl))) { return sum; } @@ -366,12 +334,9 @@ export class RagfairController const perItemPrice = offer.requirementsCost / offerItemCount; // Handle min/max calculations based on the per-item price - if (perItemPrice < min) - { + if (perItemPrice < min) { min = perItemPrice; - } - else if (perItemPrice > max) - { + } else if (perItemPrice > max) { max = perItemPrice; } @@ -380,8 +345,7 @@ export class RagfairController }, 0) / Math.max(avgOfferCount, 1); // If no items were actually counted, min will still be MAX_VALUE, so set it to 0 - if (min === Number.MAX_VALUE) - { + if (min === Number.MAX_VALUE) { min = 0; } @@ -390,8 +354,7 @@ export class RagfairController // No offers listed, get price from live ragfair price list prices.json let tplPrice = this.databaseService.getPrices()[getPriceRequest.templateId]; - if (!tplPrice) - { + if (!tplPrice) { // No flea price, get handbook price tplPrice = this.handbookHelper.getTemplatePrice(getPriceRequest.templateId); } @@ -410,25 +373,21 @@ export class RagfairController pmcData: IPmcData, offerRequest: IAddOfferRequestData, sessionID: string, - ): IItemEventRouterResponse - { + ): IItemEventRouterResponse { const output = this.eventOutputHolder.getOutput(sessionID); const fullProfile = this.saveServer.getProfile(sessionID); const validationMessage = ""; - if (!this.isValidPlayerOfferRequest(offerRequest, validationMessage)) - { + if (!this.isValidPlayerOfferRequest(offerRequest, validationMessage)) { return this.httpResponse.appendErrorToOutput(output, validationMessage); } const typeOfOffer = this.getOfferType(offerRequest); - if (typeOfOffer === FleaOfferType.UNKNOWN) - { + if (typeOfOffer === FleaOfferType.UNKNOWN) { return this.httpResponse.appendErrorToOutput(output, "Unknown offer type, cannot list item on flea"); } - switch (typeOfOffer) - { + switch (typeOfOffer) { case FleaOfferType.SINGLE: return this.createSingleOffer(sessionID, offerRequest, fullProfile, output); case FleaOfferType.MULTI: @@ -451,16 +410,15 @@ export class RagfairController sessionID: string, offerRequest: IAddOfferRequestData, fullProfile: ISptProfile, - output: IItemEventRouterResponse): IItemEventRouterResponse - { + output: IItemEventRouterResponse, + ): IItemEventRouterResponse { const pmcData = fullProfile.characters.pmc; const itemsToListCount = offerRequest.items.length; // Does not count stack size, only items // Find items to be listed on flea from player inventory - const { items: itemsAndChildrenInInventoryToList, errorMessage: itemsInInventoryError } - = this.getItemsToListOnFleaFromInventory(pmcData, offerRequest.items); - if (!itemsAndChildrenInInventoryToList || itemsInInventoryError) - { + const { items: itemsAndChildrenInInventoryToList, errorMessage: itemsInInventoryError } = + this.getItemsToListOnFleaFromInventory(pmcData, offerRequest.items); + if (!itemsAndChildrenInInventoryToList || itemsInInventoryError) { this.httpResponse.appendErrorToOutput(output, itemsInInventoryError); } @@ -485,8 +443,7 @@ export class RagfairController // Check for and apply item price modifer if it exists in config const itemPriceModifer = this.ragfairConfig.dynamic.itemPriceMultiplier[rootItem._tpl]; - if (itemPriceModifer) - { + if (itemPriceModifer) { averageOfferPriceSingleItem *= itemPriceModifer; } @@ -502,8 +459,7 @@ export class RagfairController offer.sellResult = this.ragfairSellHelper.rollForSale(sellChancePercent, stackCountTotal); // Subtract flea market fee from stash - if (this.ragfairConfig.sell.fees) - { + if (this.ragfairConfig.sell.fees) { const taxFeeChargeFailed = this.chargePlayerTaxFee( sessionID, rootItem, @@ -513,8 +469,7 @@ export class RagfairController offerRequest, output, ); - if (taxFeeChargeFailed) - { + if (taxFeeChargeFailed) { return output; } } @@ -524,8 +479,7 @@ export class RagfairController output.profileChanges[sessionID].ragFairOffers.push(offer); // Remove items from inventory after creating offer - for (const itemToRemove of offerRequest.items) - { + for (const itemToRemove of offerRequest.items) { this.inventoryHelper.removeItem(pmcData, itemToRemove, sessionID, output); } @@ -546,8 +500,8 @@ export class RagfairController sessionID: string, offerRequest: IAddOfferRequestData, fullProfile: ISptProfile, - output: IItemEventRouterResponse): IItemEventRouterResponse - { + output: IItemEventRouterResponse, + ): IItemEventRouterResponse { const pmcData = fullProfile.characters.pmc; const itemsToListCount = offerRequest.items.length; // Does not count stack size, only items @@ -555,13 +509,13 @@ export class RagfairController // Get first item and its children and use as template const firstListingAndChidren = this.itemHelper.findAndReturnChildrenAsItems( pmcData.Inventory.items, - offerRequest.items[0]); + offerRequest.items[0], + ); // Find items to be listed on flea (+ children) from player inventory - const { items: itemsAndChildrenInInventoryToList, errorMessage: itemsInInventoryError } - = this.getItemsToListOnFleaFromInventory(pmcData, offerRequest.items); - if (!itemsAndChildrenInInventoryToList || itemsInInventoryError) - { + const { items: itemsAndChildrenInInventoryToList, errorMessage: itemsInInventoryError } = + this.getItemsToListOnFleaFromInventory(pmcData, offerRequest.items); + if (!itemsAndChildrenInInventoryToList || itemsInInventoryError) { this.httpResponse.appendErrorToOutput(output, itemsInInventoryError); } @@ -570,19 +524,13 @@ export class RagfairController // When listing identical items on flea, condense separate items into one stack with a merged stack count // e.g. 2 ammo items, stackObjectCount = 3 for each, will result in 1 stack of 6 - if (!firstListingAndChidren[0].upd) - { + if (!firstListingAndChidren[0].upd) { firstListingAndChidren[0].upd = {}; } firstListingAndChidren[0].upd.StackObjectsCount = stackCountTotal; // Create flea object - const offer = this.createPlayerOffer( - sessionID, - offerRequest.requirements, - firstListingAndChidren, - false, - ); + const offer = this.createPlayerOffer(sessionID, offerRequest.requirements, firstListingAndChidren, false); // This is the item that will be listed on flea, has merged stackObjectCount const newRootOfferItem = offer.items[0]; @@ -592,8 +540,7 @@ export class RagfairController // Check for and apply item price modifer if it exists in config const itemPriceModifer = this.ragfairConfig.dynamic.itemPriceMultiplier[newRootOfferItem._tpl]; - if (itemPriceModifer) - { + if (itemPriceModifer) { averageOfferPrice *= itemPriceModifer; } @@ -617,8 +564,7 @@ export class RagfairController offer.sellResult = this.ragfairSellHelper.rollForSale(sellChancePercent, stackCountTotal); // Subtract flea market fee from stash - if (this.ragfairConfig.sell.fees) - { + if (this.ragfairConfig.sell.fees) { const taxFeeChargeFailed = this.chargePlayerTaxFee( sessionID, newRootOfferItem, @@ -628,8 +574,7 @@ export class RagfairController offerRequest, output, ); - if (taxFeeChargeFailed) - { + if (taxFeeChargeFailed) { return output; } } @@ -639,8 +584,7 @@ export class RagfairController output.profileChanges[sessionID].ragFairOffers.push(offer); // Remove items from inventory after creating offer - for (const itemToRemove of offerRequest.items) - { + for (const itemToRemove of offerRequest.items) { this.inventoryHelper.removeItem(pmcData, itemToRemove, sessionID, output); } @@ -661,8 +605,8 @@ export class RagfairController sessionID: string, offerRequest: IAddOfferRequestData, fullProfile: ISptProfile, - output: IItemEventRouterResponse): IItemEventRouterResponse - { + output: IItemEventRouterResponse, + ): IItemEventRouterResponse { const pmcData = fullProfile.characters.pmc; const itemsToListCount = offerRequest.items.length; // Does not count stack size, only items @@ -670,13 +614,13 @@ export class RagfairController // Get first item and its children and use as template const firstListingAndChidren = this.itemHelper.findAndReturnChildrenAsItems( pmcData.Inventory.items, - offerRequest.items[0]); + offerRequest.items[0], + ); // Find items to be listed on flea (+ children) from player inventory - const { items: itemsAndChildrenInInventoryToList, errorMessage: itemsInInventoryError } - = this.getItemsToListOnFleaFromInventory(pmcData, offerRequest.items); - if (!itemsAndChildrenInInventoryToList || itemsInInventoryError) - { + const { items: itemsAndChildrenInInventoryToList, errorMessage: itemsInInventoryError } = + this.getItemsToListOnFleaFromInventory(pmcData, offerRequest.items); + if (!itemsAndChildrenInInventoryToList || itemsInInventoryError) { this.httpResponse.appendErrorToOutput(output, itemsInInventoryError); } @@ -685,19 +629,13 @@ export class RagfairController // When listing identical items on flea, condense separate items into one stack with a merged stack count // e.g. 2 ammo items, stackObjectCount = 3 for each, will result in 1 stack of 6 - if (!firstListingAndChidren[0].upd) - { + if (!firstListingAndChidren[0].upd) { firstListingAndChidren[0].upd = {}; } firstListingAndChidren[0].upd.StackObjectsCount = stackCountTotal; // Create flea object - const offer = this.createPlayerOffer( - sessionID, - offerRequest.requirements, - firstListingAndChidren, - true, - ); + const offer = this.createPlayerOffer(sessionID, offerRequest.requirements, firstListingAndChidren, true); // This is the item that will be listed on flea, has merged stackObjectCount const newRootOfferItem = offer.items[0]; @@ -707,8 +645,7 @@ export class RagfairController // Check for and apply item price modifer if it exists in config const itemPriceModifer = this.ragfairConfig.dynamic.itemPriceMultiplier[newRootOfferItem._tpl]; - if (itemPriceModifer) - { + if (itemPriceModifer) { singleItemPrice *= itemPriceModifer; } @@ -732,8 +669,7 @@ export class RagfairController offer.sellResult = this.ragfairSellHelper.rollForSale(sellChancePercent, stackCountTotal, true); // Subtract flea market fee from stash - if (this.ragfairConfig.sell.fees) - { + if (this.ragfairConfig.sell.fees) { const taxFeeChargeFailed = this.chargePlayerTaxFee( sessionID, newRootOfferItem, @@ -743,8 +679,7 @@ export class RagfairController offerRequest, output, ); - if (taxFeeChargeFailed) - { + if (taxFeeChargeFailed) { return output; } } @@ -754,8 +689,7 @@ export class RagfairController output.profileChanges[sessionID].ragFairOffers.push(offer); // Remove items from inventory after creating offer - for (const itemToRemove of offerRequest.items) - { + for (const itemToRemove of offerRequest.items) { this.inventoryHelper.removeItem(pmcData, itemToRemove, sessionID, output); } @@ -768,18 +702,12 @@ export class RagfairController * @param offerRequest Client request * @returns FleaOfferType */ - protected getOfferType(offerRequest: IAddOfferRequestData): FleaOfferType - { - if (offerRequest.items.length == 1 && !offerRequest.sellInOnePiece) - { + protected getOfferType(offerRequest: IAddOfferRequestData): FleaOfferType { + if (offerRequest.items.length == 1 && !offerRequest.sellInOnePiece) { return FleaOfferType.SINGLE; - } - else if (offerRequest.items.length > 1 && !offerRequest.sellInOnePiece) - { + } else if (offerRequest.items.length > 1 && !offerRequest.sellInOnePiece) { return FleaOfferType.MULTI; - } - else if (offerRequest.sellInOnePiece) - { + } else if (offerRequest.sellInOnePiece) { return FleaOfferType.PACK; } @@ -805,19 +733,18 @@ export class RagfairController itemStackCount: number, offerRequest: IAddOfferRequestData, output: IItemEventRouterResponse, - ): boolean - { + ): boolean { // Get tax from cache hydrated earlier by client, if that's missing fall back to server calculation (inaccurate) const storedClientTaxValue = this.ragfairTaxService.getStoredClientOfferTaxValueById(offerRequest.items[0]); const tax = storedClientTaxValue ? storedClientTaxValue.fee : this.ragfairTaxService.calculateTax( - rootItem, - pmcData, - requirementsPriceInRub, - itemStackCount, - offerRequest.sellInOnePiece, - ); + rootItem, + pmcData, + requirementsPriceInRub, + itemStackCount, + offerRequest.sellInOnePiece, + ); this.logger.debug(`Offer tax to charge: ${tax}, pulled from client: ${!!storedClientTaxValue}`); @@ -826,8 +753,7 @@ export class RagfairController const buyTradeRequest = this.createBuyTradeRequestObject("RUB", tax); this.paymentService.payMoney(pmcData, buyTradeRequest, sessionID, output); - if (output.warnings.length > 0) - { + if (output.warnings.length > 0) { this.httpResponse.appendErrorToOutput( output, this.localisationService.getText("ragfair-unable_to_pay_commission_fee", tax), @@ -844,17 +770,14 @@ export class RagfairController * @param errorMessage message to show to player when offer is invalid * @returns Is offer valid */ - protected isValidPlayerOfferRequest(offerRequest: IAddOfferRequestData, errorMessage: string): boolean - { - if (!offerRequest?.items || offerRequest.items.length === 0) - { + protected isValidPlayerOfferRequest(offerRequest: IAddOfferRequestData, errorMessage: string): boolean { + if (!offerRequest?.items || offerRequest.items.length === 0) { this.logger.error(this.localisationService.getText("ragfair-invalid_player_offer_request")); return false; } - if (!offerRequest.requirements) - { + if (!offerRequest.requirements) { this.logger.error(this.localisationService.getText("ragfair-unable_to_place_offer_with_no_requirements")); return false; @@ -868,21 +791,16 @@ export class RagfairController * @param requirements * @returns Rouble price */ - protected calculateRequirementsPriceInRub(requirements: Requirement[]): number - { + protected calculateRequirementsPriceInRub(requirements: Requirement[]): number { let requirementsPriceInRub = 0; - for (const item of requirements) - { + for (const item of requirements) { const requestedItemTpl = item._tpl; - if (this.paymentHelper.isMoneyTpl(requestedItemTpl)) - { + if (this.paymentHelper.isMoneyTpl(requestedItemTpl)) { requirementsPriceInRub += this.handbookHelper.inRUB(item.count, requestedItemTpl); - } - else - { - requirementsPriceInRub - += this.ragfairPriceService.getDynamicPriceForItem(requestedItemTpl) * item.count; + } else { + requirementsPriceInRub += + this.ragfairPriceService.getDynamicPriceForItem(requestedItemTpl) * item.count; } } @@ -898,17 +816,14 @@ export class RagfairController protected getItemsToListOnFleaFromInventory( pmcData: IPmcData, itemIdsFromFleaOfferRequest: string[], - ): { items: Item[][] | undefined, errorMessage: string | undefined } - { + ): { items: Item[][] | undefined; errorMessage: string | undefined } { const itemsToReturn: Item[][] = []; let errorMessage: string | undefined = undefined; // Count how many items are being sold and multiply the requested amount accordingly - for (const itemId of itemIdsFromFleaOfferRequest) - { + for (const itemId of itemIdsFromFleaOfferRequest) { let item = pmcData.Inventory.items.find((i) => i._id === itemId); - if (!item) - { + if (!item) { errorMessage = this.localisationService.getText("ragfair-unable_to_find_item_in_inventory", { id: itemId, }); @@ -921,8 +836,7 @@ export class RagfairController itemsToReturn.push(this.itemHelper.findAndReturnChildrenAsItems(pmcData.Inventory.items, itemId)); } - if (!itemsToReturn?.length) - { + if (!itemsToReturn?.length) { errorMessage = this.localisationService.getText("ragfair-unable_to_find_requested_items_in_inventory"); this.logger.error(errorMessage); @@ -937,11 +851,9 @@ export class RagfairController requirements: Requirement[], items: Item[], sellInOnePiece: boolean, - ): IRagfairOffer - { + ): IRagfairOffer { const loyalLevel = 1; - const formattedItems: Item[] = items.map((item) => - { + const formattedItems: Item[] = items.map((item) => { const isChild = items.some((subItem) => subItem._id === item.parentId); return { @@ -953,12 +865,12 @@ export class RagfairController }; }); - const formattedRequirements: IBarterScheme[] = requirements.map((item) => - { + const formattedRequirements: IBarterScheme[] = requirements.map((item) => { return { _tpl: item._tpl, count: item.count, - onlyFunctional: item.onlyFunctional }; + onlyFunctional: item.onlyFunctional, + }; }); return this.ragfairOfferGenerator.createAndAddFleaOffer( @@ -971,13 +883,11 @@ export class RagfairController ); } - public getAllFleaPrices(): Record - { + public getAllFleaPrices(): Record { return this.ragfairPriceService.getAllFleaPrices(); } - public getStaticPrices(): Record - { + public getStaticPrices(): Record { return this.ragfairPriceService.getAllStaticPrices(); } @@ -988,14 +898,12 @@ export class RagfairController * @param sessionId Players id * @returns IItemEventRouterResponse */ - public removeOffer(removeRequest: IRemoveOfferRequestData, sessionId: string): IItemEventRouterResponse - { + public removeOffer(removeRequest: IRemoveOfferRequestData, sessionId: string): IItemEventRouterResponse { const output = this.eventOutputHolder.getOutput(sessionId); const pmcData = this.saveServer.getProfile(sessionId).characters.pmc; const playerProfileOffers = pmcData.RagfairInfo.offers; - if (!playerProfileOffers) - { + if (!playerProfileOffers) { this.logger.warning( this.localisationService.getText("ragfair-unable_to_remove_offer_not_found_in_profile", { profileId: sessionId, @@ -1007,8 +915,7 @@ export class RagfairController } const playerOfferIndex = playerProfileOffers.findIndex((offer) => offer._id === removeRequest.offerId); - if (playerOfferIndex === -1) - { + if (playerOfferIndex === -1) { this.logger.error( this.localisationService.getText("ragfair-offer_not_found_in_profile", { offerId: removeRequest.offerId, @@ -1021,8 +928,7 @@ export class RagfairController } const differenceInSeconds = playerProfileOffers[playerOfferIndex].endTime - this.timeUtil.getTimestamp(); - if (differenceInSeconds > this.ragfairConfig.sell.expireSeconds) - { + if (differenceInSeconds > this.ragfairConfig.sell.expireSeconds) { // `expireSeconds` Default is 71 seconds const newEndTime = this.ragfairConfig.sell.expireSeconds + this.timeUtil.getTimestamp(); playerProfileOffers[playerOfferIndex].endTime = Math.round(newEndTime); @@ -1037,8 +943,7 @@ export class RagfairController * @param sessionId Players id * @returns IItemEventRouterResponse */ - public extendOffer(extendRequest: IExtendOfferRequestData, sessionId: string): IItemEventRouterResponse - { + public extendOffer(extendRequest: IExtendOfferRequestData, sessionId: string): IItemEventRouterResponse { const output = this.eventOutputHolder.getOutput(sessionId); const pmcData = this.saveServer.getProfile(sessionId).characters.pmc; @@ -1046,8 +951,7 @@ export class RagfairController const playerOfferIndex = playerOffers.findIndex((offer) => offer._id === extendRequest.offerId); const secondsToAdd = extendRequest.renewalTime * TimeUtil.ONE_HOUR_AS_SECONDS; - if (playerOfferIndex === -1) - { + if (playerOfferIndex === -1) { this.logger.warning( this.localisationService.getText("ragfair-offer_not_found_in_profile", { offerId: extendRequest.offerId, @@ -1060,14 +964,12 @@ export class RagfairController } // MOD: Pay flea market fee - if (this.ragfairConfig.sell.fees) - { + if (this.ragfairConfig.sell.fees) { const count = playerOffers[playerOfferIndex].sellInOnePiece ? 1 - : playerOffers[playerOfferIndex].items.reduce((sum, item) => - { - return sum + item.upd.StackObjectsCount; - }, 0); + : playerOffers[playerOfferIndex].items.reduce((sum, item) => { + return sum + item.upd.StackObjectsCount; + }, 0); const tax = this.ragfairTaxService.calculateTax( playerOffers[playerOfferIndex].items[0], @@ -1079,8 +981,7 @@ export class RagfairController const request = this.createBuyTradeRequestObject("RUB", tax); this.paymentService.payMoney(pmcData, request, sessionId, output); - if (output.warnings.length > 0) - { + if (output.warnings.length > 0) { return this.httpResponse.appendErrorToOutput( output, this.localisationService.getText("ragfair-unable_to_pay_commission_fee"), @@ -1100,8 +1001,7 @@ export class RagfairController * @param value Amount of currency * @returns IProcessBuyTradeRequestData */ - protected createBuyTradeRequestObject(currency: string, value: number): IProcessBuyTradeRequestData - { + protected createBuyTradeRequestObject(currency: string, value: number): IProcessBuyTradeRequestData { return { tid: "ragfair", Action: "TradingConfirm", diff --git a/project/src/controllers/RepairController.ts b/project/src/controllers/RepairController.ts index d614afa2..3b30ef20 100644 --- a/project/src/controllers/RepairController.ts +++ b/project/src/controllers/RepairController.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { ProfileHelper } from "@spt/helpers/ProfileHelper"; import { QuestHelper } from "@spt/helpers/QuestHelper"; import { RepairHelper } from "@spt/helpers/RepairHelper"; @@ -13,10 +12,10 @@ import { EventOutputHolder } from "@spt/routers/EventOutputHolder"; import { DatabaseService } from "@spt/services/DatabaseService"; import { PaymentService } from "@spt/services/PaymentService"; import { RepairService } from "@spt/services/RepairService"; +import { inject, injectable } from "tsyringe"; @injectable() -export class RepairController -{ +export class RepairController { protected repairConfig: IRepairConfig; constructor( @@ -29,8 +28,7 @@ export class RepairController @inject("RepairHelper") protected repairHelper: RepairHelper, @inject("RepairService") protected repairService: RepairService, @inject("ProfileHelper") protected profileHelper: ProfileHelper, - ) - {} + ) {} /** * Handle TraderRepair event @@ -44,13 +42,11 @@ export class RepairController sessionID: string, body: ITraderRepairActionDataRequest, pmcData: IPmcData, - ): IItemEventRouterResponse - { + ): IItemEventRouterResponse { const output = this.eventOutputHolder.getOutput(sessionID); // find the item to repair - for (const repairItem of body.repairItems) - { + for (const repairItem of body.repairItems) { const repairDetails = this.repairService.repairItemByTrader(sessionID, pmcData, repairItem, body.tid); this.repairService.payForRepair( @@ -62,8 +58,7 @@ export class RepairController output, ); - if (output.warnings.length > 0) - { + if (output.warnings.length > 0) { return output; } @@ -89,8 +84,7 @@ export class RepairController sessionID: string, body: IRepairActionDataRequest, pmcData: IPmcData, - ): IItemEventRouterResponse - { + ): IItemEventRouterResponse { const output = this.eventOutputHolder.getOutput(sessionID); // repair item diff --git a/project/src/controllers/RepeatableQuestController.ts b/project/src/controllers/RepeatableQuestController.ts index c66932a3..d40e4386 100644 --- a/project/src/controllers/RepeatableQuestController.ts +++ b/project/src/controllers/RepeatableQuestController.ts @@ -1,13 +1,9 @@ -import { inject, injectable } from "tsyringe"; import { RepeatableQuestGenerator } from "@spt/generators/RepeatableQuestGenerator"; import { ProfileHelper } from "@spt/helpers/ProfileHelper"; import { QuestHelper } from "@spt/helpers/QuestHelper"; import { RepeatableQuestHelper } from "@spt/helpers/RepeatableQuestHelper"; import { IPmcData } from "@spt/models/eft/common/IPmcData"; -import { - IPmcDataRepeatableQuest, - IRepeatableQuest, -} from "@spt/models/eft/common/tables/IRepeatableQuests"; +import { IPmcDataRepeatableQuest, IRepeatableQuest } from "@spt/models/eft/common/tables/IRepeatableQuests"; import { IItemEventRouterResponse } from "@spt/models/eft/itemEvent/IItemEventRouterResponse"; import { ISptProfile } from "@spt/models/eft/profile/ISptProfile"; import { IRepeatableQuestChangeRequest } from "@spt/models/eft/quests/IRepeatableQuestChangeRequest"; @@ -26,15 +22,15 @@ import { DatabaseService } from "@spt/services/DatabaseService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { PaymentService } from "@spt/services/PaymentService"; import { ProfileFixerService } from "@spt/services/ProfileFixerService"; -import { ICloner } from "@spt/utils/cloners/ICloner"; import { HttpResponseUtil } from "@spt/utils/HttpResponseUtil"; import { ObjectId } from "@spt/utils/ObjectId"; import { RandomUtil } from "@spt/utils/RandomUtil"; import { TimeUtil } from "@spt/utils/TimeUtil"; +import { ICloner } from "@spt/utils/cloners/ICloner"; +import { inject, injectable } from "tsyringe"; @injectable() -export class RepeatableQuestController -{ +export class RepeatableQuestController { protected questConfig: IQuestConfig; constructor( @@ -54,8 +50,7 @@ export class RepeatableQuestController @inject("QuestHelper") protected questHelper: QuestHelper, @inject("ConfigServer") protected configServer: ConfigServer, @inject("PrimaryCloner") protected cloner: ICloner, - ) - { + ) { this.questConfig = this.configServer.getConfig(ConfigTypes.QUEST); } @@ -84,30 +79,26 @@ export class RepeatableQuestController * * @returns {array} Array of "repeatableQuestObjects" as described above */ - public getClientRepeatableQuests(sessionID: string): IPmcDataRepeatableQuest[] - { + public getClientRepeatableQuests(sessionID: string): IPmcDataRepeatableQuest[] { const returnData: Array = []; const fullProfile = this.profileHelper.getFullProfile(sessionID)!; const pmcData = fullProfile.characters.pmc; const currentTime = this.timeUtil.getTimestamp(); // Daily / weekly / Daily_Savage - for (const repeatableConfig of this.questConfig.repeatableQuests) - { + for (const repeatableConfig of this.questConfig.repeatableQuests) { // Get daily/weekly data from profile, add empty object if missing const generatedRepeatables = this.getRepeatableQuestSubTypeFromProfile(repeatableConfig, pmcData); const repeatableTypeLower = repeatableConfig.name.toLowerCase(); const canAccessRepeatables = this.canProfileAccessRepeatableQuests(repeatableConfig, pmcData); - if (!canAccessRepeatables) - { + if (!canAccessRepeatables) { // Dont send any repeatables, even existing ones continue; } // Existing repeatables are still valid, add to return data and move to next sub-type - if (currentTime < generatedRepeatables.endTime - 1) - { + if (currentTime < generatedRepeatables.endTime - 1) { returnData.push(generatedRepeatables); this.logger.debug(`[Quest Check] ${repeatableTypeLower} quests are still valid.`); @@ -132,12 +123,10 @@ export class RepeatableQuestController const questTypePool = this.generateQuestPool(repeatableConfig, pmcData.Info.Level); // Add repeatable quests of this loops sub-type (daily/weekly) - for (let i = 0; i < this.getQuestCount(repeatableConfig, pmcData); i++) - { + for (let i = 0; i < this.getQuestCount(repeatableConfig, pmcData); i++) { let quest: IRepeatableQuest | undefined = undefined; let lifeline = 0; - while (!quest && questTypePool.types.length > 0) - { + while (!quest && questTypePool.types.length > 0) { quest = this.repeatableQuestGenerator.generateRepeatableQuest( pmcData.Info.Level, pmcData.TradersInfo, @@ -145,8 +134,7 @@ export class RepeatableQuestController repeatableConfig, ); lifeline++; - if (lifeline > 10) - { + if (lifeline > 10) { this.logger.debug( "We were stuck in repeatable quest generation. This should never happen. Please report", ); @@ -155,8 +143,7 @@ export class RepeatableQuestController } // check if there are no more quest types available - if (questTypePool.types.length === 0) - { + if (questTypePool.types.length === 0) { break; } quest.side = repeatableConfig.side; @@ -170,8 +157,7 @@ export class RepeatableQuestController fullProfile.spt.freeRepeatableRefreshUsedCount[repeatableTypeLower] = 0; // Create stupid redundant change requirements from quest data - for (const quest of generatedRepeatables.activeQuests) - { + for (const quest of generatedRepeatables.activeQuests) { generatedRepeatables.changeRequirement[quest._id] = { changeCost: quest.changeCost, changeStandingCost: this.randomUtil.getArrayValue([0, 0.01]), // Randomise standing cost to replace @@ -202,20 +188,16 @@ export class RepeatableQuestController * @param generatedRepeatables Repeatables to process (daily/weekly) * @param pmcData Player profile */ - protected processExpiredQuests(generatedRepeatables: IPmcDataRepeatableQuest, pmcData: IPmcData): void - { + protected processExpiredQuests(generatedRepeatables: IPmcDataRepeatableQuest, pmcData: IPmcData): void { const questsToKeep = []; - for (const activeQuest of generatedRepeatables.activeQuests) - { + for (const activeQuest of generatedRepeatables.activeQuests) { const questStatusInProfile = pmcData.Quests.find((quest) => quest.qid === activeQuest._id); - if (!questStatusInProfile) - { + if (!questStatusInProfile) { continue; } // Keep finished quests in list so player can hand in - if (questStatusInProfile.status === QuestStatus.AvailableForFinish) - { + if (questStatusInProfile.status === QuestStatus.AvailableForFinish) { questsToKeep.push(activeQuest); this.logger.debug( `Keeping repeatable quest: ${activeQuest._id} in activeQuests since it is available to hand in`, @@ -243,17 +225,14 @@ export class RepeatableQuestController * @param pmcData Player profile * @returns True if profile is allowed to access dailies */ - protected canProfileAccessRepeatableQuests(repeatableConfig: IRepeatableQuestConfig, pmcData: IPmcData): boolean - { + protected canProfileAccessRepeatableQuests(repeatableConfig: IRepeatableQuestConfig, pmcData: IPmcData): boolean { // PMC and daily quests not unlocked yet - if (repeatableConfig.side === "Pmc" && !this.playerHasDailyPmcQuestsUnlocked(pmcData, repeatableConfig)) - { + if (repeatableConfig.side === "Pmc" && !this.playerHasDailyPmcQuestsUnlocked(pmcData, repeatableConfig)) { return false; } // Scav and daily quests not unlocked yet - if (repeatableConfig.side === "Scav" && !this.playerHasDailyScavQuestsUnlocked(pmcData)) - { + if (repeatableConfig.side === "Scav" && !this.playerHasDailyScavQuestsUnlocked(pmcData)) { this.logger.debug("Daily scav quests still locked, Intel center not built"); return false; @@ -267,11 +246,10 @@ export class RepeatableQuestController * @param pmcData Player profile to check * @returns True if unlocked */ - protected playerHasDailyScavQuestsUnlocked(pmcData: IPmcData): boolean - { - return pmcData?.Hideout?.Areas - ?.find((hideoutArea) => hideoutArea.type === HideoutAreas.INTEL_CENTER) - ?.level >= 1; + protected playerHasDailyScavQuestsUnlocked(pmcData: IPmcData): boolean { + return ( + pmcData?.Hideout?.Areas?.find((hideoutArea) => hideoutArea.type === HideoutAreas.INTEL_CENTER)?.level >= 1 + ); } /** @@ -280,8 +258,7 @@ export class RepeatableQuestController * @param repeatableConfig Config of daily type to check * @returns True if unlocked */ - protected playerHasDailyPmcQuestsUnlocked(pmcData: IPmcData, repeatableConfig: IRepeatableQuestConfig): boolean - { + protected playerHasDailyPmcQuestsUnlocked(pmcData: IPmcData, repeatableConfig: IRepeatableQuestConfig): boolean { return pmcData.Info.Level >= repeatableConfig.minPlayerLevel; } @@ -291,17 +268,15 @@ export class RepeatableQuestController * @param pmcData Player profile * @returns Quest count */ - protected getQuestCount(repeatableConfig: IRepeatableQuestConfig, pmcData: IPmcData): number - { + protected getQuestCount(repeatableConfig: IRepeatableQuestConfig, pmcData: IPmcData): number { if ( - repeatableConfig.name.toLowerCase() === "daily" - && this.profileHelper.hasEliteSkillLevel(SkillTypes.CHARISMA, pmcData) - ) - { + repeatableConfig.name.toLowerCase() === "daily" && + this.profileHelper.hasEliteSkillLevel(SkillTypes.CHARISMA, pmcData) + ) { // Elite charisma skill gives extra daily quest(s) return ( - repeatableConfig.numQuests - + this.databaseService.getGlobals().config.SkillsSettings.Charisma.BonusSettings.EliteBonusSettings + repeatableConfig.numQuests + + this.databaseService.getGlobals().config.SkillsSettings.Charisma.BonusSettings.EliteBonusSettings .RepeatableQuestExtraCount ); } @@ -318,13 +293,13 @@ export class RepeatableQuestController protected getRepeatableQuestSubTypeFromProfile( repeatableConfig: IRepeatableQuestConfig, pmcData: IPmcData, - ): IPmcDataRepeatableQuest - { + ): IPmcDataRepeatableQuest { // Get from profile, add if missing - let repeatableQuestDetails = pmcData.RepeatableQuests - .find((repeatable) => repeatable.name === repeatableConfig.name); - if (!repeatableQuestDetails) // Not in profile, generate - { + let repeatableQuestDetails = pmcData.RepeatableQuests.find( + (repeatable) => repeatable.name === repeatableConfig.name, + ); + if (!repeatableQuestDetails) { + // Not in profile, generate const hasAccess = this.profileHelper.hasAccessToRepeatableFreeRefreshSystem(pmcData); repeatableQuestDetails = { id: repeatableConfig.id, @@ -347,13 +322,11 @@ export class RepeatableQuestController /** * Just for debug reasons. Draws dailies a random assort of dailies extracted from dumps */ - public generateDebugDailies(dailiesPool: any, factory: any, number: number): any - { + public generateDebugDailies(dailiesPool: any, factory: any, number: number): any { let randomQuests = []; let numberOfQuests = number; - if (factory) - { + if (factory) { // First is factory extract always add for debugging randomQuests.push(dailiesPool[0]); numberOfQuests -= 1; @@ -361,14 +334,11 @@ export class RepeatableQuestController randomQuests = randomQuests.concat(this.randomUtil.drawRandomFromList(dailiesPool, numberOfQuests, false)); - for (const element of randomQuests) - { + for (const element of randomQuests) { element._id = this.objectId.generate(); const conditions = element.conditions.AvailableForFinish; - for (const condition of conditions) - { - if ("counter" in condition._props) - { + for (const condition of conditions) { + if ("counter" in condition._props) { condition._props.counter.id = this.objectId.generate(); } } @@ -384,18 +354,15 @@ export class RepeatableQuestController * @param pmcLevel level of pmc generating quest pool * @returns IQuestTypePool */ - protected generateQuestPool(repeatableConfig: IRepeatableQuestConfig, pmcLevel: number): IQuestTypePool - { + protected generateQuestPool(repeatableConfig: IRepeatableQuestConfig, pmcLevel: number): IQuestTypePool { const questPool = this.createBaseQuestPool(repeatableConfig); // Get the allowed locations based on the PMC's level const locations = this.getAllowedLocationsForPmcLevel(repeatableConfig.locations, pmcLevel); // Populate Exploration and Pickup quest locations - for (const location in locations) - { - if (location !== ELocationName.ANY) - { + for (const location in locations) { + if (location !== ELocationName.ANY) { questPool.pool.Exploration.locations[location] = locations[location]; questPool.pool.Pickup.locations[location] = locations[location]; } @@ -408,21 +375,18 @@ export class RepeatableQuestController const targetsConfig = this.repeatableQuestHelper.probabilityObjectArray(eliminationConfig.targets); // Populate Elimination quest targets and their locations - for (const { data: target, key: targetKey } of targetsConfig) - { + for (const { data: target, key: targetKey } of targetsConfig) { // Target is boss - if (target.isBoss) - { + if (target.isBoss) { questPool.pool.Elimination.targets[targetKey] = { locations: ["any"] }; - } - else - { + } else { // Non-boss targets const possibleLocations = Object.keys(locations); - const allowedLocations = (targetKey === "Savage") - ? possibleLocations.filter((location) => location !== "laboratory") // Exclude labs for Savage targets. - : possibleLocations; + const allowedLocations = + targetKey === "Savage" + ? possibleLocations.filter((location) => location !== "laboratory") // Exclude labs for Savage targets. + : possibleLocations; questPool.pool.Elimination.targets[targetKey] = { locations: allowedLocations }; } @@ -431,8 +395,7 @@ export class RepeatableQuestController return questPool; } - protected createBaseQuestPool(repeatableConfig: IRepeatableQuestConfig): IQuestTypePool - { + protected createBaseQuestPool(repeatableConfig: IRepeatableQuestConfig): IQuestTypePool { return { types: repeatableConfig.types.slice(), pool: { Exploration: { locations: {} }, Elimination: { targets: {} }, Pickup: { locations: {} } }, @@ -448,23 +411,18 @@ export class RepeatableQuestController protected getAllowedLocationsForPmcLevel( locations: Record, pmcLevel: number, - ): Partial> - { + ): Partial> { const allowedLocation: Partial> = {}; - for (const location in locations) - { + for (const location in locations) { const locationNames = []; - for (const locationName of locations[location]) - { - if (this.isPmcLevelAllowedOnLocation(locationName, pmcLevel)) - { + for (const locationName of locations[location]) { + if (this.isPmcLevelAllowedOnLocation(locationName, pmcLevel)) { locationNames.push(locationName); } } - if (locationNames.length > 0) - { + if (locationNames.length > 0) { allowedLocation[location] = locationNames; } } @@ -478,36 +436,29 @@ export class RepeatableQuestController * @param pmcLevel The level of the pmc * @returns True if the given pmc level is allowed to access the given location */ - protected isPmcLevelAllowedOnLocation(location: string, pmcLevel: number): boolean - { + protected isPmcLevelAllowedOnLocation(location: string, pmcLevel: number): boolean { // All PMC levels are allowed for 'any' location requirement - if (location === ELocationName.ANY) - { + if (location === ELocationName.ANY) { return true; } const locationBase = this.databaseService.getLocation(location.toLowerCase())?.base; - if (!locationBase) - { + if (!locationBase) { return true; } return pmcLevel <= locationBase.RequiredPlayerLevelMax && pmcLevel >= locationBase.RequiredPlayerLevelMin; } - public debugLogRepeatableQuestIds(pmcData: IPmcData): void - { - for (const repeatable of pmcData.RepeatableQuests) - { + public debugLogRepeatableQuestIds(pmcData: IPmcData): void { + for (const repeatable of pmcData.RepeatableQuests) { const activeQuestsIds = []; const inactiveQuestsIds = []; - for (const active of repeatable.activeQuests) - { + for (const active of repeatable.activeQuests) { activeQuestsIds.push(active._id); } - for (const inactive of repeatable.inactiveQuests) - { + for (const inactive of repeatable.inactiveQuests) { inactiveQuestsIds.push(inactive._id); } @@ -529,15 +480,16 @@ export class RepeatableQuestController pmcData: IPmcData, changeRequest: IRepeatableQuestChangeRequest, sessionID: string, - ): IItemEventRouterResponse - { + ): IItemEventRouterResponse { const output = this.eventOutputHolder.getOutput(sessionID); const fullProfile = this.profileHelper.getFullProfile(sessionID); // Check for existing quest in (daily/weekly/scav arrays) - const { quest: questToReplace, repeatableType: repeatablesInProfile } - = this.getRepeatableById(changeRequest.qid, pmcData); + const { quest: questToReplace, repeatableType: repeatablesInProfile } = this.getRepeatableById( + changeRequest.qid, + pmcData, + ); // Subtype name of quest - daily/weekly/scav const repeatableTypeLower = repeatablesInProfile.name.toLowerCase(); @@ -546,8 +498,9 @@ export class RepeatableQuestController const replacedQuestTraderId = questToReplace.traderId; // Update active quests to exclude the quest we're replacing - repeatablesInProfile.activeQuests = repeatablesInProfile.activeQuests - .filter((quest) => quest._id !== changeRequest.qid); + repeatablesInProfile.activeQuests = repeatablesInProfile.activeQuests.filter( + (quest) => quest._id !== changeRequest.qid, + ); // Save for later cost calculation const previousChangeRequirement = this.cloner.clone(repeatablesInProfile.changeRequirement[changeRequest.qid]); @@ -556,15 +509,14 @@ export class RepeatableQuestController delete repeatablesInProfile.changeRequirement[changeRequest.qid]; // Get config for this repeatable sub-type (daily/weekly/scav) - const repeatableConfig = this.questConfig.repeatableQuests - .find((config) => config.name === repeatablesInProfile.name, - ); + const repeatableConfig = this.questConfig.repeatableQuests.find( + (config) => config.name === repeatablesInProfile.name, + ); // Generate meta-data for what type/levelrange of quests can be generated for player const allowedQuestTypes = this.generateQuestPool(repeatableConfig, pmcData.Info.Level); const newRepeatableQuest = this.attemptToGenerateRepeatableQuest(pmcData, allowedQuestTypes, repeatableConfig); - if (!newRepeatableQuest) - { + if (!newRepeatableQuest) { // Unable to find quest being replaced const message = `Unable to generate repeatable quest of type: ${repeatableTypeLower} to replace trader: ${replacedQuestTraderId} quest ${changeRequest.qid}`; this.logger.error(message); @@ -593,20 +545,17 @@ export class RepeatableQuestController // Check if we should charge player for replacing quest const isFreeToReplace = this.useFreeRefreshIfAvailable(fullProfile, repeatablesInProfile, repeatableTypeLower); - if (!isFreeToReplace) - { + if (!isFreeToReplace) { // Reduce standing with trader for not doing their quest const traderOfReplacedQuest = pmcData.TradersInfo[replacedQuestTraderId]; traderOfReplacedQuest.standing -= previousChangeRequirement.changeStandingCost; const charismaBonus = this.profileHelper.getSkillFromProfile(pmcData, SkillTypes.CHARISMA)?.Progress ?? 0; - for (const cost of previousChangeRequirement.changeCost) - { + for (const cost of previousChangeRequirement.changeCost) { // Not free, Charge player + appy charisma bonus to cost of replacement - cost.count = Math.trunc(cost.count * (1 - (Math.trunc((charismaBonus) / 100) * 0.001)) ?? 1); + cost.count = Math.trunc(cost.count * (1 - Math.trunc(charismaBonus / 100) * 0.001) ?? 1); this.paymentService.addPaymentToOutput(pmcData, cost.templateId, cost.count, sessionID, output); - if (output.warnings.length > 0) - { + if (output.warnings.length > 0) { return output; } } @@ -618,8 +567,7 @@ export class RepeatableQuestController // Purge inactive repeatables repeatableToChangeClone.inactiveQuests = []; - if (!repeatableToChangeClone) - { + if (!repeatableToChangeClone) { // Unable to find quest being replaced const message = this.localisationService.getText("quest-unable_to_find_repeatable_to_replace"); this.logger.error(message); @@ -642,15 +590,11 @@ export class RepeatableQuestController * @param pmcData Profile that contains quests to look through * @returns IGetRepeatableByIdResult */ - protected getRepeatableById(questId: string, pmcData: IPmcData): IGetRepeatableByIdResult - { - for (const repeatablesInProfile of pmcData.RepeatableQuests) - { + protected getRepeatableById(questId: string, pmcData: IPmcData): IGetRepeatableByIdResult { + for (const repeatablesInProfile of pmcData.RepeatableQuests) { // Check for existing quest in (daily/weekly/scav arrays) - const questToReplace = repeatablesInProfile.activeQuests - .find((repeatable) => repeatable._id === questId); - if (!questToReplace) - { + const questToReplace = repeatablesInProfile.activeQuests.find((repeatable) => repeatable._id === questId); + if (!questToReplace) { // Not found, skip to next repeatable sub-type continue; } @@ -665,14 +609,11 @@ export class RepeatableQuestController pmcData: IPmcData, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig, - ): IRepeatableQuest - { + ): IRepeatableQuest { const maxAttempts = 10; let newRepeatableQuest: IRepeatableQuest = undefined; let attempts = 0; - while (attempts < maxAttempts - && questTypePool.types.length > 0) - { + while (attempts < maxAttempts && questTypePool.types.length > 0) { newRepeatableQuest = this.repeatableQuestGenerator.generateRepeatableQuest( pmcData.Info.Level, pmcData.TradersInfo, @@ -680,8 +621,7 @@ export class RepeatableQuestController repeatableConfig, ); - if (newRepeatableQuest) - { + if (newRepeatableQuest) { // Successfully generated a quest, exit loop break; } @@ -689,11 +629,8 @@ export class RepeatableQuestController attempts++; } - if (attempts > maxAttempts) - { - this.logger.debug( - "We were stuck in repeatable quest generation. This should never happen. Please report", - ); + if (attempts > maxAttempts) { + this.logger.debug("We were stuck in repeatable quest generation. This should never happen. Please report"); } return newRepeatableQuest; @@ -710,11 +647,10 @@ export class RepeatableQuestController protected useFreeRefreshIfAvailable( fullProfile: ISptProfile, repeatableSubType: IPmcDataRepeatableQuest, - repeatableTypeName: string): boolean - { + repeatableTypeName: string, + ): boolean { // No free refreshes, exit early - if (repeatableSubType.freeChangesAvailable <= 0) - { + if (repeatableSubType.freeChangesAvailable <= 0) { // Reset counter to 0 repeatableSubType.freeChangesAvailable = 0; @@ -722,12 +658,12 @@ export class RepeatableQuestController } // Only certain game versions have access to free refreshes - const hasAccessToFreeRefreshSystem - = this.profileHelper.hasAccessToRepeatableFreeRefreshSystem(fullProfile.characters.pmc); + const hasAccessToFreeRefreshSystem = this.profileHelper.hasAccessToRepeatableFreeRefreshSystem( + fullProfile.characters.pmc, + ); // If the player has access and available refreshes: - if (hasAccessToFreeRefreshSystem) - { + if (hasAccessToFreeRefreshSystem) { // Initialize/retrieve free refresh count for the desired subtype: daily/weekly fullProfile.spt.freeRepeatableRefreshUsedCount ||= {}; const repeatableRefreshCounts = fullProfile.spt.freeRepeatableRefreshUsedCount; diff --git a/project/src/controllers/TradeController.ts b/project/src/controllers/TradeController.ts index 9f81f326..34f32a34 100644 --- a/project/src/controllers/TradeController.ts +++ b/project/src/controllers/TradeController.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { ItemHelper } from "@spt/helpers/ItemHelper"; import { ProfileHelper } from "@spt/helpers/ProfileHelper"; import { RagfairOfferHelper } from "@spt/helpers/RagfairOfferHelper"; @@ -11,10 +10,7 @@ import { IItemEventRouterResponse } from "@spt/models/eft/itemEvent/IItemEventRo import { IRagfairOffer } from "@spt/models/eft/ragfair/IRagfairOffer"; import { IProcessBaseTradeRequestData } from "@spt/models/eft/trade/IProcessBaseTradeRequestData"; import { IProcessBuyTradeRequestData } from "@spt/models/eft/trade/IProcessBuyTradeRequestData"; -import { - IOfferRequest, - IProcessRagfairTradeRequestData, -} from "@spt/models/eft/trade/IProcessRagfairTradeRequestData"; +import { IOfferRequest, IProcessRagfairTradeRequestData } from "@spt/models/eft/trade/IProcessRagfairTradeRequestData"; import { IProcessSellTradeRequestData } from "@spt/models/eft/trade/IProcessSellTradeRequestData"; import { ISellScavItemsToFenceRequestData } from "@spt/models/eft/trade/ISellScavItemsToFenceRequestData"; import { BackendErrorCodes } from "@spt/models/enums/BackendErrorCodes"; @@ -37,10 +33,10 @@ import { HashUtil } from "@spt/utils/HashUtil"; import { HttpResponseUtil } from "@spt/utils/HttpResponseUtil"; import { RandomUtil } from "@spt/utils/RandomUtil"; import { TimeUtil } from "@spt/utils/TimeUtil"; +import { inject, injectable } from "tsyringe"; @injectable() -export class TradeController -{ +export class TradeController { protected ragfairConfig: IRagfairConfig; protected traderConfig: ITraderConfig; @@ -62,8 +58,7 @@ export class TradeController @inject("RagfairPriceService") protected ragfairPriceService: RagfairPriceService, @inject("MailSendService") protected mailSendService: MailSendService, @inject("ConfigServer") protected configServer: ConfigServer, - ) - { + ) { this.ragfairConfig = this.configServer.getConfig(ConfigTypes.RAGFAIR); this.traderConfig = this.configServer.getConfig(ConfigTypes.TRADER); } @@ -73,13 +68,11 @@ export class TradeController pmcData: IPmcData, request: IProcessBaseTradeRequestData, sessionID: string, - ): IItemEventRouterResponse - { + ): IItemEventRouterResponse { const output = this.eventOutputHolder.getOutput(sessionID); // Buying - if (request.type === "buy_from_trader") - { + if (request.type === "buy_from_trader") { const foundInRaid = this.traderConfig.purchasesAreFoundInRaid; const buyData = request; this.tradeHelper.buyItem(pmcData, buyData, sessionID, foundInRaid, output); @@ -88,8 +81,7 @@ export class TradeController } // Selling - if (request.type === "sell_to_trader") - { + if (request.type === "sell_to_trader") { const sellData = request; this.tradeHelper.sellItem(pmcData, pmcData, sellData, sessionID, output); @@ -107,15 +99,12 @@ export class TradeController pmcData: IPmcData, request: IProcessRagfairTradeRequestData, sessionID: string, - ): IItemEventRouterResponse - { + ): IItemEventRouterResponse { const output = this.eventOutputHolder.getOutput(sessionID); - for (const offer of request.offers) - { + for (const offer of request.offers) { const fleaOffer = this.ragfairServer.getOffer(offer.id); - if (!fleaOffer) - { + if (!fleaOffer) { return this.httpResponse.appendErrorToOutput( output, `Offer with ID ${offer.id} not found`, @@ -123,8 +112,7 @@ export class TradeController ); } - if (offer.count === 0) - { + if (offer.count === 0) { const errorMessage = this.localisationService.getText( "ragfair-unable_to_purchase_0_count_item", this.itemHelper.getItem(fleaOffer.items[0]._tpl)[1]._name, @@ -133,18 +121,14 @@ export class TradeController } const sellerIsTrader = fleaOffer.user.memberType === MemberCategory.TRADER; - if (sellerIsTrader) - { + if (sellerIsTrader) { this.buyTraderItemFromRagfair(sessionID, pmcData, fleaOffer, offer, output); - } - else - { + } else { this.buyPmcItemFromRagfair(sessionID, pmcData, fleaOffer, offer, output); } // Exit loop early if problem found - if (output.warnings.length > 0) - { + if (output.warnings.length > 0) { return output; } } @@ -166,11 +150,9 @@ export class TradeController fleaOffer: IRagfairOffer, requestOffer: IOfferRequest, output: IItemEventRouterResponse, - ): void - { + ): void { // Skip buying items when player doesn't have needed loyalty - if (this.playerLacksTraderLoyaltyLevelToBuyOffer(fleaOffer, pmcData)) - { + if (this.playerLacksTraderLoyaltyLevelToBuyOffer(fleaOffer, pmcData)) { const errorMessage = `Unable to buy item: ${fleaOffer.items[0]._tpl} from trader: ${fleaOffer.user.id} as loyalty level too low, skipping`; this.logger.debug(errorMessage); @@ -206,8 +188,7 @@ export class TradeController fleaOffer: IRagfairOffer, requestOffer: IOfferRequest, output: IItemEventRouterResponse, - ): void - { + ): void { const buyData: IProcessBuyTradeRequestData = { Action: "TradingConfirm", type: "buy_from_ragfair", @@ -226,8 +207,7 @@ export class TradeController this.ragfairConfig.dynamic.purchasesAreFoundInRaid, output, ); - if (output.warnings.length > 0) - { + if (output.warnings.length > 0) { return; } @@ -236,8 +216,7 @@ export class TradeController const offerBuyCount = requestOffer.count; const isPlayerOffer = this.isPlayerOffer(fleaOffer._id, fleaOffer.user?.id); - if (isPlayerOffer) - { + if (isPlayerOffer) { // Complete selling the offer now its been purchased this.ragfairOfferHelper.completeOffer(offerOwnerId, fleaOffer, offerBuyCount); @@ -254,17 +233,14 @@ export class TradeController * @param offerOwnerId Owner id * @returns true if offer was made by a player */ - protected isPlayerOffer(offerId: string, offerOwnerId: string): boolean - { + protected isPlayerOffer(offerId: string, offerOwnerId: string): boolean { // No ownerid, not player offer - if (!offerOwnerId) - { + if (!offerOwnerId) { return false; } const offerCreatorProfile = this.profileHelper.getPmcProfile(offerOwnerId); - if (!offerCreatorProfile || offerCreatorProfile.RagfairInfo.offers?.length === 0) - { + if (!offerCreatorProfile || offerCreatorProfile.RagfairInfo.offers?.length === 0) { // No profile or no offers return false; } @@ -280,8 +256,7 @@ export class TradeController * @param pmcData Player profile * @returns True if player can buy offer */ - protected playerLacksTraderLoyaltyLevelToBuyOffer(fleaOffer: IRagfairOffer, pmcData: IPmcData): boolean - { + protected playerLacksTraderLoyaltyLevelToBuyOffer(fleaOffer: IRagfairOffer, pmcData: IPmcData): boolean { return fleaOffer.loyaltyLevel > pmcData.TradersInfo[fleaOffer.user.id].loyaltyLevel; } @@ -290,8 +265,7 @@ export class TradeController pmcData: IPmcData, request: ISellScavItemsToFenceRequestData, sessionId: string, - ): IItemEventRouterResponse - { + ): IItemEventRouterResponse { const output = this.eventOutputHolder.getOutput(sessionId); this.mailMoneyToPlayer(sessionId, request.totalValue, Traders.FENCE); @@ -305,8 +279,7 @@ export class TradeController * @param trader Trader to sell items to * @param output IItemEventRouterResponse */ - protected mailMoneyToPlayer(sessionId: string, roublesToSend: number, trader: Traders): void - { + protected mailMoneyToPlayer(sessionId: string, roublesToSend: number, trader: Traders): void { this.logger.debug(`Selling scav items to fence for ${roublesToSend} roubles`); // Create single currency item with all currency on it @@ -325,7 +298,7 @@ export class TradeController this.traderHelper.getTraderById(trader), MessageType.MESSAGE_WITH_ITEMS, this.randomUtil.getArrayValue(this.databaseService.getTrader(trader).dialogue.soldItems), - curencyReward.flatMap((x) => x), + curencyReward.flat(), this.timeUtil.getHoursAsSeconds(72), ); } @@ -343,21 +316,18 @@ export class TradeController items: Item[], handbookPrices: Record, traderDetails: ITraderBase, - ): number - { + ): number { const itemWithChildren = this.itemHelper.findAndReturnChildrenAsItems(items, parentItemId); let totalPrice = 0; - for (const itemToSell of itemWithChildren) - { + for (const itemToSell of itemWithChildren) { const itemDetails = this.itemHelper.getItem(itemToSell._tpl); if ( !( - itemDetails[0] - && this.itemHelper.isOfBaseclasses(itemDetails[1]._id, traderDetails.items_buy.category) + itemDetails[0] && + this.itemHelper.isOfBaseclasses(itemDetails[1]._id, traderDetails.items_buy.category) ) - ) - { + ) { // Skip if tpl isn't item OR item doesn't fulfil match traders buy categories continue; } diff --git a/project/src/controllers/TraderController.ts b/project/src/controllers/TraderController.ts index 008d029e..16d36485 100644 --- a/project/src/controllers/TraderController.ts +++ b/project/src/controllers/TraderController.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { FenceBaseAssortGenerator } from "@spt/generators/FenceBaseAssortGenerator"; import { ProfileHelper } from "@spt/helpers/ProfileHelper"; import { TraderAssortHelper } from "@spt/helpers/TraderAssortHelper"; @@ -13,12 +12,12 @@ import { DatabaseService } from "@spt/services/DatabaseService"; import { FenceService } from "@spt/services/FenceService"; import { TraderAssortService } from "@spt/services/TraderAssortService"; import { TraderPurchasePersisterService } from "@spt/services/TraderPurchasePersisterService"; -import { ICloner } from "@spt/utils/cloners/ICloner"; import { TimeUtil } from "@spt/utils/TimeUtil"; +import { ICloner } from "@spt/utils/cloners/ICloner"; +import { inject, injectable } from "tsyringe"; @injectable() -export class TraderController -{ +export class TraderController { protected traderConfig: ITraderConfig; constructor( @@ -35,8 +34,7 @@ export class TraderController @inject("FenceBaseAssortGenerator") protected fenceBaseAssortGenerator: FenceBaseAssortGenerator, @inject("ConfigServer") protected configServer: ConfigServer, @inject("PrimaryCloner") protected cloner: ICloner, - ) - { + ) { this.traderConfig = this.configServer.getConfig(ConfigTypes.TRADER); } @@ -45,21 +43,17 @@ export class TraderController * Iterate over traders, ensure a pristine copy of their assorts is stored in traderAssortService * Store timestamp of next assort refresh in nextResupply property of traders .base object */ - public load(): void - { + public load(): void { const nextHourTimestamp = this.timeUtil.getTimestampOfNextHour(); const traderResetStartsWithServer = this.traderConfig.tradersResetFromServerStart; const traders = this.databaseService.getTraders(); - for (const traderId in traders) - { - if (traderId === "ragfair" || traderId === Traders.LIGHTHOUSEKEEPER) - { + for (const traderId in traders) { + if (traderId === "ragfair" || traderId === Traders.LIGHTHOUSEKEEPER) { continue; } - if (traderId === Traders.FENCE) - { + if (traderId === Traders.FENCE) { this.fenceBaseAssortGenerator.generateFenceBaseAssorts(); this.fenceService.generateFenceAssorts(); continue; @@ -68,8 +62,7 @@ export class TraderController const trader = traders[traderId]; // Create dict of trader assorts on server start - if (!this.traderAssortService.getPristineTraderAssort(traderId)) - { + if (!this.traderAssortService.getPristineTraderAssort(traderId)) { const assortsClone = this.cloner.clone(trader.assort); this.traderAssortService.setPristineTraderAssort(traderId, assortsClone); } @@ -90,19 +83,14 @@ export class TraderController * Fence is handled slightly differently * @returns has run */ - public update(): boolean - { - for (const traderId in this.databaseService.getTables().traders) - { - if (traderId === "ragfair" || traderId === Traders.LIGHTHOUSEKEEPER) - { + public update(): boolean { + for (const traderId in this.databaseService.getTables().traders) { + if (traderId === "ragfair" || traderId === Traders.LIGHTHOUSEKEEPER) { continue; } - if (traderId === Traders.FENCE) - { - if (this.fenceService.needsPartialRefresh()) - { + if (traderId === Traders.FENCE) { + if (this.fenceService.needsPartialRefresh()) { this.fenceService.performPartialRefresh(); } @@ -111,8 +99,7 @@ export class TraderController // Trader needs to be refreshed const trader = this.databaseService.getTrader(traderId); - if (this.traderAssortHelper.traderAssortsHaveExpired(traderId)) - { + if (this.traderAssortHelper.traderAssortsHaveExpired(traderId)) { this.traderAssortHelper.resetExpiredTrader(trader); // Reset purchase data per trader as they have independent reset times @@ -129,21 +116,17 @@ export class TraderController * @param sessionID Session id * @returns array if ITraderBase objects */ - public getAllTraders(sessionID: string): ITraderBase[] - { + public getAllTraders(sessionID: string): ITraderBase[] { const traders: ITraderBase[] = []; const pmcData = this.profileHelper.getPmcProfile(sessionID); - for (const traderID in this.databaseService.getTables().traders) - { - if (this.databaseService.getTables().traders[traderID].base._id === "ragfair") - { + for (const traderID in this.databaseService.getTables().traders) { + if (this.databaseService.getTables().traders[traderID].base._id === "ragfair") { continue; } traders.push(this.traderHelper.getTrader(traderID, sessionID)); - if (pmcData.Info) - { + if (pmcData.Info) { this.traderHelper.lvlUp(traderID, pmcData); } } @@ -157,15 +140,12 @@ export class TraderController * @param traderB Second trader to compare * @returns 1,-1 or 0 */ - protected sortByTraderId(traderA: ITraderBase, traderB: ITraderBase): number - { - if (traderA._id > traderB._id) - { + protected sortByTraderId(traderA: ITraderBase, traderB: ITraderBase): number { + if (traderA._id > traderB._id) { return 1; } - if (traderA._id < traderB._id) - { + if (traderA._id < traderB._id) { return -1; } @@ -173,14 +153,12 @@ export class TraderController } /** Handle client/trading/api/getTrader */ - public getTrader(sessionID: string, traderID: string): ITraderBase - { + public getTrader(sessionID: string, traderID: string): ITraderBase { return this.traderHelper.getTrader(sessionID, traderID); } /** Handle client/trading/api/getTraderAssort */ - public getAssort(sessionId: string, traderId: string): ITraderAssort - { + public getAssort(sessionId: string, traderId: string): ITraderAssort { return this.traderAssortHelper.getAssort(sessionId, traderId); } } diff --git a/project/src/controllers/WeatherController.ts b/project/src/controllers/WeatherController.ts index 5ab34fb3..0eb464d1 100644 --- a/project/src/controllers/WeatherController.ts +++ b/project/src/controllers/WeatherController.ts @@ -1,16 +1,15 @@ -import { inject, injectable } from "tsyringe"; import { WeatherGenerator } from "@spt/generators/WeatherGenerator"; import { IWeatherData } from "@spt/models/eft/weather/IWeatherData"; import { ConfigTypes } from "@spt/models/enums/ConfigTypes"; import { IWeatherConfig } from "@spt/models/spt/config/IWeatherConfig"; import { ILogger } from "@spt/models/spt/utils/ILogger"; -import { ConfigServer } from "@spt/servers/ConfigServer"; import { IGetLocalWeatherResponseData } from "@spt/models/spt/weather/IGetLocalWeatherResponseData"; +import { ConfigServer } from "@spt/servers/ConfigServer"; import { SeasonalEventService } from "@spt/services/SeasonalEventService"; +import { inject, injectable } from "tsyringe"; @injectable() -export class WeatherController -{ +export class WeatherController { protected weatherConfig: IWeatherConfig; constructor( @@ -18,14 +17,12 @@ export class WeatherController @inject("PrimaryLogger") protected logger: ILogger, @inject("ConfigServer") protected configServer: ConfigServer, @inject("SeasonalEventService") protected seasonalEventService: SeasonalEventService, - ) - { + ) { this.weatherConfig = this.configServer.getConfig(ConfigTypes.WEATHER); } /** Handle client/weather */ - public generate(): IWeatherData - { + public generate(): IWeatherData { let result: IWeatherData = { acceleration: 0, time: "", date: "", weather: undefined, season: 1 }; // defaults, hydrated below result = this.weatherGenerator.calculateGameTime(result); @@ -38,14 +35,15 @@ export class WeatherController * Get the current in-raid time (MUST HAVE PLAYER LOGGED INTO CLIENT TO WORK) * @returns Date object */ - public getCurrentInRaidTime(): Date - { + public getCurrentInRaidTime(): Date { return this.weatherGenerator.getInRaidTime(); } - public generateLocal(sesssionID: string): IGetLocalWeatherResponseData - { - let result: IGetLocalWeatherResponseData = { season: this.seasonalEventService.getActiveWeatherSeason(), weather: [] }; + public generateLocal(sesssionID: string): IGetLocalWeatherResponseData { + const result: IGetLocalWeatherResponseData = { + season: this.seasonalEventService.getActiveWeatherSeason(), + weather: [], + }; result.weather.push(this.weatherGenerator.generateWeather()); diff --git a/project/src/controllers/WishlistController.ts b/project/src/controllers/WishlistController.ts index 373719e2..dbe924ec 100644 --- a/project/src/controllers/WishlistController.ts +++ b/project/src/controllers/WishlistController.ts @@ -1,22 +1,22 @@ -import { inject, injectable } from "tsyringe"; import { IPmcData } from "@spt/models/eft/common/IPmcData"; import { IItemEventRouterResponse } from "@spt/models/eft/itemEvent/IItemEventRouterResponse"; import { IAddToWishlistRequest } from "@spt/models/eft/wishlist/IAddToWishlistRequest"; import { IChangeWishlistItemCategoryRequest } from "@spt/models/eft/wishlist/IChangeWishlistItemCategoryRequest"; import { IRemoveFromWishlistRequest } from "@spt/models/eft/wishlist/IRemoveFromWishlistRequest"; import { EventOutputHolder } from "@spt/routers/EventOutputHolder"; +import { inject, injectable } from "tsyringe"; @injectable() -export class WishlistController -{ - constructor(@inject("EventOutputHolder") protected eventOutputHolder: EventOutputHolder) - {} +export class WishlistController { + constructor(@inject("EventOutputHolder") protected eventOutputHolder: EventOutputHolder) {} /** Handle AddToWishList */ - public addToWishList(pmcData: IPmcData, request: IAddToWishlistRequest, sessionID: string): IItemEventRouterResponse - { - for (const itemId of Object.keys(request.items)) - { + public addToWishList( + pmcData: IPmcData, + request: IAddToWishlistRequest, + sessionID: string, + ): IItemEventRouterResponse { + for (const itemId of Object.keys(request.items)) { pmcData.WishList[itemId] = request.items[itemId]; } @@ -28,10 +28,8 @@ export class WishlistController pmcData: IPmcData, request: IRemoveFromWishlistRequest, sessionID: string, - ): IItemEventRouterResponse - { - for (const itemId of request.items) - { + ): IItemEventRouterResponse { + for (const itemId of request.items) { delete pmcData.WishList[itemId]; } @@ -43,8 +41,7 @@ export class WishlistController pmcData: IPmcData, request: IChangeWishlistItemCategoryRequest, sessionID: string, - ): IItemEventRouterResponse - { + ): IItemEventRouterResponse { pmcData.WishList[request.item] = request.category; return this.eventOutputHolder.getOutput(sessionID); diff --git a/project/src/di/Container.ts b/project/src/di/Container.ts index d2653ab2..2663a5ce 100644 --- a/project/src/di/Container.ts +++ b/project/src/di/Container.ts @@ -1,4 +1,3 @@ -import { DependencyContainer, Lifecycle } from "tsyringe"; import { AchievementCallbacks } from "@spt/callbacks/AchievementCallbacks"; import { BotCallbacks } from "@spt/callbacks/BotCallbacks"; import { BuildsCallbacks } from "@spt/callbacks/BuildsCallbacks"; @@ -70,18 +69,18 @@ import { BotWeaponGenerator } from "@spt/generators/BotWeaponGenerator"; import { FenceBaseAssortGenerator } from "@spt/generators/FenceBaseAssortGenerator"; import { LocationLootGenerator } from "@spt/generators/LocationLootGenerator"; import { LootGenerator } from "@spt/generators/LootGenerator"; -import { PlayerScavGenerator } from "@spt/generators/PlayerScavGenerator"; import { PMCLootGenerator } from "@spt/generators/PMCLootGenerator"; +import { PlayerScavGenerator } from "@spt/generators/PlayerScavGenerator"; import { RagfairAssortGenerator } from "@spt/generators/RagfairAssortGenerator"; import { RagfairOfferGenerator } from "@spt/generators/RagfairOfferGenerator"; import { RepeatableQuestGenerator } from "@spt/generators/RepeatableQuestGenerator"; import { RepeatableQuestRewardGenerator } from "@spt/generators/RepeatableQuestRewardGenerator"; import { ScavCaseRewardGenerator } from "@spt/generators/ScavCaseRewardGenerator"; +import { WeatherGenerator } from "@spt/generators/WeatherGenerator"; import { BarrelInventoryMagGen } from "@spt/generators/weapongen/implementations/BarrelInventoryMagGen"; import { ExternalInventoryMagGen } from "@spt/generators/weapongen/implementations/ExternalInventoryMagGen"; import { InternalMagazineInventoryMagGen } from "@spt/generators/weapongen/implementations/InternalMagazineInventoryMagGen"; import { UbglExternalMagGen } from "@spt/generators/weapongen/implementations/UbglExternalMagGen"; -import { WeatherGenerator } from "@spt/generators/WeatherGenerator"; import { AssortHelper } from "@spt/helpers/AssortHelper"; import { BotDifficultyHelper } from "@spt/helpers/BotDifficultyHelper"; import { BotGeneratorHelper } from "@spt/helpers/BotGeneratorHelper"; @@ -133,6 +132,10 @@ import { PostSptModLoader } from "@spt/loaders/PostSptModLoader"; import { PreSptModLoader } from "@spt/loaders/PreSptModLoader"; import { IAsyncQueue } from "@spt/models/spt/utils/IAsyncQueue"; import { ILogger } from "@spt/models/spt/utils/ILogger"; +import { EventOutputHolder } from "@spt/routers/EventOutputHolder"; +import { HttpRouter } from "@spt/routers/HttpRouter"; +import { ImageRouter } from "@spt/routers/ImageRouter"; +import { ItemEventRouter } from "@spt/routers/ItemEventRouter"; import { BotDynamicRouter } from "@spt/routers/dynamic/BotDynamicRouter"; import { BundleDynamicRouter } from "@spt/routers/dynamic/BundleDynamicRouter"; import { CustomizationDynamicRouter } from "@spt/routers/dynamic/CustomizationDynamicRouter"; @@ -142,9 +145,6 @@ import { InraidDynamicRouter } from "@spt/routers/dynamic/InraidDynamicRouter"; import { LocationDynamicRouter } from "@spt/routers/dynamic/LocationDynamicRouter"; import { NotifierDynamicRouter } from "@spt/routers/dynamic/NotifierDynamicRouter"; import { TraderDynamicRouter } from "@spt/routers/dynamic/TraderDynamicRouter"; -import { EventOutputHolder } from "@spt/routers/EventOutputHolder"; -import { HttpRouter } from "@spt/routers/HttpRouter"; -import { ImageRouter } from "@spt/routers/ImageRouter"; import { CustomizationItemEventRouter } from "@spt/routers/item_events/CustomizationItemEventRouter"; import { HealthItemEventRouter } from "@spt/routers/item_events/HealthItemEventRouter"; import { HideoutItemEventRouter } from "@spt/routers/item_events/HideoutItemEventRouter"; @@ -156,7 +156,6 @@ import { RagfairItemEventRouter } from "@spt/routers/item_events/RagfairItemEven import { RepairItemEventRouter } from "@spt/routers/item_events/RepairItemEventRouter"; import { TradeItemEventRouter } from "@spt/routers/item_events/TradeItemEventRouter"; import { WishlistItemEventRouter } from "@spt/routers/item_events/WishlistItemEventRouter"; -import { ItemEventRouter } from "@spt/routers/ItemEventRouter"; import { HealthSaveLoadRouter } from "@spt/routers/save_load/HealthSaveLoadRouter"; import { InraidSaveLoadRouter } from "@spt/routers/save_load/InraidSaveLoadRouter"; import { InsuranceSaveLoadRouter } from "@spt/routers/save_load/InsuranceSaveLoadRouter"; @@ -188,23 +187,21 @@ import { TraderStaticRouter } from "@spt/routers/static/TraderStaticRouter"; import { WeatherStaticRouter } from "@spt/routers/static/WeatherStaticRouter"; import { ConfigServer } from "@spt/servers/ConfigServer"; import { DatabaseServer } from "@spt/servers/DatabaseServer"; -import { SptHttpListener } from "@spt/servers/http/SptHttpListener"; import { HttpServer } from "@spt/servers/HttpServer"; import { RagfairServer } from "@spt/servers/RagfairServer"; import { SaveServer } from "@spt/servers/SaveServer"; import { WebSocketServer } from "@spt/servers/WebSocketServer"; +import { SptHttpListener } from "@spt/servers/http/SptHttpListener"; import { IWebSocketConnectionHandler } from "@spt/servers/ws/IWebSocketConnectionHandler"; +import { SptWebSocketConnectionHandler } from "@spt/servers/ws/SptWebSocketConnectionHandler"; import { DefaultSptWebSocketMessageHandler } from "@spt/servers/ws/message/DefaultSptWebSocketMessageHandler"; import { ISptWebSocketMessageHandler } from "@spt/servers/ws/message/ISptWebSocketMessageHandler"; -import { SptWebSocketConnectionHandler } from "@spt/servers/ws/SptWebSocketConnectionHandler"; import { AirdropService } from "@spt/services/AirdropService"; import { BotEquipmentFilterService } from "@spt/services/BotEquipmentFilterService"; import { BotEquipmentModPoolService } from "@spt/services/BotEquipmentModPoolService"; import { BotGenerationCacheService } from "@spt/services/BotGenerationCacheService"; import { BotLootCacheService } from "@spt/services/BotLootCacheService"; import { BotWeaponModLimitService } from "@spt/services/BotWeaponModLimitService"; -import { BundleHashCacheService } from "@spt/services/cache/BundleHashCacheService"; -import { ModHashCacheService } from "@spt/services/cache/ModHashCacheService"; import { CustomLocationWaveService } from "@spt/services/CustomLocationWaveService"; import { DatabaseService } from "@spt/services/DatabaseService"; import { FenceService } from "@spt/services/FenceService"; @@ -219,13 +216,6 @@ import { MailSendService } from "@spt/services/MailSendService"; import { MapMarkerService } from "@spt/services/MapMarkerService"; import { MatchBotDetailsCacheService } from "@spt/services/MatchBotDetailsCacheService"; import { MatchLocationService } from "@spt/services/MatchLocationService"; -import { CustomItemService } from "@spt/services/mod/CustomItemService"; -import { DynamicRouterModService } from "@spt/services/mod/dynamicRouter/DynamicRouterModService"; -import { HttpListenerModService } from "@spt/services/mod/httpListener/HttpListenerModService"; -import { ImageRouteService } from "@spt/services/mod/image/ImageRouteService"; -import { OnLoadModService } from "@spt/services/mod/onLoad/OnLoadModService"; -import { OnUpdateModService } from "@spt/services/mod/onUpdate/OnUpdateModService"; -import { StaticRouterModService } from "@spt/services/mod/staticRouter/StaticRouterModService"; import { ModCompilerService } from "@spt/services/ModCompilerService"; import { NotificationService } from "@spt/services/NotificationService"; import { OpenZoneService } from "@spt/services/OpenZoneService"; @@ -246,12 +236,17 @@ import { RepairService } from "@spt/services/RepairService"; import { SeasonalEventService } from "@spt/services/SeasonalEventService"; import { TraderAssortService } from "@spt/services/TraderAssortService"; import { TraderPurchasePersisterService } from "@spt/services/TraderPurchasePersisterService"; +import { BundleHashCacheService } from "@spt/services/cache/BundleHashCacheService"; +import { ModHashCacheService } from "@spt/services/cache/ModHashCacheService"; +import { CustomItemService } from "@spt/services/mod/CustomItemService"; +import { DynamicRouterModService } from "@spt/services/mod/dynamicRouter/DynamicRouterModService"; +import { HttpListenerModService } from "@spt/services/mod/httpListener/HttpListenerModService"; +import { ImageRouteService } from "@spt/services/mod/image/ImageRouteService"; +import { OnLoadModService } from "@spt/services/mod/onLoad/OnLoadModService"; +import { OnUpdateModService } from "@spt/services/mod/onUpdate/OnUpdateModService"; +import { StaticRouterModService } from "@spt/services/mod/staticRouter/StaticRouterModService"; import { App } from "@spt/utils/App"; import { AsyncQueue } from "@spt/utils/AsyncQueue"; -import type { ICloner } from "@spt/utils/cloners/ICloner"; -import { JsonCloner } from "@spt/utils/cloners/JsonCloner"; -import { RecursiveCloner } from "@spt/utils/cloners/RecursiveCloner"; -import { StructuredCloner } from "@spt/utils/cloners/StructuredCloner"; import { CompareUtil } from "@spt/utils/CompareUtil"; import { DatabaseImporter } from "@spt/utils/DatabaseImporter"; import { EncodingUtil } from "@spt/utils/EncodingUtil"; @@ -260,28 +255,30 @@ import { HttpFileUtil } from "@spt/utils/HttpFileUtil"; import { HttpResponseUtil } from "@spt/utils/HttpResponseUtil"; import { ImporterUtil } from "@spt/utils/ImporterUtil"; import { JsonUtil } from "@spt/utils/JsonUtil"; -import { WinstonMainLogger } from "@spt/utils/logging/WinstonMainLogger"; -import { WinstonRequestLogger } from "@spt/utils/logging/WinstonRequestLogger"; import { MathUtil } from "@spt/utils/MathUtil"; import { ObjectId } from "@spt/utils/ObjectId"; import { RandomUtil } from "@spt/utils/RandomUtil"; import { TimeUtil } from "@spt/utils/TimeUtil"; import { VFS } from "@spt/utils/VFS"; import { Watermark, WatermarkLocale } from "@spt/utils/Watermark"; +import type { ICloner } from "@spt/utils/cloners/ICloner"; +import { JsonCloner } from "@spt/utils/cloners/JsonCloner"; +import { RecursiveCloner } from "@spt/utils/cloners/RecursiveCloner"; +import { StructuredCloner } from "@spt/utils/cloners/StructuredCloner"; +import { WinstonMainLogger } from "@spt/utils/logging/WinstonMainLogger"; +import { WinstonRequestLogger } from "@spt/utils/logging/WinstonRequestLogger"; +import { DependencyContainer, Lifecycle } from "tsyringe"; /** * Handle the registration of classes to be used by the Dependency Injection code */ -export class Container -{ - public static registerPostLoadTypes(container: DependencyContainer, childContainer: DependencyContainer): void - { +export class Container { + public static registerPostLoadTypes(container: DependencyContainer, childContainer: DependencyContainer): void { container.register("SptHttpListener", SptHttpListener, { lifecycle: Lifecycle.Singleton }); childContainer.registerType("HttpListener", "SptHttpListener"); } - public static registerTypes(depContainer: DependencyContainer): void - { + public static registerTypes(depContainer: DependencyContainer): void { depContainer.register("ApplicationContext", ApplicationContext, { lifecycle: Lifecycle.Singleton }); Container.registerUtils(depContainer); @@ -304,16 +301,20 @@ export class Container Container.registerPrimaryDependencies(depContainer); } - public static registerPrimaryDependencies(depContainer: DependencyContainer): void - { - depContainer.register("PrimaryLogger", { useToken: "WinstonLogger" }, - { lifecycle: Lifecycle.Singleton }); - depContainer.register("PrimaryCloner", { useToken: "RecursiveCloner" }, - { lifecycle: Lifecycle.Singleton }); + public static registerPrimaryDependencies(depContainer: DependencyContainer): void { + depContainer.register( + "PrimaryLogger", + { useToken: "WinstonLogger" }, + { lifecycle: Lifecycle.Singleton }, + ); + depContainer.register( + "PrimaryCloner", + { useToken: "RecursiveCloner" }, + { lifecycle: Lifecycle.Singleton }, + ); } - public static registerListTypes(depContainer: DependencyContainer): void - { + public static registerListTypes(depContainer: DependencyContainer): void { depContainer.register("OnLoadModService", { useValue: new OnLoadModService(depContainer) }); depContainer.register("HttpListenerModService", { useValue: new HttpListenerModService(depContainer) }); depContainer.register("OnUpdateModService", { useValue: new OnUpdateModService(depContainer) }); @@ -409,8 +410,7 @@ export class Container depContainer.registerType("SptWebSocketMessageHandler", "DefaultSptWebSocketMessageHandler"); } - private static registerUtils(depContainer: DependencyContainer): void - { + private static registerUtils(depContainer: DependencyContainer): void { // Utils depContainer.register("App", App, { lifecycle: Lifecycle.Singleton }); depContainer.register("DatabaseImporter", DatabaseImporter, { @@ -444,8 +444,7 @@ export class Container depContainer.register("RecursiveCloner", RecursiveCloner, { lifecycle: Lifecycle.Singleton }); } - private static registerRouters(depContainer: DependencyContainer): void - { + private static registerRouters(depContainer: DependencyContainer): void { // Routers depContainer.register("HttpRouter", HttpRouter, { lifecycle: Lifecycle.Singleton }); depContainer.register("ImageRouter", ImageRouter); @@ -530,8 +529,7 @@ export class Container depContainer.register("BuildsStaticRouter", { useClass: BuildsStaticRouter }); } - private static registerGenerators(depContainer: DependencyContainer): void - { + private static registerGenerators(depContainer: DependencyContainer): void { // Generators depContainer.register("BotGenerator", BotGenerator); depContainer.register("BotWeaponGenerator", BotWeaponGenerator); @@ -578,8 +576,7 @@ export class Container depContainer.registerType("InventoryMagGen", "UbglExternalMagGen"); } - private static registerHelpers(depContainer: DependencyContainer): void - { + private static registerHelpers(depContainer: DependencyContainer): void { // Helpers depContainer.register("AssortHelper", { useClass: AssortHelper }); depContainer.register("BotHelper", { useClass: BotHelper }); @@ -642,8 +639,7 @@ export class Container }); } - private static registerLoaders(depContainer: DependencyContainer): void - { + private static registerLoaders(depContainer: DependencyContainer): void { // Loaders depContainer.register("BundleLoader", BundleLoader, { lifecycle: Lifecycle.Singleton }); depContainer.register("PreSptModLoader", PreSptModLoader, { lifecycle: Lifecycle.Singleton }); @@ -652,8 +648,7 @@ export class Container }); } - private static registerCallbacks(depContainer: DependencyContainer): void - { + private static registerCallbacks(depContainer: DependencyContainer): void { // Callbacks depContainer.register("BotCallbacks", { useClass: BotCallbacks }); depContainer.register("BundleCallbacks", { useClass: BundleCallbacks }); @@ -691,8 +686,7 @@ export class Container depContainer.register("BuildsCallbacks", { useClass: BuildsCallbacks }); } - private static registerServices(depContainer: DependencyContainer): void - { + private static registerServices(depContainer: DependencyContainer): void { // Services depContainer.register("DatabaseService", DatabaseService, { lifecycle: Lifecycle.Singleton }); depContainer.register("ImageRouteService", ImageRouteService, { @@ -800,21 +794,27 @@ export class Container }); } - private static registerServers(depContainer: DependencyContainer): void - { + private static registerServers(depContainer: DependencyContainer): void { // Servers depContainer.register("DatabaseServer", DatabaseServer, { lifecycle: Lifecycle.Singleton }); depContainer.register("HttpServer", HttpServer, { lifecycle: Lifecycle.Singleton }); depContainer.register("WebSocketServer", WebSocketServer, { lifecycle: Lifecycle.Singleton }); - depContainer.register("SptWebSocketConnectionHandler", SptWebSocketConnectionHandler, { lifecycle: Lifecycle.Singleton }); - depContainer.register("DefaultSptWebSocketMessageHandler", DefaultSptWebSocketMessageHandler, { lifecycle: Lifecycle.Singleton }); + depContainer.register( + "SptWebSocketConnectionHandler", + SptWebSocketConnectionHandler, + { lifecycle: Lifecycle.Singleton }, + ); + depContainer.register( + "DefaultSptWebSocketMessageHandler", + DefaultSptWebSocketMessageHandler, + { lifecycle: Lifecycle.Singleton }, + ); depContainer.register("RagfairServer", RagfairServer); depContainer.register("SaveServer", SaveServer, { lifecycle: Lifecycle.Singleton }); depContainer.register("ConfigServer", ConfigServer, { lifecycle: Lifecycle.Singleton }); } - private static registerControllers(depContainer: DependencyContainer): void - { + private static registerControllers(depContainer: DependencyContainer): void { // Controllers depContainer.register("BotController", { useClass: BotController }); depContainer.register("ClientLogController", { useClass: ClientLogController }); diff --git a/project/src/di/OnLoad.ts b/project/src/di/OnLoad.ts index 09dedeb6..a5cdea3f 100644 --- a/project/src/di/OnLoad.ts +++ b/project/src/di/OnLoad.ts @@ -1,5 +1,4 @@ -export interface OnLoad -{ - onLoad(): Promise - getRoute(): string +export interface OnLoad { + onLoad(): Promise; + getRoute(): string; } diff --git a/project/src/di/OnUpdate.ts b/project/src/di/OnUpdate.ts index 9dcd495c..e1ce3753 100644 --- a/project/src/di/OnUpdate.ts +++ b/project/src/di/OnUpdate.ts @@ -1,5 +1,4 @@ -export interface OnUpdate -{ - onUpdate(timeSinceLastRun: number): Promise - getRoute(): string +export interface OnUpdate { + onUpdate(timeSinceLastRun: number): Promise; + getRoute(): string; } diff --git a/project/src/di/Router.ts b/project/src/di/Router.ts index eb79eead..573d92b1 100644 --- a/project/src/di/Router.ts +++ b/project/src/di/Router.ts @@ -2,33 +2,26 @@ import { IPmcData } from "@spt/models/eft/common/IPmcData"; import { IItemEventRouterResponse } from "@spt/models/eft/itemEvent/IItemEventRouterResponse"; import { ISptProfile } from "@spt/models/eft/profile/ISptProfile"; -export class Router -{ +export class Router { protected handledRoutes: HandledRoute[] = []; - public getTopLevelRoute(): string - { + public getTopLevelRoute(): string { return "spt"; } - protected getHandledRoutes(): HandledRoute[] - { + protected getHandledRoutes(): HandledRoute[] { throw new Error("This method needs to be overrode by the router classes"); } - protected getInternalHandledRoutes(): HandledRoute[] - { - if (this.handledRoutes.length === 0) - { + protected getInternalHandledRoutes(): HandledRoute[] { + if (this.handledRoutes.length === 0) { this.handledRoutes = this.getHandledRoutes(); } return this.handledRoutes; } - public canHandle(url: string, partialMatch = false): boolean - { - if (partialMatch) - { + public canHandle(url: string, partialMatch = false): boolean { + if (partialMatch) { return this.getInternalHandledRoutes() .filter((r) => r.dynamic) .some((r) => url.includes(r.route)); @@ -39,80 +32,64 @@ export class Router } } -export class StaticRouter extends Router -{ - constructor(private routes: RouteAction[]) - { +export class StaticRouter extends Router { + constructor(private routes: RouteAction[]) { super(); } - public async handleStatic(url: string, info: any, sessionID: string, output: string): Promise - { + public async handleStatic(url: string, info: any, sessionID: string, output: string): Promise { return this.routes.find((route) => route.url === url).action(url, info, sessionID, output); } - public override getHandledRoutes(): HandledRoute[] - { + public override getHandledRoutes(): HandledRoute[] { return this.routes.map((route) => new HandledRoute(route.url, false)); } } -export class DynamicRouter extends Router -{ - constructor(private routes: RouteAction[]) - { +export class DynamicRouter extends Router { + constructor(private routes: RouteAction[]) { super(); } - public async handleDynamic(url: string, info: any, sessionID: string, output: string): Promise - { + public async handleDynamic(url: string, info: any, sessionID: string, output: string): Promise { return this.routes.find((r) => url.includes(r.url)).action(url, info, sessionID, output); } - public override getHandledRoutes(): HandledRoute[] - { + public override getHandledRoutes(): HandledRoute[] { return this.routes.map((route) => new HandledRoute(route.url, true)); } } // The name of this class should be ItemEventRouter, but that name is taken, // So instead I added the definition -export class ItemEventRouterDefinition extends Router -{ +export class ItemEventRouterDefinition extends Router { public async handleItemEvent( url: string, pmcData: IPmcData, body: any, sessionID: string, output: IItemEventRouterResponse, - ): Promise - { + ): Promise { throw new Error("This method needs to be overrode by the router classes"); } } -export class SaveLoadRouter extends Router -{ - public handleLoad(profile: ISptProfile): ISptProfile - { +export class SaveLoadRouter extends Router { + public handleLoad(profile: ISptProfile): ISptProfile { throw new Error("This method needs to be overrode by the router classes"); } } -export class HandledRoute -{ +export class HandledRoute { constructor( public route: string, public dynamic: boolean, - ) - {} + ) {} } -export class RouteAction -{ +export class RouteAction { constructor( public url: string, public action: (url: string, info: any, sessionID: string, output: string) => Promise, - ) - {} + ) {} } diff --git a/project/src/di/Serializer.ts b/project/src/di/Serializer.ts index 33b79e72..38aa5f5b 100644 --- a/project/src/di/Serializer.ts +++ b/project/src/di/Serializer.ts @@ -1,14 +1,11 @@ import { IncomingMessage, ServerResponse } from "node:http"; -export class Serializer -{ - public serialize(sessionID: string, req: IncomingMessage, resp: ServerResponse, body: any): void - { +export class Serializer { + public serialize(sessionID: string, req: IncomingMessage, resp: ServerResponse, body: any): void { throw new Error("Should be extended and overrode"); } - public canHandle(something: string): boolean - { + public canHandle(something: string): boolean { throw new Error("Should be extended and overrode"); } } diff --git a/project/src/generators/BotEquipmentModGenerator.ts b/project/src/generators/BotEquipmentModGenerator.ts index 05376289..e937b9bc 100644 --- a/project/src/generators/BotEquipmentModGenerator.ts +++ b/project/src/generators/BotEquipmentModGenerator.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { BotGeneratorHelper } from "@spt/helpers/BotGeneratorHelper"; import { BotHelper } from "@spt/helpers/BotHelper"; import { BotWeaponGeneratorHelper } from "@spt/helpers/BotWeaponGeneratorHelper"; @@ -15,7 +14,10 @@ import { BaseClasses } from "@spt/models/enums/BaseClasses"; import { ConfigTypes } from "@spt/models/enums/ConfigTypes"; import { ModSpawn } from "@spt/models/enums/ModSpawn"; import { IChooseRandomCompatibleModResult } from "@spt/models/spt/bots/IChooseRandomCompatibleModResult"; -import { IFilterPlateModsForSlotByLevelResult, Result } from "@spt/models/spt/bots/IFilterPlateModsForSlotByLevelResult"; +import { + IFilterPlateModsForSlotByLevelResult, + Result, +} from "@spt/models/spt/bots/IFilterPlateModsForSlotByLevelResult"; import { IGenerateEquipmentProperties } from "@spt/models/spt/bots/IGenerateEquipmentProperties"; import { IGenerateWeaponRequest } from "@spt/models/spt/bots/IGenerateWeaponRequest"; import { IModToSpawnRequest } from "@spt/models/spt/bots/IModToSpawnRequest"; @@ -29,13 +31,13 @@ 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 { ICloner } from "@spt/utils/cloners/ICloner"; import { HashUtil } from "@spt/utils/HashUtil"; import { RandomUtil } from "@spt/utils/RandomUtil"; +import { ICloner } from "@spt/utils/cloners/ICloner"; +import { inject, injectable } from "tsyringe"; @injectable() -export class BotEquipmentModGenerator -{ +export class BotEquipmentModGenerator { protected botConfig: IBotConfig; constructor( @@ -58,8 +60,7 @@ export class BotEquipmentModGenerator @inject("BotEquipmentModPoolService") protected botEquipmentModPoolService: BotEquipmentModPoolService, @inject("ConfigServer") protected configServer: ConfigServer, @inject("PrimaryCloner") protected cloner: ICloner, - ) - { + ) { this.botConfig = this.configServer.getConfig(ConfigTypes.BOT); } @@ -78,24 +79,20 @@ export class BotEquipmentModGenerator parentTemplate: ITemplateItem, settings: IGenerateEquipmentProperties, shouldForceSpawn = false, - ): Item[] - { + ): Item[] { let forceSpawn = shouldForceSpawn; const compatibleModsPool = settings.modPool[parentTemplate._id]; - if (!compatibleModsPool) - { + if (!compatibleModsPool) { this.logger.warning( `bot: ${settings.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) - { + for (const modSlotName in compatibleModsPool) { const itemSlotTemplate = this.getModItemSlotFromDb(modSlotName, parentTemplate); - if (!itemSlotTemplate) - { + if (!itemSlotTemplate) { this.logger.error( this.localisationService.getText("bot-mod_slot_missing_from_item", { modSlot: modSlotName, @@ -112,31 +109,27 @@ export class BotEquipmentModGenerator settings.spawnChances.equipmentMods, settings.botEquipmentConfig, ); - if (modSpawnResult === ModSpawn.SKIP && !forceSpawn) - { + if (modSpawnResult === ModSpawn.SKIP && !forceSpawn) { continue; } // Ensure submods for nvgs all spawn together - if (modSlotName === "mod_nvg") - { + if (modSlotName === "mod_nvg") { forceSpawn = true; } let modPoolToChooseFrom = compatibleModsPool[modSlotName]; if ( - settings.botEquipmentConfig.filterPlatesByLevel - && this.itemHelper.isRemovablePlateSlot(modSlotName.toLowerCase()) - ) - { + 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)) - { + 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] @@ -146,8 +139,7 @@ export class BotEquipmentModGenerator continue; } - if ([Result.LACKS_PLATE_WEIGHTS].includes(outcome.result)) - { + 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`, ); @@ -160,36 +152,32 @@ export class BotEquipmentModGenerator let modTpl: string | undefined; let found = false; const exhaustableModPool = new ExhaustableArray(modPoolToChooseFrom, this.randomUtil, this.cloner); - while (exhaustableModPool.hasValues()) - { + while (exhaustableModPool.hasValues()) { modTpl = exhaustableModPool.getRandomValue(); - if (modTpl - && !this.botGeneratorHelper.isItemIncompatibleWithCurrentItems(equipment, modTpl, modSlotName) - .incompatible - ) - { + 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) - { + if (!found && itemSlotTemplate._required) { modTpl = this.getRandomModTplFromItemDb(modTpl, itemSlotTemplate, modSlotName, equipment); found = !!modTpl; } // Compatible item not found + not required - if (!(found || itemSlotTemplate._required)) - { + if (!(found || itemSlotTemplate._required)) { // Don't add item continue; } const modTemplate = this.itemHelper.getItem(modTpl); - if (!this.isModValidForSlot(modTemplate, itemSlotTemplate, modSlotName, parentTemplate, settings.botRole)) - { + if (!this.isModValidForSlot(modTemplate, itemSlotTemplate, modSlotName, parentTemplate, settings.botRole)) { continue; } @@ -198,8 +186,7 @@ export class BotEquipmentModGenerator equipment.push(this.createModItem(modId, modTpl, parentId, modSlotName, modTemplate[1], settings.botRole)); // Does the item being added have possible child mods? - if (Object.keys(settings.modPool).includes(modTpl)) - { + if (Object.keys(settings.modPool).includes(modTpl)) { // Call self recursively with item being checkced item we just added to bot this.generateModsForEquipment(equipment, modId, modTemplate[1], settings, forceSpawn); } @@ -221,13 +208,14 @@ export class BotEquipmentModGenerator modSlot: string, existingPlateTplPool: string[], armorItem: ITemplateItem, - ): IFilterPlateModsForSlotByLevelResult - { - const result: IFilterPlateModsForSlotByLevelResult = { result: Result.UNKNOWN_FAILURE, plateModTpls: undefined }; + ): 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)) - { + if (!this.itemHelper.isRemovablePlateSlot(modSlot)) { result.result = Result.NOT_PLATE_HOLDING_SLOT; result.plateModTpls = existingPlateTplPool; @@ -239,8 +227,7 @@ export class BotEquipmentModGenerator (armorWeight) => settings.botLevel >= armorWeight.levelRange.min && settings.botLevel <= armorWeight.levelRange.max, ); - if (!plateSlotWeights) - { + if (!plateSlotWeights) { // No weights, return original array of plate tpls result.result = Result.LACKS_PLATE_WEIGHTS; result.plateModTpls = existingPlateTplPool; @@ -250,8 +237,7 @@ export class BotEquipmentModGenerator // Get the specific plate slot weights (front/back/side) const plateWeights: Record = plateSlotWeights[modSlot]; - if (!plateWeights) - { + if (!plateWeights) { // No weights, return original array of plate tpls result.result = Result.LACKS_PLATE_WEIGHTS; result.plateModTpls = existingPlateTplPool; @@ -267,27 +253,23 @@ export class BotEquipmentModGenerator // Filter plates to the chosen level based on its armorClass property const platesOfDesiredLevel = platesFromDb.filter((item) => item._props.armorClass === chosenArmorPlateLevel); - if (platesOfDesiredLevel.length === 0) - { + if (platesOfDesiredLevel.length === 0) { this.logger.debug( `Plate filter was too restrictive for armor: ${armorItem._name} ${armorItem._id}, unable to find plates of level: ${chosenArmorPlateLevel}. Using mod items default plate`, ); const relatedItemDbModSlot = armorItem._props.Slots.find((slot) => slot._name.toLowerCase() === modSlot); const defaultPlate = relatedItemDbModSlot._props.filters[0].Plate; - if (!defaultPlate) - { + 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) - { + if (defaultPreset) { const relatedPresetSlot = defaultPreset._items.find( (item) => item.slotId?.toLowerCase() === modSlot, ); - if (relatedPresetSlot) - { + if (relatedPresetSlot) { result.result = Result.SUCCESS; result.plateModTpls = [relatedPresetSlot._tpl]; @@ -319,8 +301,7 @@ export class BotEquipmentModGenerator * @param request Data used to generate the weapon * @returns Weapon + mods array */ - public generateModsForWeapon(sessionId: string, request: IGenerateWeaponRequest): Item[] - { + public generateModsForWeapon(sessionId: string, request: IGenerateWeaponRequest): Item[] { const pmcProfile = this.profileHelper.getPmcProfile(sessionId); // Get pool of mods that fit weapon @@ -328,12 +309,11 @@ export class BotEquipmentModGenerator if ( !( - request.parentTemplate._props.Slots.length - || request.parentTemplate._props.Cartridges?.length - || request.parentTemplate._props.Chambers?.length + 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, @@ -350,19 +330,17 @@ export class BotEquipmentModGenerator request.botData.equipmentRole, pmcProfile.Info.Level, ); - const botWeaponSightWhitelist - = this.botEquipmentFilterService.getBotWeaponSightWhitelist(request.botData.equipmentRole); - const randomisationSettings - = this.botHelper.getBotRandomizationDetails(request.botData.level, botEquipConfig); + 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)); - for (const modSlot of sortedModKeys) - { + for (const modSlot of sortedModKeys) { // Check weapon has slot for mod to fit in const modsParentSlot = this.getModItemSlotFromDb(modSlot, request.parentTemplate); - if (!modsParentSlot) - { + if (!modsParentSlot) { this.logger.error( this.localisationService.getText("bot-weapon_missing_mod_slot", { modSlot: modSlot, @@ -380,9 +358,9 @@ export class BotEquipmentModGenerator modsParentSlot, modSlot, request.modSpawnChances, - botEquipConfig); - if (modSpawnResult === ModSpawn.SKIP) - { + botEquipConfig, + ); + if (modSpawnResult === ModSpawn.SKIP) { continue; } @@ -402,13 +380,13 @@ export class BotEquipmentModGenerator const modToAdd = this.chooseModToPutIntoSlot(modToSpawnRequest); // Compatible mod not found - if (!modToAdd || typeof modToAdd === "undefined") - { + if (!modToAdd || typeof modToAdd === "undefined") { continue; } - if (!this.isModValidForSlot(modToAdd, modsParentSlot, modSlot, request.parentTemplate, request.botData.role)) - { + if ( + !this.isModValidForSlot(modToAdd, modsParentSlot, modSlot, request.parentTemplate, request.botData.role) + ) { continue; } @@ -422,37 +400,37 @@ export class BotEquipmentModGenerator request.parentTemplate, request.weapon, ) - ) - { + ) { 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)) - { + if (this.modSlotCanHoldScope(modSlot, modToAddTemplate._parent)) { // mod_mount was picked to be added to weapon, force scope chance to ensure its filled const scopeSlots = ["mod_scope", "mod_scope_000", "mod_scope_001", "mod_scope_002", "mod_scope_003"]; this.adjustSlotSpawnChances(request.modSpawnChances, scopeSlots, 100); // Hydrate pool of mods that fit into mount as its a randomisable slot - if (isRandomisableSlot) - { + 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); + this.addCompatibleModsForProvidedMod( + "mod_scope", + modToAddTemplate, + request.modPool, + botEquipBlacklist, + ); } } // If picked item is muzzle adapter that can hold a child, adjust spawn chance - if (this.modSlotCanHoldMuzzleDevices(modSlot, modToAddTemplate._parent)) - { + if (this.modSlotCanHoldMuzzleDevices(modSlot, modToAddTemplate._parent)) { const muzzleSlots = ["mod_muzzle", "mod_muzzle_000", "mod_muzzle_001"]; // Make chance of muzzle devices 95%, nearly certain but not guaranteed this.adjustSlotSpawnChances(request.modSpawnChances, muzzleSlots, 95); } // If front/rear sight are to be added, set opposite to 100% chance - if (this.modIsFrontOrRearSight(modSlot, modToAddTemplate._id)) - { + if (this.modIsFrontOrRearSight(modSlot, modToAddTemplate._id)) { request.modSpawnChances.mod_sight_front = 100; request.modSpawnChances.mod_sight_rear = 100; } @@ -460,11 +438,10 @@ export class BotEquipmentModGenerator // Handguard mod can take a sub handguard mod + weapon has no UBGL (takes same slot) // Force spawn chance to be 100% to ensure it gets added if ( - modSlot === "mod_handguard" - && modToAddTemplate._props.Slots.some((slot) => slot._name === "mod_handguard") - && !request.weapon.some((item) => item.slotId === "mod_launcher") - ) - { + 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; } @@ -472,71 +449,63 @@ export class BotEquipmentModGenerator // If stock mod can take a sub stock mod, force spawn chance to be 100% to ensure sub-stock gets added // Or if mod_stock is configured to be forced on if ( - modSlot === "mod_stock" - && modToAddTemplate._props.Slots.some( + modSlot === "mod_stock" && + modToAddTemplate._props.Slots.some( (slot) => slot._name.includes("mod_stock") || botEquipConfig.forceStock, ) - ) - { + ) { // Stock mod can take additional stocks, could be a locking device, force 100% chance const stockSlots = ["mod_stock", "mod_stock_000", "mod_stock_akms"]; this.adjustSlotSpawnChances(request.modSpawnChances, stockSlots, 100); } // Gather stats on mods being added to weapon - if (this.itemHelper.isOfBaseclass(modToAddTemplate._id, BaseClasses.IRON_SIGHT)) - { - if (modSlot === "mod_sight_front") - { + if (this.itemHelper.isOfBaseclass(modToAddTemplate._id, BaseClasses.IRON_SIGHT)) { + if (modSlot === "mod_sight_front") { request.weaponStats.hasFrontIronSight = true; - } - else if (modSlot === "mod_sight_rear") - { + } else if (modSlot === "mod_sight_rear") { request.weaponStats.hasRearIronSight = true; } - } - else if (!request.weaponStats.hasOptic - && this.itemHelper.isOfBaseclass(modToAddTemplate._id, BaseClasses.SIGHTS)) - { + } 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)); + request.weapon.push( + this.createModItem( + modId, + modToAddTemplate._id, + request.weaponId, + modSlot, + modToAddTemplate, + request.botData.role, + ), + ); // 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)) - { + 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 - { + } 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) - { + if (isRandomisableSlot && !containsModInPool && modToAddTemplate._props.Slots.length > 0) { const modFromService = this.botEquipmentModPoolService.getModsForWeaponSlot(modToAddTemplate._id); - if (Object.keys(modFromService ?? {}).length > 0) - { + if (Object.keys(modFromService ?? {}).length > 0) { request.modPool[modToAddTemplate._id] = modFromService; containsModInPool = true; } } - if (containsModInPool) - { + if (containsModInPool) { const recursiveRequestData: IGenerateWeaponRequest = { weapon: request.weapon, modPool: request.modPool, @@ -547,15 +516,13 @@ export class BotEquipmentModGenerator botData: { role: request.botData.role, level: request.botData.level, - equipmentRole: request.botData.equipmentRole }, + equipmentRole: request.botData.equipmentRole, + }, modLimits: request.modLimits, weaponStats: request.weaponStats, }; // Call self recursively to add mods to this mod - this.generateModsForWeapon( - sessionId, - recursiveRequestData, - ); + this.generateModsForWeapon(sessionId, recursiveRequestData); } } } @@ -568,11 +535,9 @@ export class BotEquipmentModGenerator * @param modSlot Slot to check * @returns true if it's a front/rear sight */ - protected modIsFrontOrRearSight(modSlot: string, tpl: string): boolean - { + protected modIsFrontOrRearSight(modSlot: string, tpl: string): boolean { // Gas block /w front sight is special case, deem it a 'front sight' too - if (modSlot === "mod_gas_block" && tpl === "5ae30e795acfc408fb139a0b") - { + if (modSlot === "mod_gas_block" && tpl === "5ae30e795acfc408fb139a0b") { // M4A1 front sight with gas block return true; } @@ -586,8 +551,7 @@ export class BotEquipmentModGenerator * @param modsParentId Parent id of mod item * @returns true if it can hold a scope */ - protected modSlotCanHoldScope(modSlot: string, modsParentId: string): boolean - { + protected modSlotCanHoldScope(modSlot: string, modsParentId: string): boolean { return ( [ "mod_scope", @@ -609,22 +573,18 @@ export class BotEquipmentModGenerator modSpawnChances: ModsChances, modSlotsToAdjust: string[], newChancePercent: number, - ): void - { - if (!modSpawnChances) - { + ): void { + if (!modSpawnChances) { this.logger.warning("Unable to adjust scope spawn chances as spawn chance object is empty"); return; } - if (!modSlotsToAdjust) - { + if (!modSlotsToAdjust) { return; } - for (const modName of modSlotsToAdjust) - { + for (const modName of modSlotsToAdjust) { modSpawnChances[modName] = newChancePercent; } } @@ -635,8 +595,7 @@ export class BotEquipmentModGenerator * @param modsParentId OPTIONAL: parent id of modslot being checked * @returns True if modSlot can have muzzle-related items */ - protected modSlotCanHoldMuzzleDevices(modSlot: string, modsParentId?: string): boolean - { + protected modSlotCanHoldMuzzleDevices(modSlot: string, modsParentId?: string): boolean { return ["mod_muzzle", "mod_muzzle_000", "mod_muzzle_001"].includes(modSlot.toLowerCase()); } @@ -645,11 +604,9 @@ export class BotEquipmentModGenerator * @param unsortedSlotKeys Array of mod slot strings to sort * @returns Sorted array */ - protected sortModKeys(unsortedSlotKeys: string[]): string[] - { + protected sortModKeys(unsortedSlotKeys: string[]): string[] { // No need to sort with only 1 item in array - if (unsortedSlotKeys.length <= 1) - { + if (unsortedSlotKeys.length <= 1) { return unsortedSlotKeys; } @@ -664,56 +621,47 @@ export class BotEquipmentModGenerator const modMountKey = "mod_mount"; const modScopeKey = "mod_scope"; - if (unsortedSlotKeys.includes(modHandguardKey)) - { + if (unsortedSlotKeys.includes(modHandguardKey)) { sortedKeys.push(modHandguardKey); unsortedSlotKeys.splice(unsortedSlotKeys.indexOf(modHandguardKey), 1); } - if (unsortedSlotKeys.includes(modBarrelKey)) - { + if (unsortedSlotKeys.includes(modBarrelKey)) { sortedKeys.push(modBarrelKey); unsortedSlotKeys.splice(unsortedSlotKeys.indexOf(modBarrelKey), 1); } - if (unsortedSlotKeys.includes(modMount001Key)) - { + if (unsortedSlotKeys.includes(modMount001Key)) { sortedKeys.push(modMount001Key); unsortedSlotKeys.splice(unsortedSlotKeys.indexOf(modMount001Key), 1); } - if (unsortedSlotKeys.includes(modRecieverKey)) - { + if (unsortedSlotKeys.includes(modRecieverKey)) { sortedKeys.push(modRecieverKey); unsortedSlotKeys.splice(unsortedSlotKeys.indexOf(modRecieverKey), 1); } - if (unsortedSlotKeys.includes(modPistolGrip)) - { + if (unsortedSlotKeys.includes(modPistolGrip)) { sortedKeys.push(modPistolGrip); unsortedSlotKeys.splice(unsortedSlotKeys.indexOf(modPistolGrip), 1); } - if (unsortedSlotKeys.includes(modGasBlockKey)) - { + if (unsortedSlotKeys.includes(modGasBlockKey)) { sortedKeys.push(modGasBlockKey); unsortedSlotKeys.splice(unsortedSlotKeys.indexOf(modGasBlockKey), 1); } - if (unsortedSlotKeys.includes(modStockKey)) - { + if (unsortedSlotKeys.includes(modStockKey)) { sortedKeys.push(modStockKey); unsortedSlotKeys.splice(unsortedSlotKeys.indexOf(modStockKey), 1); } - if (unsortedSlotKeys.includes(modMountKey)) - { + if (unsortedSlotKeys.includes(modMountKey)) { sortedKeys.push(modMountKey); unsortedSlotKeys.splice(unsortedSlotKeys.indexOf(modMountKey), 1); } - if (unsortedSlotKeys.includes(modScopeKey)) - { + if (unsortedSlotKeys.includes(modScopeKey)) { sortedKeys.push(modScopeKey); unsortedSlotKeys.splice(unsortedSlotKeys.indexOf(modScopeKey), 1); } @@ -729,11 +677,9 @@ export class BotEquipmentModGenerator * @param parentTemplate item template * @returns Slot item */ - protected getModItemSlotFromDb(modSlot: string, parentTemplate: ITemplateItem): Slot - { + protected getModItemSlotFromDb(modSlot: string, parentTemplate: ITemplateItem): Slot { const modSlotLower = modSlot.toLowerCase(); - switch (modSlotLower) - { + switch (modSlotLower) { case "patron_in_weapon": case "patron_in_weapon_000": case "patron_in_weapon_001": @@ -758,16 +704,13 @@ export class BotEquipmentModGenerator modSlot: string, modSpawnChances: ModsChances, botEquipConfig: EquipmentFilters, - ): ModSpawn - { + ): ModSpawn { const slotRequired = itemSlot._required; - if (this.getAmmoContainers().includes(modSlot)) - { + if (this.getAmmoContainers().includes(modSlot)) { return ModSpawn.SPAWN; } const spawnMod = this.probabilityHelper.rollChance(modSpawnChances[modSlot]); - if (!spawnMod && (slotRequired || botEquipConfig.weaponSlotIdsToMakeRequired?.includes(modSlot))) - { + if (!spawnMod && (slotRequired || botEquipConfig.weaponSlotIdsToMakeRequired?.includes(modSlot))) { // Mod is required but spawn chance roll failed, choose default mod spawn for slot return ModSpawn.DEFAULT_MOD; } @@ -780,17 +723,13 @@ export class BotEquipmentModGenerator * @param request Data used to choose an appropriate mod with * @returns itemHelper.getItem() result */ - protected chooseModToPutIntoSlot( - request: IModToSpawnRequest, - ): [boolean, ITemplateItem] | undefined - { + protected chooseModToPutIntoSlot(request: IModToSpawnRequest): [boolean, ITemplateItem] | undefined { /** Slot mod will fill */ const parentSlot = request.parentTemplate._props.Slots?.find((i) => i._name === request.modSlot); const weaponTemplate = this.itemHelper.getItem(request.weapon[0]._tpl)[1]; // It's ammo, use predefined ammo parameter - if (this.getAmmoContainers().includes(request.modSlot) && request.modSlot !== "mod_magazine") - { + if (this.getAmmoContainers().includes(request.modSlot) && request.modSlot !== "mod_magazine") { return this.itemHelper.getItem(request.ammoTpl); } @@ -804,42 +743,37 @@ export class BotEquipmentModGenerator request.botEquipBlacklist, request.isRandomisableSlot, ); - if (!(modPool || parentSlot?._required)) - { + if (!(modPool || parentSlot?._required)) { // Nothing in mod pool + item not required - this.logger.debug(`Mod pool for slot: ${request.modSlot} on item: ${request.parentTemplate._name} was empty, skipping mod`); + this.logger.debug( + `Mod pool for slot: ${request.modSlot} on item: ${request.parentTemplate._name} was empty, skipping mod`, + ); return undefined; } // Filter out non-whitelisted scopes, use full modpool if filtered pool would have no elements - if (request.modSlot.includes("mod_scope") && request.botWeaponSightWhitelist) - { + if (request.modSlot.includes("mod_scope") && request.botWeaponSightWhitelist) { // scope pool has more than one scope - if (modPool.length > 1) - { + if (modPool.length > 1) { modPool = this.filterSightsByWeaponType(request.weapon[0], modPool, request.botWeaponSightWhitelist); } } - if (request.modSlot == "mod_gas_block") - { - if (request.weaponStats.hasOptic && modPool.length > 1) - { + if (request.modSlot == "mod_gas_block") { + if (request.weaponStats.hasOptic && modPool.length > 1) { // Attempt to limit modpool to low profile gas blocks when weapon has an optic - const onlyLowProfileGasBlocks = modPool - .filter((tpl) => this.botConfig.lowProfileGasBlockTpls.includes(tpl)); - if (onlyLowProfileGasBlocks.length > 0) - { + const onlyLowProfileGasBlocks = modPool.filter((tpl) => + this.botConfig.lowProfileGasBlockTpls.includes(tpl), + ); + if (onlyLowProfileGasBlocks.length > 0) { modPool = onlyLowProfileGasBlocks; } - } - else if (request.weaponStats.hasRearIronSight && modPool.length > 1) - { + } else if (request.weaponStats.hasRearIronSight && modPool.length > 1) { // Attempt to limit modpool to high profile gas blocks when weapon has rear iron sight + no front iron sight - const onlyHighProfileGasBlocks = modPool - .filter((tpl) => !this.botConfig.lowProfileGasBlockTpls.includes(tpl)); - if (onlyHighProfileGasBlocks.length > 0) - { + const onlyHighProfileGasBlocks = modPool.filter( + (tpl) => !this.botConfig.lowProfileGasBlockTpls.includes(tpl), + ); + if (onlyHighProfileGasBlocks.length > 0) { modPool = onlyHighProfileGasBlocks; } } @@ -853,36 +787,30 @@ export class BotEquipmentModGenerator request.weapon, request.modSlot, ); - if (chosenModResult.slotBlocked && !parentSlot!._required) - { + if (chosenModResult.slotBlocked && !parentSlot!._required) { // Don't bother trying to fit mod, slot is completely blocked return undefined; } // Log if mod chosen was incompatible - if (chosenModResult.incompatible && parentSlot!._required) - { + if (chosenModResult.incompatible && parentSlot!._required) { this.logger.debug(chosenModResult.reason); // this.logger.debug(`Weapon: ${weapon.map(x => `${x._tpl} ${x.slotId ?? ""}`).join(",")}`) } // Get random mod to attach from items db for required slots if none found above - if (!chosenModResult.found && parentSlot !== undefined && parentSlot._required) - { + if (!chosenModResult.found && parentSlot !== undefined && parentSlot._required) { chosenModResult.chosenTpl = this.getRandomModTplFromItemDb("", parentSlot, request.modSlot, request.weapon); chosenModResult.found = true; } // Compatible item not found + not required - if (!chosenModResult.found && parentSlot !== undefined && !parentSlot._required) - { + if (!chosenModResult.found && parentSlot !== undefined && !parentSlot._required) { return undefined; } - if (!chosenModResult.found && parentSlot !== undefined) - { - if (parentSlot._required) - { + if (!chosenModResult.found && parentSlot !== undefined) { + if (parentSlot._required) { this.logger.warning( `Required slot unable to be filled, ${request.modSlot} on ${request.parentTemplate._name} ${request.parentTemplate._id} for weapon: ${request.weapon[0]._tpl}`, ); @@ -909,8 +837,7 @@ export class BotEquipmentModGenerator choiceTypeEnum: ModSpawn, weapon: Item[], modSlotName: string, - ): IChooseRandomCompatibleModResult - { + ): IChooseRandomCompatibleModResult { let chosenTpl: string; const exhaustableModPool = new ExhaustableArray(modPool, this.randomUtil, this.cloner); let chosenModResult: IChooseRandomCompatibleModResult = { incompatible: true, found: false, reason: "unknown" }; @@ -919,11 +846,9 @@ export class BotEquipmentModGenerator // How many times can a mod for the slot be blocked before we stop trying const maxBlockedAttempts = Math.round(modPool.length * 0.75); // Roughly 75% of pool size let blockedAttemptCount = 0; - while (exhaustableModPool.hasValues()) - { + while (exhaustableModPool.hasValues()) { chosenTpl = exhaustableModPool.getRandomValue()!; - if (choiceTypeEnum === ModSpawn.DEFAULT_MOD && modPool.length === 1) - { + if (choiceTypeEnum === ModSpawn.DEFAULT_MOD && modPool.length === 1) { // Default mod wanted and only one choice in pool chosenModResult.found = true; chosenModResult.incompatible = false; @@ -934,8 +859,7 @@ export class BotEquipmentModGenerator // Check chosen item is on the allowed list of the parent const isOnModParentFilterList = modParentFilterList.includes(chosenTpl); - if (!isOnModParentFilterList) - { + if (!isOnModParentFilterList) { // Try again continue; } @@ -946,11 +870,9 @@ export class BotEquipmentModGenerator modSlotName, ); - if (chosenModResult.slotBlocked) - { + if (chosenModResult.slotBlocked) { // Give max of x attempts of picking a mod if blocked by another - if (blockedAttemptCount > maxBlockedAttempts) - { + if (blockedAttemptCount > maxBlockedAttempts) { blockedAttemptCount = 0; break; } @@ -962,8 +884,7 @@ export class BotEquipmentModGenerator } // Some mod combos will never work, make sure this isnt the case - if (!(chosenModResult.incompatible || this.weaponModComboIsIncompatible(weapon, chosenTpl))) - { + if (!(chosenModResult.incompatible || this.weaponModComboIsIncompatible(weapon, chosenTpl))) { // Success chosenModResult.found = true; chosenModResult.incompatible = false; @@ -998,11 +919,9 @@ export class BotEquipmentModGenerator modSlot: string, botEquipBlacklist: EquipmentFilterDetails, isRandomisableSlot: boolean, - ): string[] - { + ): string[] { // Mod is flagged as being default only, try and find it in globals - if (itemSpawnCategory === ModSpawn.DEFAULT_MOD) - { + if (itemSpawnCategory === ModSpawn.DEFAULT_MOD) { const matchingPreset = this.getMatchingPreset(weaponTemplate, parentTemplate._id); const matchingModFromPreset = matchingPreset?._items.find( (item) => item?.slotId?.toLowerCase() === modSlot.toLowerCase(), @@ -1011,11 +930,9 @@ export class BotEquipmentModGenerator // Only filter mods down to single default item if it already exists in existing itemModPool, OR the default item has no children // Filtering mod pool to item that wasnt already there can have problems; // You'd have a mod being picked without any sub-mods in its chain, possibly resulting in missing required mods not being added - if (matchingModFromPreset) - { + if (matchingModFromPreset) { // Mod is in existing mod pool - if (itemModPool[modSlot].includes(matchingModFromPreset._tpl)) - { + if (itemModPool[modSlot].includes(matchingModFromPreset._tpl)) { // Found mod on preset + it already exists in mod pool return [matchingModFromPreset._tpl]; } @@ -1028,17 +945,15 @@ export class BotEquipmentModGenerator // Mod isnt in existing pool, only add if it has no children and matches parent filter if ( - parentSlotCompatibleItems?.includes(matchingModFromPreset._tpl) - && this.itemHelper.getItem(matchingModFromPreset._tpl)[1]._props.Slots?.length === 0 - ) - { + parentSlotCompatibleItems?.includes(matchingModFromPreset._tpl) && + this.itemHelper.getItem(matchingModFromPreset._tpl)[1]._props.Slots?.length === 0 + ) { // Mod has no children and matches parent filters, can be used return [matchingModFromPreset._tpl]; } } - if (itemModPool[modSlot]?.length > 1) - { + if (itemModPool[modSlot]?.length > 1) { this.logger.debug( `No default: ${modSlot} mod found on template: ${weaponTemplate._name} and multiple items found in existing pool`, ); @@ -1048,8 +963,7 @@ export class BotEquipmentModGenerator return itemModPool[modSlot]; } - if (isRandomisableSlot) - { + if (isRandomisableSlot) { return this.getDynamicModPool(parentTemplate._id, modSlot, botEquipBlacklist); } @@ -1063,19 +977,16 @@ export class BotEquipmentModGenerator * @param parentItemTpl Tpl of the parent item * @returns Default preset found */ - protected getMatchingPreset(weaponTemplate: ITemplateItem, parentItemTpl: string): IPreset | undefined - { + protected getMatchingPreset(weaponTemplate: ITemplateItem, parentItemTpl: string): IPreset | undefined { // Edge case - using mp5sd reciever means default mp5 handguard doesnt fit const isMp5sd = parentItemTpl === "5926f2e086f7745aae644231"; - if (isMp5sd) - { + if (isMp5sd) { return this.presetHelper.getPreset("59411abb86f77478f702b5d2"); } // Edge case - dvl 500mm is the silenced barrel and has specific muzzle mods const isDvl500mmSilencedBarrel = parentItemTpl === "5888945a2459774bf43ba385"; - if (isDvl500mmSilencedBarrel) - { + if (isDvl500mmSilencedBarrel) { return this.presetHelper.getPreset("59e8d2b386f77445830dd299"); } @@ -1088,11 +999,9 @@ export class BotEquipmentModGenerator * @param modTpl Mod to check compatibility with weapon * @returns True if incompatible */ - protected weaponModComboIsIncompatible(weapon: Item[], modTpl: string): boolean - { + protected weaponModComboIsIncompatible(weapon: Item[], modTpl: string): boolean { // STM-9 + AR-15 Lone Star Ion Lite handguard - if (weapon[0]._tpl === "60339954d62c9b14ed777c06" && modTpl === "5d4405f0a4b9361e6a4e6bd9") - { + if (weapon[0]._tpl === "60339954d62c9b14ed777c06" && modTpl === "5d4405f0a4b9361e6a4e6bd9") { return true; } @@ -1116,8 +1025,7 @@ export class BotEquipmentModGenerator modSlot: string, modTemplate: ITemplateItem, botRole: string, - ): Item - { + ): Item { return { _id: modId, _tpl: modTpl, @@ -1132,8 +1040,7 @@ export class BotEquipmentModGenerator * e.g. mod_magazine / patron_in_weapon_000 * @returns string array */ - protected getAmmoContainers(): string[] - { + protected getAmmoContainers(): string[] { return ["mod_magazine", "patron_in_weapon", "patron_in_weapon_000", "patron_in_weapon_001", "cartridges"]; } @@ -1150,19 +1057,16 @@ export class BotEquipmentModGenerator parentSlot: Slot, modSlot: string, items: Item[], - ): string | undefined - { + ): string | undefined { // Find compatible mods and make an array of them const allowedItems = parentSlot._props.filters[0].Filter; // Find mod item that fits slot from sorted mod array const exhaustableModPool = new ExhaustableArray(allowedItems, this.randomUtil, this.cloner); let tmpModTpl = fallbackModTpl; - while (exhaustableModPool.hasValues()) - { + while (exhaustableModPool.hasValues()) { tmpModTpl = exhaustableModPool.getRandomValue()!; - if (!this.botGeneratorHelper.isItemIncompatibleWithCurrentItems(items, tmpModTpl, modSlot).incompatible) - { + if (!this.botGeneratorHelper.isItemIncompatibleWithCurrentItems(items, tmpModTpl, modSlot).incompatible) { return tmpModTpl; } } @@ -1186,13 +1090,11 @@ export class BotEquipmentModGenerator modSlot: string, parentTemplate: ITemplateItem, botRole: string, - ): boolean - { + ): boolean { const modBeingAddedDbTemplate = modToAdd[1]; // Mod lacks db template object - if (!modBeingAddedDbTemplate) - { + if (!modBeingAddedDbTemplate) { this.logger.error( this.localisationService.getText("bot-no_item_template_found_when_adding_mod", { modId: modBeingAddedDbTemplate?._id ?? "UNKNOWN", @@ -1205,11 +1107,9 @@ export class BotEquipmentModGenerator } // Mod has invalid db item - if (!modToAdd[0]) - { + if (!modToAdd[0]) { // Parent slot must be filled but db object is invalid, show warning and return false - if (slotAddedToTemplate._required) - { + if (slotAddedToTemplate._required) { this.logger.warning( this.localisationService.getText("bot-unable_to_add_mod_item_invalid", { itemName: modBeingAddedDbTemplate?._name ?? "UNKNOWN", @@ -1239,22 +1139,18 @@ export class BotEquipmentModGenerator modTemplate: ITemplateItem, modPool: Mods, botEquipBlacklist: EquipmentFilterDetails, - ): void - { + ): void { const desiredSlotObject = modTemplate._props.Slots?.find((slot) => slot._name.includes(desiredSlotName)); - if (desiredSlotObject) - { + if (desiredSlotObject) { const supportedSubMods = desiredSlotObject._props.filters[0].Filter; - if (supportedSubMods) - { + if (supportedSubMods) { // Filter mods let filteredMods = this.filterWeaponModsByBlacklist( supportedSubMods, botEquipBlacklist, desiredSlotName, ); - if (filteredMods.length === 0) - { + if (filteredMods.length === 0) { this.logger.warning( this.localisationService.getText("bot-unable_to_filter_mods_all_blacklisted", { slotName: desiredSlotObject._name, @@ -1264,8 +1160,7 @@ export class BotEquipmentModGenerator filteredMods = supportedSubMods; } - if (!modPool[modTemplate._id]) - { + if (!modPool[modTemplate._id]) { modPool[modTemplate._id] = {}; } @@ -1285,15 +1180,13 @@ export class BotEquipmentModGenerator parentItemId: string, modSlot: string, botEquipBlacklist: EquipmentFilterDetails, - ): string[] - { + ): string[] { const modsFromDynamicPool = this.cloner.clone( this.botEquipmentModPoolService.getCompatibleModsForWeaponSlot(parentItemId, modSlot), ); const filteredMods = this.filterWeaponModsByBlacklist(modsFromDynamicPool, botEquipBlacklist, modSlot); - if (filteredMods.length === 0) - { + if (filteredMods.length === 0) { this.logger.warning( this.localisationService.getText("bot-unable_to_filter_mod_slot_all_blacklisted", modSlot), ); @@ -1314,11 +1207,9 @@ export class BotEquipmentModGenerator allowedMods: string[], botEquipBlacklist: EquipmentFilterDetails, modSlot: string, - ): string[] - { + ): string[] { // No blacklist, nothing to filter out - if (!botEquipBlacklist) - { + if (!botEquipBlacklist) { return allowedMods; } @@ -1347,11 +1238,10 @@ export class BotEquipmentModGenerator items: Item[], modPool: Mods, cylinderMagParentId: string, - cylinderMagTemplate: ITemplateItem): void - { + cylinderMagTemplate: ITemplateItem, + ): void { let itemModPool = modPool[cylinderMagTemplate._id]; - if (!itemModPool) - { + if (!itemModPool) { this.logger.warning( this.localisationService.getText("bot-unable_to_fill_camora_slot_mod_pool_empty", { weaponId: cylinderMagTemplate._id, @@ -1362,8 +1252,7 @@ export class BotEquipmentModGenerator // Attempt to generate camora slots for item modPool[cylinderMagTemplate._id] = {}; - for (const camora of camoraSlots) - { + for (const camora of camoraSlots) { modPool[cylinderMagTemplate._id][camora._name] = camora._props.filters[0].Filter; } itemModPool = modPool[cylinderMagTemplate._id]; @@ -1372,21 +1261,12 @@ export class BotEquipmentModGenerator let exhaustableModPool = undefined; let modSlot = "cartridges"; const camoraFirstSlot = "camora_000"; - if (modSlot in itemModPool) - { + if (modSlot in itemModPool) { exhaustableModPool = new ExhaustableArray(itemModPool[modSlot], this.randomUtil, this.cloner); - } - else if (camoraFirstSlot in itemModPool) - { + } else if (camoraFirstSlot in itemModPool) { modSlot = camoraFirstSlot; - exhaustableModPool = new ExhaustableArray( - this.mergeCamoraPools(itemModPool), - this.randomUtil, - this.cloner, - ); - } - else - { + exhaustableModPool = new ExhaustableArray(this.mergeCamoraPools(itemModPool), this.randomUtil, this.cloner); + } else { this.logger.error(this.localisationService.getText("bot-missing_cartridge_slot", cylinderMagTemplate._id)); return; @@ -1394,25 +1274,21 @@ export class BotEquipmentModGenerator let modTpl: string; let found = false; - while (exhaustableModPool.hasValues()) - { + while (exhaustableModPool.hasValues()) { modTpl = exhaustableModPool.getRandomValue(); - if (!this.botGeneratorHelper.isItemIncompatibleWithCurrentItems(items, modTpl, modSlot).incompatible) - { + if (!this.botGeneratorHelper.isItemIncompatibleWithCurrentItems(items, modTpl, modSlot).incompatible) { found = true; break; } } - if (!found) - { + if (!found) { this.logger.error(this.localisationService.getText("bot-no_compatible_camora_ammo_found", modSlot)); return; } - for (const slot of cylinderMagTemplate._props.Slots) - { + for (const slot of cylinderMagTemplate._props.Slots) { const modSlotId = slot._name; const modId = this.hashUtil.generate(); items.push({ _id: modId, _tpl: modTpl, parentId: cylinderMagParentId, slotId: modSlotId }); @@ -1424,11 +1300,9 @@ export class BotEquipmentModGenerator * @param camorasWithShells Dictionary of camoras we want to merge into one array * @returns String array of shells for multiple camora sources */ - protected mergeCamoraPools(camorasWithShells: Record): string[] - { + protected mergeCamoraPools(camorasWithShells: Record): string[] { const uniqueShells = new Set(); - for (const shells of Object.values(camorasWithShells)) - { + for (const shells of Object.values(camorasWithShells)) { // Add all shells to the set. shells.forEach((shell) => uniqueShells.add(shell)); } @@ -1449,14 +1323,12 @@ export class BotEquipmentModGenerator weapon: Item, scopes: string[], botWeaponSightWhitelist: Record, - ): string[] - { + ): string[] { const weaponDetails = this.itemHelper.getItem(weapon._tpl); // Return original scopes array if whitelist not found const whitelistedSightTypes = botWeaponSightWhitelist[weaponDetails[1]._parent]; - if (!whitelistedSightTypes) - { + if (!whitelistedSightTypes) { this.logger.debug( `Unable to find whitelist for weapon type: ${weaponDetails[1]._parent} ${weaponDetails[1]._name}, skipping sight filtering`, ); @@ -1466,11 +1338,9 @@ export class BotEquipmentModGenerator // Filter items that are not directly scopes OR mounts that do not hold the type of scope we allow for this weapon type const filteredScopesAndMods: string[] = []; - for (const item of scopes) - { + for (const item of scopes) { // Mods is a scope, check base class is allowed - if (this.itemHelper.isOfBaseclasses(item, whitelistedSightTypes)) - { + if (this.itemHelper.isOfBaseclasses(item, whitelistedSightTypes)) { // Add mod to allowed list filteredScopesAndMods.push(item); continue; @@ -1479,8 +1349,7 @@ export class BotEquipmentModGenerator // Edge case, what if item is a mount for a scope and not directly a scope? // Check item is mount + has child items const itemDetails = this.itemHelper.getItem(item)[1]; - if (this.itemHelper.isOfBaseclass(item, BaseClasses.MOUNT) && itemDetails._props.Slots.length > 0) - { + if (this.itemHelper.isOfBaseclass(item, BaseClasses.MOUNT) && itemDetails._props.Slots.length > 0) { // Check to see if mount has a scope slot (only include primary slot, ignore the rest like the backup sight slots) // Should only find 1 as there's currently no items with a mod_scope AND a mod_scope_000 const scopeSlot = itemDetails._props.Slots.filter((slot) => @@ -1492,12 +1361,11 @@ export class BotEquipmentModGenerator scopeSlot?.every((slot) => slot._props.filters[0].Filter.every( (tpl) => - this.itemHelper.isOfBaseclasses(tpl, whitelistedSightTypes) - || this.itemHelper.isOfBaseclass(tpl, BaseClasses.MOUNT), + this.itemHelper.isOfBaseclasses(tpl, whitelistedSightTypes) || + this.itemHelper.isOfBaseclass(tpl, BaseClasses.MOUNT), ), ) - ) - { + ) { // Add mod to allowed list filteredScopesAndMods.push(item); } @@ -1505,8 +1373,7 @@ export class BotEquipmentModGenerator } // No mods added to return list after filtering has occurred, send back the original mod list - if (!filteredScopesAndMods || filteredScopesAndMods.length === 0) - { + if (!filteredScopesAndMods || filteredScopesAndMods.length === 0) { this.logger.debug( `Scope whitelist too restrictive for: ${weapon._tpl} ${weaponDetails[1]._name}, skipping filter`, ); diff --git a/project/src/generators/BotGenerator.ts b/project/src/generators/BotGenerator.ts index 2dd6d5f8..3f4ad141 100644 --- a/project/src/generators/BotGenerator.ts +++ b/project/src/generators/BotGenerator.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { BotInventoryGenerator } from "@spt/generators/BotInventoryGenerator"; import { BotLevelGenerator } from "@spt/generators/BotLevelGenerator"; import { BotDifficultyHelper } from "@spt/helpers/BotDifficultyHelper"; @@ -31,14 +30,14 @@ import { DatabaseService } from "@spt/services/DatabaseService"; import { ItemFilterService } from "@spt/services/ItemFilterService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { SeasonalEventService } from "@spt/services/SeasonalEventService"; -import { ICloner } from "@spt/utils/cloners/ICloner"; import { HashUtil } from "@spt/utils/HashUtil"; import { RandomUtil } from "@spt/utils/RandomUtil"; import { TimeUtil } from "@spt/utils/TimeUtil"; +import { ICloner } from "@spt/utils/cloners/ICloner"; +import { inject, injectable } from "tsyringe"; @injectable() -export class BotGenerator -{ +export class BotGenerator { protected botConfig: IBotConfig; protected pmcConfig: IPmcConfig; @@ -60,8 +59,7 @@ export class BotGenerator @inject("ItemFilterService") protected itemFilterService: ItemFilterService, @inject("ConfigServer") protected configServer: ConfigServer, @inject("PrimaryCloner") protected cloner: ICloner, - ) - { + ) { this.botConfig = this.configServer.getConfig(ConfigTypes.BOT); this.pmcConfig = this.configServer.getConfig(ConfigTypes.PMC); } @@ -73,8 +71,7 @@ export class BotGenerator * @param botTemplate base bot template to use (e.g. assault/pmcbot) * @returns */ - public generatePlayerScav(sessionId: string, role: string, difficulty: string, botTemplate: IBotType): IBotBase - { + public generatePlayerScav(sessionId: string, role: string, difficulty: string, botTemplate: IBotType): IBotBase { let bot = this.getCloneOfBotBase(); bot.Info.Settings.BotDifficulty = difficulty; bot.Info.Settings.Role = role; @@ -102,12 +99,12 @@ export class BotGenerator * @param botGenerationDetails details on how to generate bots * @returns constructed bot */ - public prepareAndGenerateBot(sessionId: string, botGenerationDetails: BotGenerationDetails): IBotBase - { + public prepareAndGenerateBot(sessionId: string, botGenerationDetails: BotGenerationDetails): IBotBase { const preparedBotBase = this.getPreparedBotBase( botGenerationDetails.eventRole ?? botGenerationDetails.role, // Use eventRole if provided, botGenerationDetails.side, - botGenerationDetails.botDifficulty); + botGenerationDetails.botDifficulty, + ); // Get raw json data for bot (Cloned) const botRole = botGenerationDetails.isPmc @@ -125,8 +122,7 @@ export class BotGenerator * @param difficulty Difficult bot should have * @returns Cloned bot base */ - protected getPreparedBotBase(botRole: string, botSide: string, difficulty: string): IBotBase - { + protected getPreparedBotBase(botRole: string, botSide: string, difficulty: string): IBotBase { const botBaseClone = this.getCloneOfBotBase(); botBaseClone.Info.Settings.Role = botRole; botBaseClone.Info.Side = botSide; @@ -139,8 +135,7 @@ export class BotGenerator * Get a clone of the database\bots\base.json file * @returns IBotBase object */ - protected getCloneOfBotBase(): IBotBase - { + protected getCloneOfBotBase(): IBotBase { return this.cloner.clone(this.databaseService.getBots().base); } @@ -157,8 +152,7 @@ export class BotGenerator bot: IBotBase, botJsonTemplate: IBotType, botGenerationDetails: BotGenerationDetails, - ): IBotBase - { + ): IBotBase { const botRole = botGenerationDetails.role.toLowerCase(); const botLevel = this.botLevelGenerator.generateBotLevel( botJsonTemplate.experience.level, @@ -166,8 +160,7 @@ export class BotGenerator bot, ); - if (!botGenerationDetails.isPlayerScav) - { + if (!botGenerationDetails.isPlayerScav) { this.botEquipmentFilterService.filterBotEquipment( sessionId, botJsonTemplate, @@ -178,11 +171,9 @@ export class BotGenerator bot.Info.Nickname = this.generateBotNickname(botJsonTemplate, botGenerationDetails, botRole, sessionId); - if (!this.seasonalEventService.christmasEventEnabled()) - { + if (!this.seasonalEventService.christmasEventEnabled()) { // Process all bots EXCEPT gifter, he needs christmas items - if (botGenerationDetails.role !== "gifter") - { + if (botGenerationDetails.role !== "gifter") { this.seasonalEventService.removeChristmasItemsFromBotInventory( botJsonTemplate.inventory, botGenerationDetails.role, @@ -193,8 +184,7 @@ export class BotGenerator this.removeBlacklistedLootFromBotTemplate(botJsonTemplate.inventory); // Remove hideout data if bot is not a PMC or pscav - match what live sends - if (!(botGenerationDetails.isPmc || botGenerationDetails.isPlayerScav)) - { + if (!(botGenerationDetails.isPmc || botGenerationDetails.isPlayerScav)) { bot.Hideout = undefined; } @@ -209,12 +199,10 @@ export class BotGenerator bot.Health = this.generateHealth(botJsonTemplate.health, botGenerationDetails.isPlayerScav); bot.Skills = this.generateSkills(botJsonTemplate.skills); // TODO: fix bad type, bot jsons store skills in dict, output needs to be array - if (botGenerationDetails.isPmc) - { + if (botGenerationDetails.isPmc) { bot.Info.IsStreamerModeAvailable = true; // Set to true so client patches can pick it up later - client sometimes alters botrole to assaultGroup this.setRandomisedGameVersionAndCategory(bot.Info); - if (bot.Info.GameVersion === GameEditions.UNHEARD) - { + if (bot.Info.GameVersion === GameEditions.UNHEARD) { this.addAdditionalPocketLootWeightsForUnheardBot(botJsonTemplate); } } @@ -230,8 +218,7 @@ export class BotGenerator bot.Info.GameVersion, ); - if (this.botConfig.botRolesWithDogTags.includes(botRole)) - { + if (this.botConfig.botRolesWithDogTags.includes(botRole)) { this.addDogtagToBot(bot); } @@ -242,16 +229,14 @@ export class BotGenerator this.generateInventoryId(bot); // Set role back to originally requested now its been generated - if (botGenerationDetails.eventRole) - { + if (botGenerationDetails.eventRole) { bot.Info.Settings.Role = botGenerationDetails.eventRole; } return bot; } - protected addAdditionalPocketLootWeightsForUnheardBot(botJsonTemplate: IBotType): void - { + protected addAdditionalPocketLootWeightsForUnheardBot(botJsonTemplate: IBotType): void { // Adjust pocket loot weights to allow for 5 or 6 items const pocketWeights = botJsonTemplate.generation.items.pocketLoot.weights; pocketWeights["5"] = 1; @@ -262,31 +247,25 @@ export class BotGenerator * Remove items from item.json/lootableItemBlacklist from bots inventory * @param botInventory Bot to filter */ - protected removeBlacklistedLootFromBotTemplate(botInventory: Inventory): void - { + protected removeBlacklistedLootFromBotTemplate(botInventory: Inventory): void { const lootContainersToFilter = ["Backpack", "Pockets", "TacticalVest"]; // Remove blacklisted loot from loot containers - for (const lootContainerKey of lootContainersToFilter) - { + for (const lootContainerKey of lootContainersToFilter) { // No container, skip - if (botInventory.items[lootContainerKey]?.length === 0) - { + if (botInventory.items[lootContainerKey]?.length === 0) { continue; } const tplsToRemove: string[] = []; const containerItems = botInventory.items[lootContainerKey]; - for (const tplKey of Object.keys(containerItems)) - { - if (this.itemFilterService.isLootableItemBlacklisted(tplKey)) - { + for (const tplKey of Object.keys(containerItems)) { + if (this.itemFilterService.isLootableItemBlacklisted(tplKey)) { tplsToRemove.push(tplKey); } } - for (const blacklistedTplToRemove of tplsToRemove) - { + for (const blacklistedTplToRemove of tplsToRemove) { delete containerItems[blacklistedTplToRemove]; } } @@ -302,8 +281,7 @@ export class BotGenerator bot: IBotBase, appearance: Appearance, botGenerationDetails: BotGenerationDetails, - ): void - { + ): void { bot.Customization.Head = this.weightedRandomHelper.getWeightedValue(appearance.head); bot.Customization.Body = this.weightedRandomHelper.getWeightedValue(appearance.body); bot.Customization.Feet = this.weightedRandomHelper.getWeightedValue(appearance.feet); @@ -314,8 +292,7 @@ export class BotGenerator // Find the body/hands mapping const matchingBody: IWildBody = bodyGlobalDict[chosenBodyTemplate?._name]; - if (matchingBody?.isNotRandom) - { + if (matchingBody?.isNotRandom) { // Has fixed hands for this body, set them bot.Customization.Hands = matchingBody.hands; } @@ -334,8 +311,7 @@ export class BotGenerator botGenerationDetails: BotGenerationDetails, botRole: string, sessionId?: string, - ): string - { + ): string { const isPlayerScav = botGenerationDetails.isPlayerScav; let name = `${this.randomUtil.getArrayValue(botJsonTemplate.firstName)} ${ @@ -345,19 +321,16 @@ export class BotGenerator // Simulate bot looking like a player scav with the PMC name in brackets. // E.g. "ScavName (PMCName)" - if (this.shouldSimulatePlayerScavName(botRole, isPlayerScav)) - { + if (this.shouldSimulatePlayerScavName(botRole, isPlayerScav)) { return this.addPlayerScavNameSimulationSuffix(name); } - if (this.botConfig.showTypeInNickname && !isPlayerScav) - { + if (this.botConfig.showTypeInNickname && !isPlayerScav) { name += ` ${botRole}`; } // We want to replace pmc bot names with player name + prefix - if (botGenerationDetails.isPmc && botGenerationDetails.allPmcsHaveSameNameAsPlayer) - { + if (botGenerationDetails.isPmc && botGenerationDetails.allPmcsHaveSameNameAsPlayer) { const prefix = this.localisationService.getRandomTextThatMatchesPartialKey("pmc-name_prefix_"); name = `${prefix} ${name}`; } @@ -365,15 +338,15 @@ export class BotGenerator return name; } - protected shouldSimulatePlayerScavName(botRole: string, isPlayerScav: boolean): boolean - { - return botRole === "assault" - && this.randomUtil.getChance100(this.botConfig.chanceAssaultScavHasPlayerScavName) - && !isPlayerScav; + protected shouldSimulatePlayerScavName(botRole: string, isPlayerScav: boolean): boolean { + return ( + botRole === "assault" && + this.randomUtil.getChance100(this.botConfig.chanceAssaultScavHasPlayerScavName) && + !isPlayerScav + ); } - protected addPlayerScavNameSimulationSuffix(nickname: string): string - { + protected addPlayerScavNameSimulationSuffix(nickname: string): string { const pmcNames = [ ...this.databaseService.getBots().types.usec.firstName, ...this.databaseService.getBots().types.bear.firstName, @@ -385,10 +358,8 @@ export class BotGenerator * Log the number of PMCs generated to the debug console * @param output Generated bot array, ready to send to client */ - protected logPmcGeneratedCount(output: IBotBase[]): void - { - const pmcCount = output.reduce((acc, cur) => - { + protected logPmcGeneratedCount(output: IBotBase[]): void { + const pmcCount = output.reduce((acc, cur) => { return cur.Info.Side === "Bear" || cur.Info.Side === "Usec" ? acc + 1 : acc; }, 0); this.logger.debug(`Generated ${output.length} total bots. Replaced ${pmcCount} with PMCs`); @@ -400,8 +371,7 @@ export class BotGenerator * @param playerScav Is a pscav bot being generated * @returns PmcHealth object */ - protected generateHealth(healthObj: Health, playerScav = false): PmcHealth - { + protected generateHealth(healthObj: Health, playerScav = false): PmcHealth { const bodyParts = playerScav ? this.getLowestHpBody(healthObj.BodyParts) : this.randomUtil.getArrayValue(healthObj.BodyParts); @@ -474,21 +444,17 @@ export class BotGenerator * @param bodies Body parts to sum up * @returns Lowest hp collection */ - protected getLowestHpBody(bodies: BodyPart[]): BodyPart | undefined - { - if (bodies.length === 0) - { + protected getLowestHpBody(bodies: BodyPart[]): BodyPart | undefined { + if (bodies.length === 0) { // Handle empty input return undefined; } let result: BodyPart; let currentHighest = Number.POSITIVE_INFINITY; - for (const bodyParts of bodies) - { + for (const bodyParts of bodies) { const hpTotal = Object.values(bodyParts).reduce((acc, curr) => acc + curr.max, 0); - if (hpTotal < currentHighest) - { + if (hpTotal < currentHighest) { // Found collection with lower value that previous, use it currentHighest = hpTotal; result = bodyParts; @@ -503,8 +469,7 @@ export class BotGenerator * @param botSkills Skills that should have their progress value randomised * @returns */ - protected generateSkills(botSkills: IBaseJsonSkills): botSkills - { + protected generateSkills(botSkills: IBaseJsonSkills): botSkills { const skillsToReturn: botSkills = { Common: this.getSkillsWithRandomisedProgressValue(botSkills.Common, true), Mastering: this.getSkillsWithRandomisedProgressValue(botSkills.Mastering, false), @@ -523,20 +488,16 @@ export class BotGenerator protected getSkillsWithRandomisedProgressValue( skills: Record, isCommonSkills: boolean, - ): IBaseSkill[] - { - if (Object.keys(skills ?? []).length === 0) - { + ): IBaseSkill[] { + if (Object.keys(skills ?? []).length === 0) { return []; } return Object.keys(skills) - .map((skillKey): IBaseSkill => - { + .map((skillKey): IBaseSkill => { // Get skill from dict, skip if not found const skill = skills[skillKey]; - if (!skill) - { + if (!skill) { return undefined; } @@ -544,8 +505,7 @@ export class BotGenerator const skillToAdd: IBaseSkill = { Id: skillKey, Progress: this.randomUtil.getInt(skill.min, skill.max) }; // Common skills have additional props - if (isCommonSkills) - { + if (isCommonSkills) { (skillToAdd as Common).PointsEarnedDuringSession = 0; (skillToAdd as Common).LastAccess = 0; } @@ -560,8 +520,7 @@ export class BotGenerator * @param bot bot to update * @returns updated IBotBase object */ - protected addIdsToBot(bot: IBotBase): void - { + protected addIdsToBot(bot: IBotBase): void { const botId = this.hashUtil.generate(); bot._id = botId; @@ -573,15 +532,12 @@ export class BotGenerator * Update all inventory items that make use of this value too * @param profile Profile to update */ - protected generateInventoryId(profile: IBotBase): void - { + protected generateInventoryId(profile: IBotBase): void { const newInventoryItemId = this.hashUtil.generate(); - for (const item of profile.Inventory.items) - { + for (const item of profile.Inventory.items) { // Root item found, update its _id value to newly generated id - if (item._tpl === ItemTpl.INVENTORY_DEFAULT) - { + if (item._tpl === ItemTpl.INVENTORY_DEFAULT) { item._id = newInventoryItemId; continue; @@ -589,14 +545,12 @@ export class BotGenerator // Optimisation - skip items without a parentId // They are never linked to root inventory item + we already handled root item above - if (!item.parentId) - { + if (!item.parentId) { continue; } // Item is a child of root inventory item, update its parentId value to newly generated id - if (item.parentId === profile.Inventory.equipment) - { + if (item.parentId === profile.Inventory.equipment) { item.parentId = newInventoryItemId; } } @@ -612,11 +566,9 @@ export class BotGenerator * @param botInfo bot info object to update * @returns Chosen game version */ - protected setRandomisedGameVersionAndCategory(botInfo: Info): string - { + protected setRandomisedGameVersionAndCategory(botInfo: Info): string { // Special case - if (botInfo.Nickname.toLowerCase() === "nikita") - { + if (botInfo.Nickname.toLowerCase() === "nikita") { botInfo.GameVersion = GameEditions.UNHEARD; botInfo.MemberCategory = MemberCategory.DEVELOPER; @@ -627,8 +579,7 @@ export class BotGenerator botInfo.GameVersion = this.weightedRandomHelper.getWeightedValue(this.pmcConfig.gameVersionWeight); // Choose appropriate member category value - switch (botInfo.GameVersion) - { + switch (botInfo.GameVersion) { case GameEditions.EDGE_OF_DARKNESS: botInfo.MemberCategory = MemberCategory.UNIQUE_ID; break; @@ -654,8 +605,7 @@ export class BotGenerator * @param bot bot to add dogtag to * @returns Bot with dogtag added */ - protected addDogtagToBot(bot: IBotBase): void - { + protected addDogtagToBot(bot: IBotBase): void { const dogtagUpd: Upd = { SpawnedInSession: true, Dogtag: { @@ -691,12 +641,9 @@ export class BotGenerator * @param gameVersion edge_of_darkness / standard * @returns item tpl */ - protected getDogtagTplByGameVersionAndSide(side: string, gameVersion: string): string - { - if (side.toLowerCase() == "usec") - { - switch (gameVersion) - { + protected getDogtagTplByGameVersionAndSide(side: string, gameVersion: string): string { + if (side.toLowerCase() == "usec") { + switch (gameVersion) { case GameEditions.EDGE_OF_DARKNESS: return ItemTpl.BARTER_DOGTAG_USEC_EOD; case GameEditions.UNHEARD: @@ -706,8 +653,7 @@ export class BotGenerator } } - switch (gameVersion) - { + switch (gameVersion) { case GameEditions.EDGE_OF_DARKNESS: return ItemTpl.BARTER_DOGTAG_BEAR_EOD; case GameEditions.UNHEARD: @@ -721,10 +667,8 @@ export class BotGenerator * Adjust a PMCs pocket tpl to UHD if necessary, otherwise do nothing * @param bot Pmc object to adjust */ - protected setPmcPocketsByGameVersion(bot: IBotBase): void - { - if (bot.Info.GameVersion === GameEditions.UNHEARD) - { + protected setPmcPocketsByGameVersion(bot: IBotBase): void { + if (bot.Info.GameVersion === GameEditions.UNHEARD) { const pockets = bot.Inventory.items.find((item) => item.slotId === "Pockets"); pockets._tpl = ItemTpl.POCKETS_1X4_TUE; } diff --git a/project/src/generators/BotInventoryGenerator.ts b/project/src/generators/BotInventoryGenerator.ts index 5af82c8c..def5a3c2 100644 --- a/project/src/generators/BotInventoryGenerator.ts +++ b/project/src/generators/BotInventoryGenerator.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { BotEquipmentModGenerator } from "@spt/generators/BotEquipmentModGenerator"; import { BotLootGenerator } from "@spt/generators/BotLootGenerator"; import { BotWeaponGenerator } from "@spt/generators/BotWeaponGenerator"; @@ -14,10 +13,7 @@ import { EquipmentSlots } from "@spt/models/enums/EquipmentSlots"; import { GameEditions } from "@spt/models/enums/GameEditions"; import { ItemTpl } from "@spt/models/enums/ItemTpl"; import { IGenerateEquipmentProperties } from "@spt/models/spt/bots/IGenerateEquipmentProperties"; -import { - EquipmentFilterDetails, - IBotConfig, -} from "@spt/models/spt/config/IBotConfig"; +import { EquipmentFilterDetails, IBotConfig } from "@spt/models/spt/config/IBotConfig"; import { ILogger } from "@spt/models/spt/utils/ILogger"; import { ConfigServer } from "@spt/servers/ConfigServer"; import { BotEquipmentModPoolService } from "@spt/services/BotEquipmentModPoolService"; @@ -25,10 +21,10 @@ 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 { inject, injectable } from "tsyringe"; @injectable() -export class BotInventoryGenerator -{ +export class BotInventoryGenerator { protected botConfig: IBotConfig; constructor( @@ -46,8 +42,7 @@ export class BotInventoryGenerator @inject("BotEquipmentModPoolService") protected botEquipmentModPoolService: BotEquipmentModPoolService, @inject("BotEquipmentModGenerator") protected botEquipmentModGenerator: BotEquipmentModGenerator, @inject("ConfigServer") protected configServer: ConfigServer, - ) - { + ) { this.botConfig = this.configServer.getConfig(ConfigTypes.BOT); } @@ -68,8 +63,7 @@ export class BotInventoryGenerator isPmc: boolean, botLevel: number, chosenGameVersion: string, - ): PmcInventory - { + ): PmcInventory { const templateInventory = botJsonTemplate.inventory; const wornItemChances = botJsonTemplate.chances; const itemGenerationLimitsMinMax = botJsonTemplate.generation; @@ -83,7 +77,8 @@ export class BotInventoryGenerator botRole, botInventory, botLevel, - chosenGameVersion); + chosenGameVersion, + ); // Roll weapon spawns (primary/secondary/holster) and generate a weapon for each roll that passed this.generateAndAddWeaponsToBot( @@ -107,8 +102,7 @@ export class BotInventoryGenerator * Create a pmcInventory object with all the base/generic items needed * @returns PmcInventory object */ - protected generateInventoryBase(): PmcInventory - { + protected generateInventoryBase(): PmcInventory { const equipmentId = this.hashUtil.generate(); const stashId = this.hashUtil.generate(); const questRaidItemsId = this.hashUtil.generate(); @@ -150,8 +144,7 @@ export class BotInventoryGenerator botInventory: PmcInventory, botLevel: number, chosenGameVersion: string, - ): void - { + ): void { // These will be handled later const excludedSlots: string[] = [ EquipmentSlots.POCKETS, @@ -167,11 +160,9 @@ export class BotInventoryGenerator const botEquipConfig = this.botConfig.equipment[this.botGeneratorHelper.getBotEquipmentRole(botRole)]; const randomistionDetails = this.botHelper.getBotRandomizationDetails(botLevel, botEquipConfig); - for (const equipmentSlot in templateInventory.equipment) - { + for (const equipmentSlot in templateInventory.equipment) { // Weapons have special generation and will be generated separately; ArmorVest should be generated after TactivalVest - if (excludedSlots.includes(equipmentSlot)) - { + if (excludedSlots.includes(equipmentSlot)) { continue; } @@ -191,9 +182,10 @@ export class BotInventoryGenerator // Generate below in specific order this.generateEquipment({ rootEquipmentSlot: EquipmentSlots.POCKETS, - rootEquipmentPool: chosenGameVersion === GameEditions.UNHEARD - ? { [ItemTpl.POCKETS_1X4_TUE]: 1 } - : templateInventory.equipment.Pockets, + rootEquipmentPool: + chosenGameVersion === GameEditions.UNHEARD + ? { [ItemTpl.POCKETS_1X4_TUE]: 1 } + : templateInventory.equipment.Pockets, modPool: templateInventory.mods, spawnChances: wornItemChances, botRole: botRole, @@ -249,15 +241,13 @@ export class BotInventoryGenerator }); // Bot has no armor vest and flagged to be foreced to wear armored rig in this event - if (botEquipConfig.forceOnlyArmoredRigWhenNoArmor && !hasArmorVest) - { + if (botEquipConfig.forceOnlyArmoredRigWhenNoArmor && !hasArmorVest) { // Filter rigs down to only those with armor this.filterRigsToThoseWithProtection(templateInventory.equipment); } // Optimisation - Remove armored rigs from pool - if (hasArmorVest) - { + if (hasArmorVest) { // Filter rigs down to only those with armor this.filterRigsToThoseWithoutProtection(templateInventory.equipment); } @@ -279,13 +269,10 @@ export class BotInventoryGenerator * Remove non-armored rigs from parameter data * @param templateEquipment Equpiment to filter TacticalVest of */ - protected filterRigsToThoseWithProtection(templateEquipment: Equipment): void - { + protected filterRigsToThoseWithProtection(templateEquipment: Equipment): void { const tacVestsWithArmor = Object.entries(templateEquipment.TacticalVest).reduce( - (newVestDictionary, [tplKey]) => - { - if (this.itemHelper.itemHasSlots(tplKey)) - { + (newVestDictionary, [tplKey]) => { + if (this.itemHelper.itemHasSlots(tplKey)) { newVestDictionary[tplKey] = templateEquipment.TacticalVest[tplKey]; } return newVestDictionary; @@ -300,13 +287,10 @@ export class BotInventoryGenerator * Remove armored rigs from parameter data * @param templateEquipment Equpiment to filter TacticalVest of */ - protected filterRigsToThoseWithoutProtection(templateEquipment: Equipment): void - { + protected filterRigsToThoseWithoutProtection(templateEquipment: Equipment): void { const tacVestsWithoutArmor = Object.entries(templateEquipment.TacticalVest).reduce( - (newVestDictionary, [tplKey]) => - { - if (!this.itemHelper.itemHasSlots(tplKey)) - { + (newVestDictionary, [tplKey]) => { + if (!this.itemHelper.itemHasSlots(tplKey)) { newVestDictionary[tplKey] = templateEquipment.TacticalVest[tplKey]; } return newVestDictionary; @@ -322,16 +306,14 @@ export class BotInventoryGenerator * @param settings Values to adjust how item is chosen and added to bot * @returns true when item added */ - protected generateEquipment(settings: IGenerateEquipmentProperties): boolean - { + protected generateEquipment(settings: IGenerateEquipmentProperties): boolean { const spawnChance = ([EquipmentSlots.POCKETS, EquipmentSlots.SECURED_CONTAINER] as string[]).includes( settings.rootEquipmentSlot, ) ? 100 : settings.spawnChances.equipment[settings.rootEquipmentSlot]; - if (typeof spawnChance === "undefined") - { + if (typeof spawnChance === "undefined") { this.logger.warning( this.localisationService.getText( "bot-no_spawn_chance_defined_for_equipment_slot", @@ -343,25 +325,21 @@ export class BotInventoryGenerator } const shouldSpawn = this.randomUtil.getChance100(spawnChance); - if (shouldSpawn && Object.keys(settings.rootEquipmentPool).length) - { + if (shouldSpawn && Object.keys(settings.rootEquipmentPool).length) { let pickedItemDb: ITemplateItem; let found = false; const maxAttempts = Math.round(Object.keys(settings.rootEquipmentPool).length * 0.75); // Roughly 75% of pool size let attempts = 0; - while (!found) - { - if (Object.values(settings.rootEquipmentPool).length === 0) - { + while (!found) { + if (Object.values(settings.rootEquipmentPool).length === 0) { return false; } const chosenItemTpl = this.weightedRandomHelper.getWeightedValue(settings.rootEquipmentPool); const dbResult = this.itemHelper.getItem(chosenItemTpl); - if (!dbResult[0]) - { + if (!dbResult[0]) { this.logger.error(this.localisationService.getText("bot-missing_item_template", chosenItemTpl)); this.logger.info(`EquipmentSlot -> ${settings.rootEquipmentSlot}`); @@ -378,11 +356,9 @@ export class BotInventoryGenerator chosenItemTpl, settings.rootEquipmentSlot, ); - if (compatabilityResult.incompatible) - { + if (compatabilityResult.incompatible) { // Tried x different items that failed, stop - if (attempts > maxAttempts) - { + if (attempts > maxAttempts) { return false; } @@ -390,9 +366,7 @@ export class BotInventoryGenerator delete settings.rootEquipmentPool[chosenItemTpl]; attempts++; - } - else - { + } else { // Success found = true; pickedItemDb = dbResult[1]; @@ -412,10 +386,9 @@ export class BotInventoryGenerator // Use dynamic mod pool if enabled in config for this bot const botEquipmentRole = this.botGeneratorHelper.getBotEquipmentRole(settings.botRole); if ( - this.botConfig.equipment[botEquipmentRole] - && settings.randomisationDetails?.randomisedArmorSlots?.includes(settings.rootEquipmentSlot) - ) - { + this.botConfig.equipment[botEquipmentRole] && + settings.randomisationDetails?.randomisedArmorSlots?.includes(settings.rootEquipmentSlot) + ) { settings.modPool[pickedItemDb._id] = this.getFilteredDynamicModsForItem( pickedItemDb._id, this.botConfig.equipment[botEquipmentRole].blacklist, @@ -423,8 +396,7 @@ export class BotInventoryGenerator } // Item has slots, fill them - if (pickedItemDb._props.Slots?.length > 0 && !settings.generateModsBlacklist?.includes(pickedItemDb._id)) - { + if (pickedItemDb._props.Slots?.length > 0 && !settings.generateModsBlacklist?.includes(pickedItemDb._id)) { const items = this.botEquipmentModGenerator.generateModsForEquipment( [item], id, @@ -432,9 +404,7 @@ export class BotInventoryGenerator settings, ); settings.inventory.items.push(...items); - } - else - { + } else { // No slots, push root item only settings.inventory.items.push(item); } @@ -454,16 +424,13 @@ export class BotInventoryGenerator protected getFilteredDynamicModsForItem( itemTpl: string, equipmentBlacklist: EquipmentFilterDetails[], - ): Record - { + ): Record { const modPool = this.botEquipmentModPoolService.getModsForGearSlot(itemTpl); - for (const modSlot of Object.keys(modPool ?? [])) - { + for (const modSlot of Object.keys(modPool ?? [])) { const blacklistedMods = equipmentBlacklist[0]?.equipment[modSlot] || []; const filteredMods = modPool[modSlot].filter((x) => !blacklistedMods.includes(x)); - if (filteredMods.length > 0) - { + if (filteredMods.length > 0) { modPool[modSlot] = filteredMods; } } @@ -491,14 +458,11 @@ export class BotInventoryGenerator isPmc: boolean, itemGenerationLimitsMinMax: Generation, botLevel: number, - ): void - { + ): void { const weaponSlotsToFill = this.getDesiredWeaponsForBot(equipmentChances); - for (const weaponSlot of weaponSlotsToFill) - { + 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) - { + if (weaponSlot.shouldSpawn && Object.keys(templateInventory.equipment[weaponSlot.slot]).length) { this.addWeaponAndMagazinesToInventory( sessionId, weaponSlot, @@ -519,8 +483,7 @@ export class BotInventoryGenerator * @param equipmentChances Chances bot has certain equipment * @returns What slots bot should have weapons generated for */ - protected getDesiredWeaponsForBot(equipmentChances: Chances): { slot: EquipmentSlots, shouldSpawn: boolean }[] - { + protected getDesiredWeaponsForBot(equipmentChances: Chances): { slot: EquipmentSlots; shouldSpawn: boolean }[] { const shouldSpawnPrimary = this.randomUtil.getChance100(equipmentChances.equipment.FirstPrimaryWeapon); return [ { slot: EquipmentSlots.FIRST_PRIMARY_WEAPON, shouldSpawn: shouldSpawnPrimary }, @@ -552,7 +515,7 @@ export class BotInventoryGenerator */ protected addWeaponAndMagazinesToInventory( sessionId: string, - weaponSlot: { slot: EquipmentSlots, shouldSpawn: boolean }, + weaponSlot: { slot: EquipmentSlots; shouldSpawn: boolean }, templateInventory: Inventory, botInventory: PmcInventory, equipmentChances: Chances, @@ -560,8 +523,7 @@ export class BotInventoryGenerator isPmc: boolean, itemGenerationWeights: Generation, botLevel: number, - ): void - { + ): void { const generatedWeapon = this.botWeaponGenerator.generateRandomWeapon( sessionId, weaponSlot.slot, diff --git a/project/src/generators/BotLevelGenerator.ts b/project/src/generators/BotLevelGenerator.ts index 0e98fbd7..47f2755e 100644 --- a/project/src/generators/BotLevelGenerator.ts +++ b/project/src/generators/BotLevelGenerator.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { MinMax } from "@spt/models/common/MinMax"; import { IRandomisedBotLevelResult } from "@spt/models/eft/bot/IRandomisedBotLevelResult"; import { IBotBase } from "@spt/models/eft/common/tables/IBotBase"; @@ -6,16 +5,15 @@ import { BotGenerationDetails } from "@spt/models/spt/bots/BotGenerationDetails" import { ILogger } from "@spt/models/spt/utils/ILogger"; import { DatabaseService } from "@spt/services/DatabaseService"; import { RandomUtil } from "@spt/utils/RandomUtil"; +import { inject, injectable } from "tsyringe"; @injectable() -export class BotLevelGenerator -{ +export class BotLevelGenerator { constructor( @inject("PrimaryLogger") protected logger: ILogger, @inject("RandomUtil") protected randomUtil: RandomUtil, @inject("DatabaseService") protected databaseService: DatabaseService, - ) - {} + ) {} /** * Return a randomised bot level and exp value @@ -28,8 +26,7 @@ export class BotLevelGenerator levelDetails: MinMax, botGenerationDetails: BotGenerationDetails, bot: IBotBase, - ): IRandomisedBotLevelResult - { + ): IRandomisedBotLevelResult { const expTable = this.databaseService.getGlobals().config.exp.level.exp_table; const highestLevel = this.getHighestRelativeBotLevel(botGenerationDetails, levelDetails, expTable.length); const lowestLevel = this.getLowestRelativeBotLevel(botGenerationDetails, levelDetails, expTable.length); @@ -38,14 +35,12 @@ export class BotLevelGenerator let exp = 0; const level = this.randomUtil.getInt(lowestLevel, highestLevel); - for (let i = 0; i < level; i++) - { + for (let i = 0; i < level; i++) { exp += expTable[i].exp; } // Sprinkle in some random exp within the level, unless we are at max level. - if (level < expTable.length - 1) - { + if (level < expTable.length - 1) { exp += this.randomUtil.getInt(0, expTable[level].exp - 1); } @@ -63,16 +58,14 @@ export class BotLevelGenerator botGenerationDetails: BotGenerationDetails, levelDetails: MinMax, maxLevel: number, - ): number - { - const maxPossibleLevel - = botGenerationDetails.isPmc && botGenerationDetails.locationSpecificPmcLevelOverride + ): number { + const maxPossibleLevel = + botGenerationDetails.isPmc && botGenerationDetails.locationSpecificPmcLevelOverride ? Math.min(botGenerationDetails.locationSpecificPmcLevelOverride.max, maxLevel) // Was a PMC and they have a level override : Math.min(levelDetails.max, maxLevel); // Not pmc with override or non-pmc let level = botGenerationDetails.playerLevel + botGenerationDetails.botRelativeLevelDeltaMax; - if (level > maxPossibleLevel) - { + if (level > maxPossibleLevel) { level = maxPossibleLevel; } @@ -90,19 +83,17 @@ export class BotLevelGenerator botGenerationDetails: BotGenerationDetails, levelDetails: MinMax, maxlevel: number, - ): number - { - const minPossibleLevel - = botGenerationDetails.isPmc && botGenerationDetails.locationSpecificPmcLevelOverride + ): number { + const minPossibleLevel = + botGenerationDetails.isPmc && botGenerationDetails.locationSpecificPmcLevelOverride ? Math.min( - Math.max(levelDetails.min, botGenerationDetails.locationSpecificPmcLevelOverride.min), // Biggest between json min and the botgen min - maxlevel, // Fallback if value above is crazy (default is 79) - ) + Math.max(levelDetails.min, botGenerationDetails.locationSpecificPmcLevelOverride.min), // Biggest between json min and the botgen min + maxlevel, // Fallback if value above is crazy (default is 79) + ) : Math.min(levelDetails.min, maxlevel); // Not pmc with override or non-pmc let level = botGenerationDetails.playerLevel - botGenerationDetails.botRelativeLevelDeltaMin; - if (level < minPossibleLevel) - { + if (level < minPossibleLevel) { level = minPossibleLevel; } diff --git a/project/src/generators/BotLootGenerator.ts b/project/src/generators/BotLootGenerator.ts index 044fecbb..0ad35696 100644 --- a/project/src/generators/BotLootGenerator.ts +++ b/project/src/generators/BotLootGenerator.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { BotWeaponGenerator } from "@spt/generators/BotWeaponGenerator"; import { BotGeneratorHelper } from "@spt/helpers/BotGeneratorHelper"; import { BotHelper } from "@spt/helpers/BotHelper"; @@ -23,13 +22,13 @@ 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 { ICloner } from "@spt/utils/cloners/ICloner"; +import { inject, injectable } from "tsyringe"; @injectable() -export class BotLootGenerator -{ +export class BotLootGenerator { protected botConfig: IBotConfig; protected pmcConfig: IPmcConfig; @@ -49,14 +48,12 @@ export class BotLootGenerator @inject("LocalisationService") protected localisationService: LocalisationService, @inject("ConfigServer") protected configServer: ConfigServer, @inject("PrimaryCloner") protected cloner: ICloner, - ) - { + ) { this.botConfig = this.configServer.getConfig(ConfigTypes.BOT); this.pmcConfig = this.configServer.getConfig(ConfigTypes.PMC); } - protected getItemSpawnLimitsForBot(botRole: string): IItemSpawnLimitSettings - { + protected getItemSpawnLimitsForBot(botRole: string): IItemSpawnLimitSettings { // Init item limits const limitsForBotDict: Record = {}; this.initItemLimitArray(botRole, limitsForBotDict); @@ -80,25 +77,23 @@ export class BotLootGenerator botRole: string, botInventory: PmcInventory, botLevel: number, - ): void - { + ): void { // Limits on item types to be added as loot const itemCounts = botJsonTemplate.generation.items; 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 - ) - { + !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; @@ -107,9 +102,7 @@ export class BotLootGenerator let backpackLootCount = Number( this.weightedRandomHelper.getWeightedValue(itemCounts.backpackLoot.weights), ); - let pocketLootCount = Number( - this.weightedRandomHelper.getWeightedValue(itemCounts.pocketLoot.weights), - ); + let pocketLootCount = Number(this.weightedRandomHelper.getWeightedValue(itemCounts.pocketLoot.weights)); let vestLootCount = this.weightedRandomHelper.getWeightedValue(itemCounts.vestLoot.weights); const specialLootItemCount = Number( this.weightedRandomHelper.getWeightedValue(itemCounts.specialItems.weights), @@ -120,16 +113,13 @@ export class BotLootGenerator const foodItemCount = Number(this.weightedRandomHelper.getWeightedValue(itemCounts.food.weights)); const drinkItemCount = Number(this.weightedRandomHelper.getWeightedValue(itemCounts.drink.weights)); - let currencyItemCount = Number( - this.weightedRandomHelper.getWeightedValue(itemCounts.currency.weights), - ); + let currencyItemCount = Number(this.weightedRandomHelper.getWeightedValue(itemCounts.currency.weights)); const stimItemCount = Number(this.weightedRandomHelper.getWeightedValue(itemCounts.stims.weights)); const grenadeCount = Number(this.weightedRandomHelper.getWeightedValue(itemCounts.grenades.weights)); // If bot has been flagged as not having loot, set below counts to 0 - if (this.botConfig.disableLootOnBotTypes?.includes(botRole.toLowerCase())) - { + if (this.botConfig.disableLootOnBotTypes?.includes(botRole.toLowerCase())) { backpackLootCount = 0; pocketLootCount = 0; vestLootCount = 0; @@ -137,8 +127,7 @@ export class BotLootGenerator } // Forced pmc healing loot into secure container - if (isPmc && this.pmcConfig.forceHealingItemsIntoSecure) - { + if (isPmc && this.pmcConfig.forceHealingItemsIntoSecure) { this.addForcedMedicalItemsToPmcSecure(botInventory, botRole); } @@ -255,11 +244,9 @@ export class BotLootGenerator ); // Backpack - generate loot if they have one - if (containersBotHasAvailable.includes(EquipmentSlots.BACKPACK)) - { + if (containersBotHasAvailable.includes(EquipmentSlots.BACKPACK)) { // Add randomly generated weapon to PMC backpacks - if (isPmc && this.randomUtil.getChance100(this.pmcConfig.looseWeaponInBackpackChancePercent)) - { + if (isPmc && this.randomUtil.getChance100(this.pmcConfig.looseWeaponInBackpackChancePercent)) { this.addLooseWeaponsToInventorySlot( sessionId, botInventory, @@ -287,8 +274,7 @@ export class BotLootGenerator } // TacticalVest - generate loot if they have one - if (containersBotHasAvailable.includes(EquipmentSlots.TACTICAL_VEST)) - { + if (containersBotHasAvailable.includes(EquipmentSlots.TACTICAL_VEST)) { // Vest this.addLootFromPool( this.botLootCacheService.getLootFromCache(botRole, isPmc, LootCacheType.VEST, botJsonTemplate), @@ -319,8 +305,7 @@ export class BotLootGenerator // Secure // only add if not a pmc or is pmc and flag is true - if (!isPmc || (isPmc && this.pmcConfig.addSecureContainerLootFromBotConfig)) - { + if (!isPmc || (isPmc && this.pmcConfig.addSecureContainerLootFromBotConfig)) { this.addLootFromPool( this.botLootCacheService.getLootFromCache(botRole, isPmc, LootCacheType.SECURE, botJsonTemplate), [EquipmentSlots.SECURED_CONTAINER], @@ -340,17 +325,14 @@ export class BotLootGenerator * @param botInventory Bot to check * @returns Array of available slots */ - protected getAvailableContainersBotCanStoreItemsIn(botInventory: PmcInventory): EquipmentSlots[] - { + protected getAvailableContainersBotCanStoreItemsIn(botInventory: PmcInventory): EquipmentSlots[] { const result = [EquipmentSlots.POCKETS]; - if (botInventory.items.some((item) => item.slotId === EquipmentSlots.TACTICAL_VEST)) - { + if (botInventory.items.some((item) => item.slotId === EquipmentSlots.TACTICAL_VEST)) { result.push(EquipmentSlots.TACTICAL_VEST); } - if (botInventory.items.some((item) => item.slotId === EquipmentSlots.BACKPACK)) - { + if (botInventory.items.some((item) => item.slotId === EquipmentSlots.BACKPACK)) { result.push(EquipmentSlots.BACKPACK); } @@ -362,8 +344,7 @@ export class BotLootGenerator * @param botInventory Inventory to add items to * @param botRole Role of bot (pmcBEAR/pmcUSEC) */ - protected addForcedMedicalItemsToPmcSecure(botInventory: PmcInventory, botRole: string): void - { + protected addForcedMedicalItemsToPmcSecure(botInventory: PmcInventory, botRole: string): void { // surv12 this.addLootFromPool( { "5d02797c86f774203f38e30a": 1 }, @@ -396,8 +377,7 @@ export class BotLootGenerator * @param nValue Value to bias choice * @returns Chosen number */ - protected getRandomisedCount(min: number, max: number, nValue: number): number - { + protected getRandomisedCount(min: number, max: number, nValue: number): number { const range = max - min; return this.randomUtil.getBiasedRandomNumber(min, max, range, nValue); } @@ -423,28 +403,23 @@ export class BotLootGenerator totalValueLimitRub = 0, isPmc = false, containersIdFull = new Set(), - ): void - { + ): void { // Loot pool has items const poolSize = Object.keys(pool).length; - if (poolSize > 0) - { + if (poolSize > 0) { let currentTotalRub = 0; let fitItemIntoContainerAttempts = 0; - for (let i = 0; i < totalItemCount; i++) - { + for (let i = 0; i < totalItemCount; i++) { // Pool can become empty if item spawn limits keep removing items - if (Object.keys(pool).length === 0) - { + if (Object.keys(pool).length === 0) { return; } const weightedItemTpl = this.weightedRandomHelper.getWeightedValue(pool); const itemResult = this.itemHelper.getItem(weightedItemTpl); const itemToAddTemplate = itemResult[1]; - if (!itemResult[0]) - { + if (!itemResult[0]) { this.logger.warning( `Unable to process item tpl: ${weightedItemTpl} for slots: ${equipmentSlots} on bot: ${botRole}`, ); @@ -452,10 +427,8 @@ export class BotLootGenerator continue; } - if (itemSpawnLimits) - { - if (this.itemHasReachedSpawnLimit(itemToAddTemplate, botRole, itemSpawnLimits)) - { + if (itemSpawnLimits) { + if (this.itemHasReachedSpawnLimit(itemToAddTemplate, botRole, itemSpawnLimits)) { // Remove item from pool to prevent it being picked again delete pool[weightedItemTpl]; @@ -474,11 +447,9 @@ export class BotLootGenerator ]; // Is Simple-Wallet / WZ wallet - if (this.botConfig.walletLoot.walletTplPool.includes(weightedItemTpl)) - { + if (this.botConfig.walletLoot.walletTplPool.includes(weightedItemTpl)) { const addCurrencyToWallet = this.randomUtil.getChance100(this.botConfig.walletLoot.chancePercent); - if (addCurrencyToWallet) - { + if (addCurrencyToWallet) { // Create the currency items we want to add to wallet const itemsToAdd = this.createWalletLoot(newRootItemId); @@ -490,11 +461,9 @@ export class BotLootGenerator this.cloner.clone(containerGrid), // MUST clone grid before passing in as function modifies grid itemsToAdd, ); - if (canAddToContainer) - { + if (canAddToContainer) { // Add each currency to wallet - for (const itemToAdd of itemsToAdd) - { + for (const itemToAdd of itemsToAdd) { this.inventoryHelper.placeItemInContainer( containerGrid, itemToAdd, @@ -503,7 +472,7 @@ export class BotLootGenerator ); } - itemWithChildrenToAdd.push(...itemsToAdd.flatMap((moneyStack) => moneyStack)); + itemWithChildrenToAdd.push(...itemsToAdd.flat()); } } } @@ -521,10 +490,8 @@ export class BotLootGenerator ); // Handle when item cannot be added - if (itemAddedResult !== ItemAddedResult.SUCCESS) - { - if (itemAddedResult === ItemAddedResult.NO_CONTAINERS) - { + if (itemAddedResult !== ItemAddedResult.SUCCESS) { + if (itemAddedResult === ItemAddedResult.NO_CONTAINERS) { // Bot has no container to put item in, exit this.logger.debug( `Unable to add: ${totalItemCount} items to bot as it lacks a container to include them`, @@ -533,8 +500,7 @@ export class BotLootGenerator } fitItemIntoContainerAttempts++; - if (fitItemIntoContainerAttempts >= 4) - { + if (fitItemIntoContainerAttempts >= 4) { this.logger.debug( `Failed to place item ${i} of ${totalItemCount} items into ${botRole} containers: ${equipmentSlots.join( ",", @@ -554,11 +520,9 @@ export class BotLootGenerator fitItemIntoContainerAttempts = 0; // Stop adding items to bots pool if rolling total is over total limit - if (totalValueLimitRub > 0) - { + if (totalValueLimitRub > 0) { currentTotalRub += this.handbookHelper.getTemplatePrice(itemToAddTemplate._id); - if (currentTotalRub > totalValueLimitRub) - { + if (currentTotalRub > totalValueLimitRub) { break; } } @@ -566,8 +530,7 @@ export class BotLootGenerator } } - protected createWalletLoot(walletId: string): Item[][] - { + protected createWalletLoot(walletId: string): Item[][] { const result: Item[][] = []; // Choose how many stacks of currency will be added to wallet @@ -575,8 +538,7 @@ export class BotLootGenerator this.botConfig.walletLoot.itemCount.min, this.botConfig.walletLoot.itemCount.max, ); - for (let index = 0; index < itemCount; index++) - { + for (let index = 0; index < itemCount; index++) { // Choose the size of the currency stack - default is 5k, 10k, 15k, 20k, 25k const chosenStackCount = Number( this.weightedRandomHelper.getWeightedValue(this.botConfig.walletLoot.stackSizeWeight), @@ -606,26 +568,21 @@ export class BotLootGenerator itemToAddChildrenTo: Item[], isPmc: boolean, botRole: string, - ): void - { + ): void { // Fill ammo box - if (this.itemHelper.isOfBaseclass(itemToAddTemplate._id, BaseClasses.AMMO_BOX)) - { + if (this.itemHelper.isOfBaseclass(itemToAddTemplate._id, BaseClasses.AMMO_BOX)) { this.itemHelper.addCartridgesToAmmoBox(itemToAddChildrenTo, itemToAddTemplate); } // Make money a stack - else if (this.itemHelper.isOfBaseclass(itemToAddTemplate._id, BaseClasses.MONEY)) - { + else if (this.itemHelper.isOfBaseclass(itemToAddTemplate._id, BaseClasses.MONEY)) { this.randomiseMoneyStackSize(botRole, itemToAddTemplate, itemToAddChildrenTo[0]); } // Make ammo a stack - else if (this.itemHelper.isOfBaseclass(itemToAddTemplate._id, BaseClasses.AMMO)) - { + else if (this.itemHelper.isOfBaseclass(itemToAddTemplate._id, BaseClasses.AMMO)) { this.randomiseAmmoStackSize(isPmc, itemToAddTemplate, itemToAddChildrenTo[0]); } // Must add soft inserts/plates - else if (this.itemHelper.itemRequiresSoftInserts(itemToAddTemplate._id)) - { + else if (this.itemHelper.itemRequiresSoftInserts(itemToAddTemplate._id)) { this.itemHelper.addChildSlotItems(itemToAddChildrenTo, itemToAddTemplate, undefined, false); } } @@ -649,8 +606,7 @@ export class BotLootGenerator isPmc: boolean, botLevel: number, containersIdFull?: Set, - ): void - { + ): void { const chosenWeaponType = this.randomUtil.getArrayValue([ EquipmentSlots.FIRST_PRIMARY_WEAPON, EquipmentSlots.FIRST_PRIMARY_WEAPON, @@ -661,10 +617,8 @@ export class BotLootGenerator this.pmcConfig.looseWeaponInBackpackLootMinMax.min, this.pmcConfig.looseWeaponInBackpackLootMinMax.max, ); - if (randomisedWeaponCount > 0) - { - for (let i = 0; i < randomisedWeaponCount; i++) - { + if (randomisedWeaponCount > 0) { + for (let i = 0; i < randomisedWeaponCount; i++) { const generatedWeapon = this.botWeaponGenerator.generateRandomWeapon( sessionId, chosenWeaponType, @@ -684,8 +638,7 @@ export class BotLootGenerator containersIdFull, ); - if (result !== ItemAddedResult.SUCCESS) - { + if (result !== ItemAddedResult.SUCCESS) { this.logger.debug( `Failed to add additional weapon ${generatedWeapon.weapon[0]._id} to bot backpack, reason: ${ItemAddedResult[result]}`, ); @@ -700,12 +653,10 @@ export class BotLootGenerator * @param botRole Role the bot has * @param limitCount */ - protected initItemLimitArray(botRole: string, limitCount: Record): void - { + protected initItemLimitArray(botRole: string, limitCount: Record): void { // Init current count of items we want to limit const spawnLimits = this.getItemSpawnLimitsForBotType(botRole); - for (const limit in spawnLimits) - { + for (const limit in spawnLimits) { limitCount[limit] = 0; } } @@ -721,24 +672,20 @@ export class BotLootGenerator itemTemplate: ITemplateItem, botRole: string, itemSpawnLimits: IItemSpawnLimitSettings, - ): boolean - { + ): boolean { // PMCs and scavs have different sections of bot config for spawn limits - if (!!itemSpawnLimits && Object.keys(itemSpawnLimits.globalLimits).length === 0) - { + if (!!itemSpawnLimits && Object.keys(itemSpawnLimits.globalLimits).length === 0) { // No items found in spawn limit, drop out return false; } // No spawn limits, skipping - if (!itemSpawnLimits) - { + if (!itemSpawnLimits) { return false; } const idToCheckFor = this.getMatchingIdFromSpawnLimits(itemTemplate, itemSpawnLimits.globalLimits); - if (!idToCheckFor) - { + if (!idToCheckFor) { // ParentId or tplid not found in spawnLimits, not a spawn limited item, skip return false; } @@ -747,11 +694,9 @@ export class BotLootGenerator itemSpawnLimits.currentLimits[idToCheckFor]++; // Check if over limit - if (itemSpawnLimits.currentLimits[idToCheckFor] > itemSpawnLimits.globalLimits[idToCheckFor]) - { + 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[idToCheckFor] * 10) - { + if (itemSpawnLimits.currentLimits[idToCheckFor] > itemSpawnLimits[idToCheckFor] * 10) { this.logger.debug( this.localisationService.getText("bot-item_spawn_limit_reached_skipping_item", { botRole: botRole, @@ -775,12 +720,10 @@ export class BotLootGenerator * @param itemTemplate item details from db * @param moneyItem Money item to randomise */ - protected randomiseMoneyStackSize(botRole: string, itemTemplate: ITemplateItem, moneyItem: Item): void - { + protected randomiseMoneyStackSize(botRole: string, itemTemplate: ITemplateItem, moneyItem: Item): void { // Get all currency weights for this bot type let currencyWeights = this.botConfig.currencyStackSize[botRole]; - if (!currencyWeights) - { + if (!currencyWeights) { currencyWeights = this.botConfig.currencyStackSize.default; } @@ -797,15 +740,14 @@ export class BotLootGenerator * @param itemTemplate item details from db * @param ammoItem Ammo item to randomise */ - protected randomiseAmmoStackSize(isPmc: boolean, itemTemplate: ITemplateItem, ammoItem: Item): void - { - const randomSize - = itemTemplate._props.StackMaxSize === 1 + protected randomiseAmmoStackSize(isPmc: boolean, itemTemplate: ITemplateItem, ammoItem: Item): void { + const randomSize = + itemTemplate._props.StackMaxSize === 1 ? 1 : this.randomUtil.getInt( - itemTemplate._props.StackMinRandom, - Math.min(itemTemplate._props.StackMaxRandom, 60), - ); + itemTemplate._props.StackMinRandom, + Math.min(itemTemplate._props.StackMaxRandom, 60), + ); this.itemHelper.addUpdObjectToItem(ammoItem); @@ -818,15 +760,12 @@ export class BotLootGenerator * @param botRole what role does the bot have * @returns Dictionary of tplIds and limit */ - protected getItemSpawnLimitsForBotType(botRole: string): Record - { - if (this.botHelper.isBotPmc(botRole)) - { + protected getItemSpawnLimitsForBotType(botRole: string): Record { + if (this.botHelper.isBotPmc(botRole)) { return this.botConfig.itemSpawnLimits.pmc; } - if (this.botConfig.itemSpawnLimits[botRole.toLowerCase()]) - { + if (this.botConfig.itemSpawnLimits[botRole.toLowerCase()]) { return this.botConfig.itemSpawnLimits[botRole.toLowerCase()]; } @@ -843,16 +782,13 @@ export class BotLootGenerator * @param spawnLimits Limits to check for item * @returns id as string, otherwise undefined */ - protected getMatchingIdFromSpawnLimits(itemTemplate: ITemplateItem, spawnLimits: Record): string - { - if (itemTemplate._id in spawnLimits) - { + protected getMatchingIdFromSpawnLimits(itemTemplate: ITemplateItem, spawnLimits: Record): string { + if (itemTemplate._id in spawnLimits) { return itemTemplate._id; } // tplId not found in spawnLimits, check if parentId is - if (itemTemplate._parent in spawnLimits) - { + if (itemTemplate._parent in spawnLimits) { return itemTemplate._parent; } diff --git a/project/src/generators/BotWeaponGenerator.ts b/project/src/generators/BotWeaponGenerator.ts index e26843b4..2ba2e561 100644 --- a/project/src/generators/BotWeaponGenerator.ts +++ b/project/src/generators/BotWeaponGenerator.ts @@ -1,4 +1,3 @@ -import { inject, injectAll, injectable } from "tsyringe"; import { BotEquipmentModGenerator } from "@spt/generators/BotEquipmentModGenerator"; import { IInventoryMagGen } from "@spt/generators/weapongen/IInventoryMagGen"; import { InventoryMagGen } from "@spt/generators/weapongen/InventoryMagGen"; @@ -24,13 +23,13 @@ import { BotWeaponModLimitService } from "@spt/services/BotWeaponModLimitService import { DatabaseService } from "@spt/services/DatabaseService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { RepairService } from "@spt/services/RepairService"; -import { ICloner } from "@spt/utils/cloners/ICloner"; import { HashUtil } from "@spt/utils/HashUtil"; import { RandomUtil } from "@spt/utils/RandomUtil"; +import { ICloner } from "@spt/utils/cloners/ICloner"; +import { inject, injectAll, injectable } from "tsyringe"; @injectable() -export class BotWeaponGenerator -{ +export class BotWeaponGenerator { protected readonly modMagazineSlotId = "mod_magazine"; protected botConfig: IBotConfig; protected pmcConfig: IPmcConfig; @@ -52,8 +51,7 @@ export class BotWeaponGenerator @inject("RepairService") protected repairService: RepairService, @injectAll("InventoryMagGen") protected inventoryMagGenComponents: IInventoryMagGen[], @inject("PrimaryCloner") protected cloner: ICloner, - ) - { + ) { this.botConfig = this.configServer.getConfig(ConfigTypes.BOT); this.pmcConfig = this.configServer.getConfig(ConfigTypes.PMC); this.repairConfig = this.configServer.getConfig(ConfigTypes.REPAIR); @@ -79,8 +77,7 @@ export class BotWeaponGenerator botRole: string, isPmc: boolean, botLevel: number, - ): GenerateWeaponResult - { + ): GenerateWeaponResult { const weaponTpl = this.pickWeightedWeaponTplFromPool(equipmentSlot, botTemplateInventory); return this.generateWeaponByTpl( sessionId, @@ -101,8 +98,7 @@ export class BotWeaponGenerator * @param botTemplateInventory e.g. assault.json * @returns weapon tpl */ - public pickWeightedWeaponTplFromPool(equipmentSlot: string, botTemplateInventory: Inventory): string - { + public pickWeightedWeaponTplFromPool(equipmentSlot: string, botTemplateInventory: Inventory): string { const weaponPool = botTemplateInventory.equipment[equipmentSlot]; return this.weightedRandomHelper.getWeightedValue(weaponPool); } @@ -128,13 +124,11 @@ export class BotWeaponGenerator botRole: string, isPmc: boolean, botLevel: number, - ): GenerateWeaponResult - { + ): GenerateWeaponResult { const modPool = botTemplateInventory.mods; const weaponItemTemplate = this.itemHelper.getItem(weaponTpl)[1]; - if (!weaponItemTemplate) - { + if (!weaponItemTemplate) { this.logger.error(this.localisationService.getText("bot-missing_item_template", weaponTpl)); this.logger.error(`WeaponSlot -> ${equipmentSlot}`); @@ -142,8 +136,7 @@ export class BotWeaponGenerator } // Find ammo to use when filling magazines/chamber - if (!botTemplateInventory.Ammo) - { + 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")); @@ -160,15 +153,13 @@ export class BotWeaponGenerator ); // Chance to add randomised weapon enhancement - if (isPmc && this.randomUtil.getChance100(this.pmcConfig.weaponHasEnhancementChancePercent)) - { + 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)) - { + if (Object.keys(modPool).includes(weaponTpl)) { const botEquipmentRole = this.botGeneratorHelper.getBotEquipmentRole(botRole); const modLimits = this.botWeaponModLimitService.getWeaponModLimits(botEquipmentRole); @@ -190,8 +181,7 @@ export class BotWeaponGenerator } // Use weapon preset from globals.json if weapon isnt valid - if (!this.isWeaponValid(weaponWithModsArray, botRole)) - { + if (!this.isWeaponValid(weaponWithModsArray, botRole)) { // Weapon is bad, fall back to weapons preset weaponWithModsArray = this.getPresetWeaponMods( weaponTpl, @@ -203,17 +193,15 @@ export class BotWeaponGenerator } // Fill existing magazines to full and sync ammo type - for (const magazine of weaponWithModsArray.filter((item) => item.slotId === this.modMagazineSlotId)) - { + for (const magazine of weaponWithModsArray.filter((item) => item.slotId === this.modMagazineSlotId)) { this.fillExistingMagazines(weaponWithModsArray, magazine, ammoTpl); } // Add cartridge(s) to gun chamber(s) if ( - weaponItemTemplate._props.Chambers?.length > 0 - && weaponItemTemplate._props.Chambers[0]?._props?.filters[0]?.Filter?.includes(ammoTpl) - ) - { + 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); @@ -222,8 +210,7 @@ export class BotWeaponGenerator // Fill UBGL if found const ubglMod = weaponWithModsArray.find((x) => x.slotId === "mod_launcher"); let ubglAmmoTpl: string = undefined; - if (ubglMod) - { + if (ubglMod) { const ubglTemplate = this.itemHelper.getItem(ubglMod._tpl)[1]; ubglAmmoTpl = this.getWeightedCompatibleAmmo(botTemplateInventory.Ammo, ubglTemplate); this.fillUbgl(weaponWithModsArray, ubglMod, ubglAmmoTpl); @@ -245,13 +232,10 @@ export class BotWeaponGenerator * @param ammoTpl Cartridge to add to weapon * @param chamberSlotIds name of slots to create or add ammo to */ - protected addCartridgeToChamber(weaponWithModsArray: Item[], ammoTpl: string, chamberSlotIds: string[]): void - { - for (const slotId of chamberSlotIds) - { + protected addCartridgeToChamber(weaponWithModsArray: Item[], ammoTpl: string, chamberSlotIds: string[]): void { + for (const slotId of chamberSlotIds) { const existingItemWithSlot = weaponWithModsArray.find((x) => x.slotId === slotId); - if (!existingItemWithSlot) - { + if (!existingItemWithSlot) { // Not found, add new slot to weapon weaponWithModsArray.push({ _id: this.hashUtil.generate(), @@ -260,9 +244,7 @@ export class BotWeaponGenerator slotId: slotId, upd: { StackObjectsCount: 1 }, }); - } - else - { + } else { // Already exists, update values existingItemWithSlot._tpl = ammoTpl; existingItemWithSlot.upd = { StackObjectsCount: 1 }; @@ -286,8 +268,7 @@ export class BotWeaponGenerator equipmentSlot: string, weaponItemTemplate: ITemplateItem, botRole: string, - ): Item[] - { + ): Item[] { return [ { _id: this.hashUtil.generate(), @@ -312,8 +293,7 @@ export class BotWeaponGenerator weaponParentId: string, itemTemplate: ITemplateItem, botRole: string, - ): Item[] - { + ): Item[] { // Invalid weapon generated, fallback to preset this.logger.warning( this.localisationService.getText( @@ -325,17 +305,14 @@ export class BotWeaponGenerator // TODO: Right now, preset weapons trigger a lot of warnings regarding missing ammo in magazines & such let preset: IPreset; - for (const presetObj of Object.values(this.databaseService.getGlobals().ItemPresets)) - { - if (presetObj._items[0]._tpl === weaponTpl) - { + for (const presetObj of Object.values(this.databaseService.getGlobals().ItemPresets)) { + if (presetObj._items[0]._tpl === weaponTpl) { preset = this.cloner.clone(presetObj); break; } } - if (preset) - { + if (preset) { const parentItem = preset._items[0]; preset._items[0] = { ...parentItem, @@ -346,9 +323,7 @@ export class BotWeaponGenerator }, }; weaponMods.push(...preset._items); - } - else - { + } else { throw new Error(this.localisationService.getText("bot-missing_weapon_preset", weaponTpl)); } @@ -361,25 +336,20 @@ export class BotWeaponGenerator * @param botRole role of bot weapon is for * @returns true if valid */ - protected isWeaponValid(weaponItemArray: Item[], botRole: string): boolean - { - for (const mod of weaponItemArray) - { + protected isWeaponValid(weaponItemArray: Item[], botRole: string): boolean { + for (const mod of weaponItemArray) { const modTemplate = this.itemHelper.getItem(mod._tpl)[1]; - if (!modTemplate._props.Slots?.length) - { + if (!modTemplate._props.Slots?.length) { continue; } // Iterate over required slots in db item, check mod exists for that slot - for (const modSlotTemplate of modTemplate._props.Slots.filter((slot) => slot._required)) - { + for (const modSlotTemplate of modTemplate._props.Slots.filter((slot) => slot._required)) { const slotName = modSlotTemplate._name; const hasWeaponSlotItem = weaponItemArray.some( (weaponItem) => weaponItem.parentId === mod._id && weaponItem.slotId === slotName, ); - if (!hasWeaponSlotItem) - { + if (!hasWeaponSlotItem) { this.logger.warning( this.localisationService.getText("bot-weapons_required_slot_missing_item", { modSlot: modSlotTemplate._name, @@ -410,23 +380,20 @@ export class BotWeaponGenerator magWeights: GenerationData, inventory: PmcInventory, botRole: string, - ): void - { + ): 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) - { + 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) - { + if (!ammoTemplate) { this.logger.error( this.localisationService.getText("bot-unable_to_find_ammo_item", generatedWeaponResult.chosenAmmoTpl), ); @@ -435,8 +402,7 @@ export class BotWeaponGenerator } // Has an UBGL - if (generatedWeaponResult.chosenUbglAmmoTpl) - { + if (generatedWeaponResult.chosenUbglAmmoTpl) { this.addUbglGrenadesToBotInventory(weaponAndMods, generatedWeaponResult, inventory); } @@ -470,8 +436,7 @@ export class BotWeaponGenerator weaponMods: Item[], generatedWeaponResult: GenerateWeaponResult, inventory: PmcInventory, - ): void - { + ): void { // Find ubgl mod item + get details of it from db const ubglMod = weaponMods.find((x) => x.slotId === "mod_launcher"); const ubglDbTemplate = this.itemHelper.getItem(ubglMod._tpl)[1]; @@ -513,10 +478,8 @@ export class BotWeaponGenerator ammoTpl: string, stackSize: number, inventory: PmcInventory, - ): void - { - for (let i = 0; i < stackCount; i++) - { + ): void { + for (let i = 0; i < stackCount; i++) { const id = this.hashUtil.generate(); this.botGeneratorHelper.addItemWithChildrenToEquipmentSlot( [EquipmentSlots.SECURED_CONTAINER], @@ -539,21 +502,17 @@ export class BotWeaponGenerator weaponMods: Item[], weaponTemplate: ITemplateItem, botRole: string, - ): string - { + ): string { const magazine = weaponMods.find((m) => m.slotId === this.modMagazineSlotId); - if (!magazine) - { + if (!magazine) { // Edge case - magazineless chamber loaded weapons dont have magazines, e.g. mp18 // return default mag tpl - if (weaponTemplate._props.ReloadMode === "OnlyBarrel") - { + if (weaponTemplate._props.ReloadMode === "OnlyBarrel") { return this.botWeaponGeneratorHelper.getWeaponsDefaultMagazineTpl(weaponTemplate); } // log error if no magazine AND not a chamber loaded weapon (e.g. shotgun revolver) - if (!weaponTemplate._props.isChamberLoad) - { + if (!weaponTemplate._props.isChamberLoad) { // Shouldn't happen this.logger.warning( this.localisationService.getText("bot-weapon_missing_magazine_or_chamber", { @@ -583,13 +542,11 @@ export class BotWeaponGenerator protected getWeightedCompatibleAmmo( ammo: Record>, weaponTemplate: ITemplateItem, - ): string - { + ): string { const desiredCaliber = this.getWeaponCaliber(weaponTemplate); const compatibleCartridges = this.cloner.clone(ammo[desiredCaliber]); - if (!compatibleCartridges || compatibleCartridges?.length === 0) - { + if (!compatibleCartridges || compatibleCartridges?.length === 0) { this.logger.debug( this.localisationService.getText("bot-no_caliber_data_for_weapon_falling_back_to_default", { weaponId: weaponTemplate._id, @@ -603,19 +560,16 @@ export class BotWeaponGenerator } let chosenAmmoTpl: string; - while (!chosenAmmoTpl) - { + while (!chosenAmmoTpl) { const possibleAmmo = this.weightedRandomHelper.getWeightedValue(compatibleCartridges); // Weapon has chamber but does not support cartridge if ( - weaponTemplate._props.Chambers[0] - && !weaponTemplate._props.Chambers[0]._props.filters[0].Filter.includes(possibleAmmo) - ) - { + weaponTemplate._props.Chambers[0] && + !weaponTemplate._props.Chambers[0]._props.filters[0].Filter.includes(possibleAmmo) + ) { // Ran out of possible choices, use default ammo - if (Object.keys(compatibleCartridges).length === 0) - { + if (Object.keys(compatibleCartridges).length === 0) { this.logger.debug( this.localisationService.getText("bot-incompatible_ammo_for_weapon_falling_back_to_default", { chosenAmmo: chosenAmmoTpl, @@ -632,9 +586,7 @@ export class BotWeaponGenerator // Not compatible, remove item from possible list and try again delete compatibleCartridges[possibleAmmo]; - } - else - { + } else { // Compatible ammo found chosenAmmoTpl = possibleAmmo; break; @@ -649,28 +601,23 @@ export class BotWeaponGenerator * @param weaponTemplate Weapon to look up caliber of * @returns caliber as string */ - protected getWeaponCaliber(weaponTemplate: ITemplateItem): string - { - if (weaponTemplate._props.Caliber) - { + protected getWeaponCaliber(weaponTemplate: ITemplateItem): string { + if (weaponTemplate._props.Caliber) { return weaponTemplate._props.Caliber; } - if (weaponTemplate._props.ammoCaliber) - { + if (weaponTemplate._props.ammoCaliber) { // 9x18pmm has a typo, should be Caliber9x18PM return weaponTemplate._props.ammoCaliber === "Caliber9x18PMM" ? "Caliber9x18PM" : weaponTemplate._props.ammoCaliber; } - if (weaponTemplate._props.LinkedWeapon) - { + if (weaponTemplate._props.LinkedWeapon) { const ammoInChamber = this.itemHelper.getItem( weaponTemplate._props.Chambers[0]._props.filters[0].Filter[0], ); - if (!ammoInChamber[0]) - { + if (!ammoInChamber[0]) { return; } @@ -684,11 +631,9 @@ export class BotWeaponGenerator * @param magazine Magazine item * @param cartridgeTpl Cartridge to insert into magazine */ - protected fillExistingMagazines(weaponMods: Item[], magazine: Item, cartridgeTpl: string): void - { + protected fillExistingMagazines(weaponMods: Item[], magazine: Item, cartridgeTpl: string): void { const magazineTemplate = this.itemHelper.getItem(magazine._tpl)[1]; - if (!magazineTemplate) - { + if (!magazineTemplate) { this.logger.error(this.localisationService.getText("bot-unable_to_find_magazine_item", magazine._tpl)); return; @@ -699,12 +644,9 @@ export class BotWeaponGenerator // the revolver shotgun uses a magazine with chambers, not cartridges ("camora_xxx") // Exchange of the camora ammo is not necessary we could also just check for stackSize > 0 here // and remove the else - if (this.botWeaponGeneratorHelper.magazineIsCylinderRelated(parentItem._name)) - { + if (this.botWeaponGeneratorHelper.magazineIsCylinderRelated(parentItem._name)) { this.fillCamorasWithAmmo(weaponMods, magazine._id, cartridgeTpl); - } - else - { + } else { this.addOrUpdateMagazinesChildWithAmmo(weaponMods, magazine, cartridgeTpl, magazineTemplate); } } @@ -715,8 +657,7 @@ export class BotWeaponGenerator * @param ubglMod UBGL item * @param ubglAmmoTpl Grenade ammo tpl */ - protected fillUbgl(weaponMods: Item[], ubglMod: Item, ubglAmmoTpl: string): void - { + protected fillUbgl(weaponMods: Item[], ubglMod: Item, ubglAmmoTpl: string): void { weaponMods.push({ _id: this.hashUtil.generate(), _tpl: ubglAmmoTpl, @@ -739,13 +680,11 @@ export class BotWeaponGenerator magazine: Item, chosenAmmoTpl: string, magazineTemplate: ITemplateItem, - ): void - { + ): void { const magazineCartridgeChildItem = weaponWithMods.find( (m) => m.parentId === magazine._id && m.slotId === "cartridges", ); - if (magazineCartridgeChildItem) - { + if (magazineCartridgeChildItem) { // Delete the existing cartridge object and create fresh below weaponWithMods.splice(weaponWithMods.indexOf(magazineCartridgeChildItem), 1); } @@ -766,21 +705,16 @@ export class BotWeaponGenerator * @param magazineId magazine id to find and add to * @param ammoTpl ammo template id to hydate with */ - protected fillCamorasWithAmmo(weaponMods: Item[], magazineId: string, ammoTpl: string): void - { + protected fillCamorasWithAmmo(weaponMods: Item[], magazineId: string, ammoTpl: string): void { // for CylinderMagazine we exchange the ammo in the "camoras". // This might not be necessary since we already filled the camoras with a random whitelisted and compatible ammo type, // but I'm not sure whether this is also used elsewhere const camoras = weaponMods.filter((x) => x.parentId === magazineId && x.slotId.startsWith("camora")); - for (const camora of camoras) - { + for (const camora of camoras) { camora._tpl = ammoTpl; - if (camora.upd) - { + if (camora.upd) { camora.upd.StackObjectsCount = 1; - } - else - { + } else { camora.upd = { StackObjectsCount: 1 }; } } diff --git a/project/src/generators/FenceBaseAssortGenerator.ts b/project/src/generators/FenceBaseAssortGenerator.ts index a2930ae3..b0b2b077 100644 --- a/project/src/generators/FenceBaseAssortGenerator.ts +++ b/project/src/generators/FenceBaseAssortGenerator.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { HandbookHelper } from "@spt/helpers/HandbookHelper"; import { ItemHelper } from "@spt/helpers/ItemHelper"; import { PresetHelper } from "@spt/helpers/PresetHelper"; @@ -18,10 +17,10 @@ import { ItemFilterService } from "@spt/services/ItemFilterService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { SeasonalEventService } from "@spt/services/SeasonalEventService"; import { HashUtil } from "@spt/utils/HashUtil"; +import { inject, injectable } from "tsyringe"; @injectable() -export class FenceBaseAssortGenerator -{ +export class FenceBaseAssortGenerator { protected traderConfig: ITraderConfig; constructor( @@ -36,54 +35,45 @@ export class FenceBaseAssortGenerator @inject("LocalisationService") protected localisationService: LocalisationService, @inject("ConfigServer") protected configServer: ConfigServer, @inject("FenceService") protected fenceService: FenceService, - ) - { + ) { this.traderConfig = this.configServer.getConfig(ConfigTypes.TRADER); } /** * Create base fence assorts dynamically and store in memory */ - public generateFenceBaseAssorts(): void - { + public generateFenceBaseAssorts(): void { const blockedSeasonalItems = this.seasonalEventService.getInactiveSeasonalEventItems(); const baseFenceAssort = this.databaseService.getTrader(Traders.FENCE).assort; - for (const rootItemDb of this.itemHelper.getItems().filter((item) => this.isValidFenceItem(item))) - { + for (const rootItemDb of this.itemHelper.getItems().filter((item) => this.isValidFenceItem(item))) { // Skip blacklisted items - if (this.itemFilterService.isItemBlacklisted(rootItemDb._id)) - { + if (this.itemFilterService.isItemBlacklisted(rootItemDb._id)) { continue; } // Invalid - if (!this.itemHelper.isValidItem(rootItemDb._id)) - { + if (!this.itemHelper.isValidItem(rootItemDb._id)) { continue; } // Item base type blacklisted - if (this.traderConfig.fence.blacklist.length > 0) - { + if (this.traderConfig.fence.blacklist.length > 0) { if ( - this.traderConfig.fence.blacklist.includes(rootItemDb._id) - || this.itemHelper.isOfBaseclasses(rootItemDb._id, this.traderConfig.fence.blacklist) - ) - { + this.traderConfig.fence.blacklist.includes(rootItemDb._id) || + this.itemHelper.isOfBaseclasses(rootItemDb._id, this.traderConfig.fence.blacklist) + ) { continue; } } // Only allow rigs with no slots (carrier rigs) - if (this.itemHelper.isOfBaseclass(rootItemDb._id, BaseClasses.VEST) && rootItemDb._props.Slots.length > 0) - { + if (this.itemHelper.isOfBaseclass(rootItemDb._id, BaseClasses.VEST) && rootItemDb._props.Slots.length > 0) { continue; } // Skip seasonal event items when not in seasonal event - if (this.traderConfig.fence.blacklistSeasonalItems && blockedSeasonalItems.includes(rootItemDb._id)) - { + if (this.traderConfig.fence.blacklistSeasonalItems && blockedSeasonalItems.includes(rootItemDb._id)) { continue; } @@ -99,27 +89,22 @@ export class FenceBaseAssortGenerator ]; // Ensure ammo is not above penetration limit value - if (this.itemHelper.isOfBaseclasses(rootItemDb._id, [BaseClasses.AMMO_BOX, BaseClasses.AMMO])) - { - if (this.isAmmoAbovePenetrationLimit(rootItemDb)) - { + if (this.itemHelper.isOfBaseclasses(rootItemDb._id, [BaseClasses.AMMO_BOX, BaseClasses.AMMO])) { + if (this.isAmmoAbovePenetrationLimit(rootItemDb)) { continue; } } - if (this.itemHelper.isOfBaseclass(rootItemDb._id, BaseClasses.AMMO_BOX)) - { + if (this.itemHelper.isOfBaseclass(rootItemDb._id, BaseClasses.AMMO_BOX)) { // Only add cartridges to box if box has no children - if (itemWithChildrenToAdd.length === 1) - { + if (itemWithChildrenToAdd.length === 1) { this.itemHelper.addCartridgesToAmmoBox(itemWithChildrenToAdd, rootItemDb); } } // Ensure IDs are unique this.itemHelper.remapRootItemId(itemWithChildrenToAdd); - if (itemWithChildrenToAdd.length > 1) - { + if (itemWithChildrenToAdd.length > 1) { this.itemHelper.reparentItemAndChildren(itemWithChildrenToAdd[0], itemWithChildrenToAdd); itemWithChildrenToAdd[0].parentId = "hideout"; } @@ -142,11 +127,9 @@ export class FenceBaseAssortGenerator // Add all default presets to base fence assort const defaultPresets = Object.values(this.presetHelper.getDefaultPresets()); - for (const defaultPreset of defaultPresets) - { + for (const defaultPreset of defaultPresets) { // Skip presets we've already added - if (baseFenceAssort.items.some((item) => item.upd && item.upd.sptPresetId === defaultPreset._id)) - { + if (baseFenceAssort.items.some((item) => item.upd && item.upd.sptPresetId === defaultPreset._id)) { continue; } @@ -154,13 +137,11 @@ export class FenceBaseAssortGenerator const itemAndChildren: Item[] = this.itemHelper.replaceIDs(defaultPreset._items); // Find root item and add some properties to it - for (let i = 0; i < itemAndChildren.length; i++) - { + for (let i = 0; i < itemAndChildren.length; i++) { const mod = itemAndChildren[i]; // Build root Item info - if (!("parentId" in mod)) - { + if (!("parentId" in mod)) { mod.parentId = "hideout"; mod.slotId = "hideout"; mod.upd = { @@ -196,12 +177,12 @@ export class FenceBaseAssortGenerator * @param rootItemDb Ammo box or ammo item from items.db * @returns True if penetration value is above limit set in config */ - protected isAmmoAbovePenetrationLimit(rootItemDb: ITemplateItem): boolean - { + protected isAmmoAbovePenetrationLimit(rootItemDb: ITemplateItem): boolean { const ammoPenetrationPower = this.getAmmoPenetrationPower(rootItemDb); - if (ammoPenetrationPower === undefined) - { - this.logger.warning(this.localisationService.getText("fence-unable_to_get_ammo_penetration_value", rootItemDb._id)); + if (ammoPenetrationPower === undefined) { + this.logger.warning( + this.localisationService.getText("fence-unable_to_get_ammo_penetration_value", rootItemDb._id), + ); return false; } @@ -214,17 +195,14 @@ export class FenceBaseAssortGenerator * @param rootItemDb Ammo box or ammo item from items.db * @returns Penetration power of passed in item, undefined if it doesnt have a power */ - protected getAmmoPenetrationPower(rootItemDb: ITemplateItem): number | undefined - { - if (this.itemHelper.isOfBaseclass(rootItemDb._id, BaseClasses.AMMO_BOX)) - { + protected getAmmoPenetrationPower(rootItemDb: ITemplateItem): number | undefined { + if (this.itemHelper.isOfBaseclass(rootItemDb._id, BaseClasses.AMMO_BOX)) { // Get the cartridge tpl found inside ammo box const cartridgeTplInBox = rootItemDb._props.StackSlots[0]._props.filters[0].Filter[0]; // Look up cartridge tpl in db const ammoItemDb = this.itemHelper.getItem(cartridgeTplInBox); - if (!ammoItemDb[0]) - { + if (!ammoItemDb[0]) { this.logger.warning(this.localisationService.getText("fence-ammo_not_found_in_db", cartridgeTplInBox)); return undefined; @@ -234,8 +212,7 @@ export class FenceBaseAssortGenerator } // Plain old ammo, get its pen property - if (this.itemHelper.isOfBaseclass(rootItemDb._id, BaseClasses.AMMO)) - { + if (this.itemHelper.isOfBaseclass(rootItemDb._id, BaseClasses.AMMO)) { return rootItemDb._props.PenetrationPower; } @@ -248,26 +225,21 @@ export class FenceBaseAssortGenerator * @param armor Armor item array to add mods into * @param itemDbDetails Armor items db template */ - protected addChildrenToArmorModSlots(armor: Item[], itemDbDetails: ITemplateItem): void - { + protected addChildrenToArmorModSlots(armor: Item[], itemDbDetails: ITemplateItem): void { // Armor has no mods, make no additions const hasMods = itemDbDetails._props.Slots.length > 0; - if (!hasMods) - { + if (!hasMods) { return; } // Check for and add required soft inserts to armors const requiredSlots = itemDbDetails._props.Slots.filter((slot) => slot._required); const hasRequiredSlots = requiredSlots.length > 0; - if (hasRequiredSlots) - { - for (const requiredSlot of requiredSlots) - { + if (hasRequiredSlots) { + for (const requiredSlot of requiredSlots) { const modItemDbDetails = this.itemHelper.getItem(requiredSlot._props.filters[0].Plate)[1]; const plateTpl = requiredSlot._props.filters[0].Plate; // `Plate` property appears to be the 'default' item for slot - if (plateTpl === "") - { + if (plateTpl === "") { // Some bsg plate properties are empty, skip mod continue; } @@ -293,13 +265,10 @@ export class FenceBaseAssortGenerator const plateSlots = itemDbDetails._props.Slots.filter((slot) => this.itemHelper.isRemovablePlateSlot(slot._name), ); - if (plateSlots.length > 0) - { - for (const plateSlot of plateSlots) - { + if (plateSlots.length > 0) { + for (const plateSlot of plateSlots) { const plateTpl = plateSlot._props.filters[0].Plate; - if (!plateTpl) - { + if (!plateTpl) { // Bsg data lacks a default plate, skip adding mod continue; } @@ -325,10 +294,8 @@ export class FenceBaseAssortGenerator * @param item Item to check * @returns true if valid fence item */ - protected isValidFenceItem(item: ITemplateItem): boolean - { - if (item._type === "Item") - { + protected isValidFenceItem(item: ITemplateItem): boolean { + if (item._type === "Item") { return true; } diff --git a/project/src/generators/LocationLootGenerator.ts b/project/src/generators/LocationLootGenerator.ts index 22939756..cbc6a344 100644 --- a/project/src/generators/LocationLootGenerator.ts +++ b/project/src/generators/LocationLootGenerator.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { ContainerHelper } from "@spt/helpers/ContainerHelper"; import { ItemHelper } from "@spt/helpers/ItemHelper"; import { PresetHelper } from "@spt/helpers/PresetHelper"; @@ -22,29 +21,27 @@ import { DatabaseService } from "@spt/services/DatabaseService"; import { ItemFilterService } from "@spt/services/ItemFilterService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { SeasonalEventService } from "@spt/services/SeasonalEventService"; -import { ICloner } from "@spt/utils/cloners/ICloner"; import { MathUtil } from "@spt/utils/MathUtil"; import { ObjectId } from "@spt/utils/ObjectId"; import { ProbabilityObject, ProbabilityObjectArray, RandomUtil } from "@spt/utils/RandomUtil"; +import { ICloner } from "@spt/utils/cloners/ICloner"; +import { inject, injectable } from "tsyringe"; -export interface IContainerItem -{ - items: Item[] - width: number - height: number +export interface IContainerItem { + items: Item[]; + width: number; + height: number; } -export interface IContainerGroupCount -{ +export interface IContainerGroupCount { /** Containers this group has + probabilty to spawn */ - containerIdsWithProbability: Record + containerIdsWithProbability: Record; /** How many containers the map should spawn with this group id */ - chosenCount: number + chosenCount: number; } @injectable() -export class LocationLootGenerator -{ +export class LocationLootGenerator { protected locationConfig: ILocationConfig; constructor( @@ -61,8 +58,7 @@ export class LocationLootGenerator @inject("ItemFilterService") protected itemFilterService: ItemFilterService, @inject("ConfigServer") protected configServer: ConfigServer, @inject("PrimaryCloner") protected cloner: ICloner, - ) - { + ) { this.locationConfig = this.configServer.getConfig(ConfigTypes.LOCATION); } @@ -75,8 +71,7 @@ export class LocationLootGenerator public generateStaticContainers( locationBase: ILocationBase, staticAmmoDist: Record, - ): SpawnpointTemplate[] - { + ): SpawnpointTemplate[] { let staticLootItemCount = 0; const result: SpawnpointTemplate[] = []; const locationId = locationBase.Id.toLowerCase(); @@ -84,9 +79,10 @@ export class LocationLootGenerator const mapData = this.databaseService.getLocation(locationId); const staticWeaponsOnMapClone = this.cloner.clone(mapData.staticContainers.staticWeapons); - if (!staticWeaponsOnMapClone) - { - this.logger.error(this.localisationService.getText("location-unable_to_find_static_weapon_for_map", locationBase.Name)); + if (!staticWeaponsOnMapClone) { + this.logger.error( + this.localisationService.getText("location-unable_to_find_static_weapon_for_map", locationBase.Name), + ); } // Add mounted weapons to output loot @@ -94,18 +90,23 @@ export class LocationLootGenerator const allStaticContainersOnMapClone = this.cloner.clone(mapData.staticContainers.staticContainers); - if (!allStaticContainersOnMapClone) - { - this.logger.error(this.localisationService.getText("location-unable_to_find_static_container_for_map", locationBase.Name)); + if (!allStaticContainersOnMapClone) { + this.logger.error( + this.localisationService.getText("location-unable_to_find_static_container_for_map", locationBase.Name), + ); } const staticRandomisableContainersOnMap = this.getRandomisableContainersOnMap(allStaticContainersOnMapClone); // Containers that MUST be added to map (quest containers etc) const staticForcedOnMapClone = this.cloner.clone(mapData.staticContainers.staticForced); - if (!staticForcedOnMapClone) - { - this.logger.error(this.localisationService.getText("location-unable_to_find_forced_static_data_for_map", locationBase.Name)); + if (!staticForcedOnMapClone) { + this.logger.error( + this.localisationService.getText( + "location-unable_to_find_forced_static_data_for_map", + locationBase.Name, + ), + ); } // Keep track of static loot count @@ -117,8 +118,7 @@ export class LocationLootGenerator staticContainerCount += guaranteedContainers.length; // Add loot to guaranteed containers and add to result - for (const container of guaranteedContainers) - { + for (const container of guaranteedContainers) { const containerWithLoot = this.addLootToContainer( container, staticForcedOnMapClone, @@ -136,16 +136,14 @@ export class LocationLootGenerator // Randomisation is turned off globally or just turned off for this map if ( !( - this.locationConfig.containerRandomisationSettings.enabled - && this.locationConfig.containerRandomisationSettings.maps[locationId] + this.locationConfig.containerRandomisationSettings.enabled && + this.locationConfig.containerRandomisationSettings.maps[locationId] ) - ) - { + ) { this.logger.debug( `Container randomisation disabled, Adding ${staticRandomisableContainersOnMap.length} containers to ${locationBase.Name}`, ); - for (const container of staticRandomisableContainersOnMap) - { + for (const container of staticRandomisableContainersOnMap) { const containerWithLoot = this.addLootToContainer( container, staticForcedOnMapClone, @@ -164,27 +162,25 @@ export class LocationLootGenerator } // Group containers by their groupId - if (!mapData.statics) - { - this.logger.warning(this.localisationService.getText("location-unable_to_generate_static_loot", locationId)); + if (!mapData.statics) { + this.logger.warning( + this.localisationService.getText("location-unable_to_generate_static_loot", locationId), + ); return result; } const mapping = this.getGroupIdToContainerMappings(mapData.statics, staticRandomisableContainersOnMap); // For each of the container groups, choose from the pool of containers, hydrate container with loot and add to result array - for (const groupId in mapping) - { + for (const groupId in mapping) { const data = mapping[groupId]; // Count chosen was 0, skip - if (data.chosenCount === 0) - { + if (data.chosenCount === 0) { continue; } - if (Object.keys(data.containerIdsWithProbability).length === 0) - { + if (Object.keys(data.containerIdsWithProbability).length === 0) { this.logger.debug( `Group: ${groupId} has no containers with < 100% spawn chance to choose from, skipping`, ); @@ -192,15 +188,12 @@ export class LocationLootGenerator } // EDGE CASE: These are containers without a group and have a probability < 100% - if (groupId === "") - { + if (groupId === "") { const containerIdsCopy = this.cloner.clone(data.containerIdsWithProbability); // Roll each containers probability, if it passes, it gets added data.containerIdsWithProbability = {}; - for (const containerId in containerIdsCopy) - { - if (this.randomUtil.getChance100(containerIdsCopy[containerId] * 100)) - { + for (const containerId in containerIdsCopy) { + if (this.randomUtil.getChance100(containerIdsCopy[containerId] * 100)) { data.containerIdsWithProbability[containerId] = containerIdsCopy[containerId]; } } @@ -209,22 +202,19 @@ export class LocationLootGenerator data.chosenCount = Object.keys(data.containerIdsWithProbability).length; // EDGE CASE: chosen container count could be 0 - if (data.chosenCount === 0) - { + if (data.chosenCount === 0) { continue; } } // Pass possible containers into function to choose some const chosenContainerIds = this.getContainersByProbabilty(groupId, data); - for (const chosenContainerId of chosenContainerIds) - { + for (const chosenContainerId of chosenContainerIds) { // Look up container object from full list of containers on map const containerObject = staticRandomisableContainersOnMap.find( (staticContainer) => staticContainer.template.Id === chosenContainerId, ); - if (!containerObject) - { + if (!containerObject) { this.logger.debug( `Container: ${chosenContainerIds[chosenContainerId]} not found in staticRandomisableContainersOnMap, this is bad`, ); @@ -260,13 +250,12 @@ export class LocationLootGenerator * @param staticContainers * @returns IStaticContainerData array */ - protected getRandomisableContainersOnMap(staticContainers: IStaticContainerData[]): IStaticContainerData[] - { + protected getRandomisableContainersOnMap(staticContainers: IStaticContainerData[]): IStaticContainerData[] { return staticContainers.filter( (staticContainer) => - staticContainer.probability !== 1 - && !staticContainer.template.IsAlwaysSpawn - && !this.locationConfig.containerRandomisationSettings.containerTypesToNotRandomise.includes( + staticContainer.probability !== 1 && + !staticContainer.template.IsAlwaysSpawn && + !this.locationConfig.containerRandomisationSettings.containerTypesToNotRandomise.includes( staticContainer.template.Items[0]._tpl, ), ); @@ -277,13 +266,12 @@ export class LocationLootGenerator * @param staticContainersOnMap * @returns IStaticContainerData array */ - protected getGuaranteedContainers(staticContainersOnMap: IStaticContainerData[]): IStaticContainerData[] - { + protected getGuaranteedContainers(staticContainersOnMap: IStaticContainerData[]): IStaticContainerData[] { return staticContainersOnMap.filter( (staticContainer) => - staticContainer.probability === 1 - || staticContainer.template.IsAlwaysSpawn - || this.locationConfig.containerRandomisationSettings.containerTypesToNotRandomise.includes( + staticContainer.probability === 1 || + staticContainer.template.IsAlwaysSpawn || + this.locationConfig.containerRandomisationSettings.containerTypesToNotRandomise.includes( staticContainer.template.Items[0]._tpl, ), ); @@ -295,13 +283,11 @@ export class LocationLootGenerator * @param containerData Containers and probability values for a groupId * @returns List of chosen container Ids */ - protected getContainersByProbabilty(groupId: string, containerData: IContainerGroupCount): string[] - { + protected getContainersByProbabilty(groupId: string, containerData: IContainerGroupCount): string[] { const chosenContainerIds: string[] = []; const containerIds = Object.keys(containerData.containerIdsWithProbability); - if (containerData.chosenCount > containerIds.length) - { + if (containerData.chosenCount > containerIds.length) { this.logger.debug( `Group: ${groupId} wants ${containerData.chosenCount} containers but pool only has ${containerIds.length}, add what's available`, ); @@ -310,8 +296,7 @@ export class LocationLootGenerator // Create probability array with all possible container ids in this group and their relataive probability of spawning const containerDistribution = new ProbabilityObjectArray(this.mathUtil, this.cloner); - for (const x of containerIds) - { + for (const x of containerIds) { containerDistribution.push(new ProbabilityObject(x, containerData.containerIdsWithProbability[x])); } @@ -328,25 +313,22 @@ export class LocationLootGenerator protected getGroupIdToContainerMappings( staticContainerGroupData: IStaticContainer | Record, staticContainersOnMap: IStaticContainerData[], - ): Record - { + ): Record { // Create dictionary of all group ids and choose a count of containers the map will spawn of that group const mapping: Record = {}; - for (const groupId in staticContainerGroupData.containersGroups) - { + for (const groupId in staticContainerGroupData.containersGroups) { const groupData = staticContainerGroupData.containersGroups[groupId]; - if (!mapping[groupId]) - { + if (!mapping[groupId]) { mapping[groupId] = { containerIdsWithProbability: {}, chosenCount: this.randomUtil.getInt( Math.round( - groupData.minContainers - * this.locationConfig.containerRandomisationSettings.containerGroupMinSizeMultiplier, + groupData.minContainers * + this.locationConfig.containerRandomisationSettings.containerGroupMinSizeMultiplier, ), Math.round( - groupData.maxContainers - * this.locationConfig.containerRandomisationSettings.containerGroupMaxSizeMultiplier, + groupData.maxContainers * + this.locationConfig.containerRandomisationSettings.containerGroupMaxSizeMultiplier, ), ), }; @@ -359,18 +341,20 @@ export class LocationLootGenerator // Iterate over all containers and add to group keyed by groupId // Containers without a group go into a group with empty key "" - for (const container of staticContainersOnMap) - { + for (const container of staticContainersOnMap) { const groupData = staticContainerGroupData.containers[container.template.Id]; - if (!groupData) - { - this.logger.error(this.localisationService.getText("location-unable_to_find_container_in_statics_json", container.template.Id)); + if (!groupData) { + this.logger.error( + this.localisationService.getText( + "location-unable_to_find_container_in_statics_json", + container.template.Id, + ), + ); continue; } - if (container.probability === 1) - { + if (container.probability === 1) { this.logger.debug( `Container ${container.template.Id} with group ${groupData.groupId} had 100% chance to spawn was picked as random container, skipping`, ); @@ -399,8 +383,7 @@ export class LocationLootGenerator staticLootDist: Record, staticAmmoDist: Record, locationName: string, - ): IStaticContainerData - { + ): IStaticContainerData { const containerClone = this.cloner.clone(staticContainer); const containerTpl = containerClone.template.Items[0]._tpl; @@ -435,8 +418,7 @@ export class LocationLootGenerator // Add forced loot to chosen item pool const tplsToAddToContainer = tplsForced.concat(chosenTpls); - for (const tplToAdd of tplsToAddToContainer) - { + for (const tplToAdd of tplsToAddToContainer) { const chosenItemWithChildren = this.createStaticLootItem(tplToAdd, staticAmmoDist, parentId); const items = chosenItemWithChildren.items; const width = chosenItemWithChildren.width; @@ -444,10 +426,8 @@ export class LocationLootGenerator // look for open slot to put chosen item into const result = this.containerHelper.findSlotForItem(containerMap, width, height); - if (!result.success) - { - if (failedToFitCount >= this.locationConfig.fitLootIntoContainerAttempts) - { + if (!result.success) { + if (failedToFitCount >= this.locationConfig.fitLootIntoContainerAttempts) { // x attempts to fit an item, container is probably full, stop trying to add more break; } @@ -472,8 +452,7 @@ export class LocationLootGenerator items[0].location = { x: result.x!, y: result.y!, r: rotation }; // Add loot to container before returning - for (const item of items) - { + for (const item of items) { containerClone.template.Items.push(item); } } @@ -486,8 +465,7 @@ export class LocationLootGenerator * @param containerTpl Tpl id of the container * @returns number[][] */ - protected getContainerMapping(containerTpl: string): number[][] - { + protected getContainerMapping(containerTpl: string): number[][] { // Get template from db const containerTemplate = this.itemHelper.getItem(containerTpl)[1]; @@ -512,24 +490,22 @@ export class LocationLootGenerator containerTypeId: string, staticLootDist: Record, locationName: string, - ): number - { + ): number { // Create probability array to calcualte the total count of lootable items inside container const itemCountArray = new ProbabilityObjectArray(this.mathUtil, this.cloner); const countDistribution = staticLootDist[containerTypeId]?.itemcountDistribution; - if (!countDistribution) - { - this.logger.warning(this.localisationService.getText("location-unable_to_find_count_distribution_for_container", - { + if (!countDistribution) { + this.logger.warning( + this.localisationService.getText("location-unable_to_find_count_distribution_for_container", { containerId: containerTypeId, locationName: locationName, - })); + }), + ); return 0; } - for (const itemCountDistribution of countDistribution) - { + for (const itemCountDistribution of countDistribution) { // Add each count of items into array itemCountArray.push( new ProbabilityObject(itemCountDistribution.count, itemCountDistribution.relativeProbability), @@ -549,31 +525,28 @@ export class LocationLootGenerator protected getPossibleLootItemsForContainer( containerTypeId: string, staticLootDist: Record, - ): ProbabilityObjectArray - { + ): ProbabilityObjectArray { const seasonalEventActive = this.seasonalEventService.seasonalEventEnabled(); const seasonalItemTplBlacklist = this.seasonalEventService.getInactiveSeasonalEventItems(); const itemDistribution = new ProbabilityObjectArray(this.mathUtil, this.cloner); const itemContainerDistribution = staticLootDist[containerTypeId]?.itemDistribution; - if (!itemContainerDistribution) - { - this.logger.warning(this.localisationService.getText("location-missing_item_distribution_data", containerTypeId)); + if (!itemContainerDistribution) { + this.logger.warning( + this.localisationService.getText("location-missing_item_distribution_data", containerTypeId), + ); return itemDistribution; } - for (const icd of itemContainerDistribution) - { - if (!seasonalEventActive && seasonalItemTplBlacklist.includes(icd.tpl)) - { + for (const icd of itemContainerDistribution) { + if (!seasonalEventActive && seasonalItemTplBlacklist.includes(icd.tpl)) { // Skip seasonal event items if they're not enabled continue; } // Ensure no blacklisted lootable items are in pool - if (this.itemFilterService.isLootableItemBlacklisted(icd.tpl)) - { + if (this.itemFilterService.isLootableItemBlacklisted(icd.tpl)) { continue; } @@ -583,13 +556,11 @@ export class LocationLootGenerator return itemDistribution; } - protected getLooseLootMultiplerForLocation(location: string): number - { + protected getLooseLootMultiplerForLocation(location: string): number { return this.locationConfig.looseLootMultiplier[location]; } - protected getStaticLootMultiplerForLocation(location: string): number - { + protected getStaticLootMultiplerForLocation(location: string): number { return this.locationConfig.staticLootMultiplier[location]; } @@ -604,8 +575,7 @@ export class LocationLootGenerator dynamicLootDist: ILooseLoot, staticAmmoDist: Record, locationName: string, - ): SpawnpointTemplate[] - { + ): SpawnpointTemplate[] { const loot: SpawnpointTemplate[] = []; const dynamicForcedSpawnPoints: SpawnpointsForced[] = []; @@ -620,11 +590,11 @@ export class LocationLootGenerator // Draw from random distribution const desiredSpawnpointCount = Math.round( - this.getLooseLootMultiplerForLocation(locationName) - * this.randomUtil.getNormallyDistributedRandomNumber( - dynamicLootDist.spawnpointCount.mean, - dynamicLootDist.spawnpointCount.std, - ), + this.getLooseLootMultiplerForLocation(locationName) * + this.randomUtil.getNormallyDistributedRandomNumber( + dynamicLootDist.spawnpointCount.mean, + dynamicLootDist.spawnpointCount.std, + ), ); // Positions not in forced but have 100% chance to spawn @@ -633,24 +603,20 @@ export class LocationLootGenerator const blacklistedSpawnpoints = this.locationConfig.looseLootBlacklist[locationName]; const spawnpointArray = new ProbabilityObjectArray(this.mathUtil, this.cloner); - for (const spawnpoint of allDynamicSpawnpoints) - { + for (const spawnpoint of allDynamicSpawnpoints) { // Point is blacklsited, skip - if (blacklistedSpawnpoints?.includes(spawnpoint.template.Id)) - { + if (blacklistedSpawnpoints?.includes(spawnpoint.template.Id)) { this.logger.debug(`Ignoring loose loot location: ${spawnpoint.template.Id}`); continue; } // We've handled IsAlwaysSpawn above, so skip them - if (spawnpoint.template.IsAlwaysSpawn) - { + if (spawnpoint.template.IsAlwaysSpawn) { continue; } // 100%, add it to guaranteed - if (spawnpoint.probability === 1) - { + if (spawnpoint.probability === 1) { guaranteedLoosePoints.push(spawnpoint); continue; } @@ -664,11 +630,9 @@ export class LocationLootGenerator const randomSpawnpointCount = desiredSpawnpointCount - chosenSpawnpoints.length; // Only draw random spawn points if needed - if (randomSpawnpointCount > 0 && spawnpointArray.length > 0) - { + if (randomSpawnpointCount > 0 && spawnpointArray.length > 0) { // Add randomly chosen spawn points - for (const si of spawnpointArray.draw(randomSpawnpointCount, false)) - { + for (const si of spawnpointArray.draw(randomSpawnpointCount, false)) { chosenSpawnpoints.push(spawnpointArray.data(si)!); } } @@ -680,8 +644,7 @@ export class LocationLootGenerator // Do we have enough items in pool to fulfill requirement const tooManySpawnPointsRequested = desiredSpawnpointCount - chosenSpawnpoints.length > 0; - if (tooManySpawnPointsRequested) - { + if (tooManySpawnPointsRequested) { this.logger.debug( this.localisationService.getText("location-spawn_point_count_requested_vs_found", { requested: desiredSpawnpointCount + guaranteedLoosePoints.length, @@ -694,11 +657,9 @@ export class LocationLootGenerator // Iterate over spawnpoints const seasonalEventActive = this.seasonalEventService.seasonalEventEnabled(); const seasonalItemTplBlacklist = this.seasonalEventService.getInactiveSeasonalEventItems(); - for (const spawnPoint of chosenSpawnpoints) - { + for (const spawnPoint of chosenSpawnpoints) { // Spawnpoint is invalid, skip it - if (!spawnPoint.template) - { + if (!spawnPoint.template) { this.logger.warning( this.localisationService.getText("location-missing_dynamic_template", spawnPoint.locationId), ); @@ -707,19 +668,19 @@ export class LocationLootGenerator } // Ensure no blacklisted lootable items are in pool - spawnPoint.template.Items = spawnPoint.template.Items - .filter((item) => !this.itemFilterService.isLootableItemBlacklisted(item._tpl)); + spawnPoint.template.Items = spawnPoint.template.Items.filter( + (item) => !this.itemFilterService.isLootableItemBlacklisted(item._tpl), + ); // Ensure no seasonal items are in pool if not in-season - if (!seasonalEventActive) - { - spawnPoint.template.Items = spawnPoint.template.Items - .filter((item) => !seasonalItemTplBlacklist.includes(item._tpl)); + if (!seasonalEventActive) { + spawnPoint.template.Items = spawnPoint.template.Items.filter( + (item) => !seasonalItemTplBlacklist.includes(item._tpl), + ); } // Spawn point has no items after filtering, skip - if (!spawnPoint.template.Items || spawnPoint.template.Items.length === 0) - { + if (!spawnPoint.template.Items || spawnPoint.template.Items.length === 0) { this.logger.warning( this.localisationService.getText("location-spawnpoint_missing_items", spawnPoint.template.Id), ); @@ -732,19 +693,18 @@ export class LocationLootGenerator // Construct container to hold above filtered items, letting us pick an item for the spot const itemArray = new ProbabilityObjectArray(this.mathUtil, this.cloner); - for (const itemDist of spawnPoint.itemDistribution) - { - if (!validItemIds.includes(itemDist.composedKey.key)) - { + for (const itemDist of spawnPoint.itemDistribution) { + if (!validItemIds.includes(itemDist.composedKey.key)) { continue; } itemArray.push(new ProbabilityObject(itemDist.composedKey.key, itemDist.relativeProbability)); } - if (itemArray.length === 0) - { - this.logger.warning(this.localisationService.getText("location-loot_pool_is_empty_skipping", spawnPoint.template.Id)); + if (itemArray.length === 0) { + this.logger.warning( + this.localisationService.getText("location-loot_pool_is_empty_skipping", spawnPoint.template.Id), + ); continue; } @@ -775,20 +735,16 @@ export class LocationLootGenerator lootLocationTemplates: SpawnpointTemplate[], forcedSpawnPoints: SpawnpointsForced[], locationName: string, - ): void - { + ): void { const lootToForceSingleAmountOnMap = this.locationConfig.forcedLootSingleSpawnById[locationName]; - if (lootToForceSingleAmountOnMap) - { + if (lootToForceSingleAmountOnMap) { // Process loot items defined as requiring only 1 spawn position as they appear in multiple positions on the map - for (const itemTpl of lootToForceSingleAmountOnMap) - { + for (const itemTpl of lootToForceSingleAmountOnMap) { // Get all spawn positions for item tpl in forced loot array const items = forcedSpawnPoints.filter( (forcedSpawnPoint) => forcedSpawnPoint.template.Items[0]._tpl === itemTpl, ); - if (!items || items.length === 0) - { + if (!items || items.length === 0) { this.logger.debug( `Unable to adjust loot item ${itemTpl} as it does not exist inside ${locationName} forced loot.`, ); @@ -800,20 +756,19 @@ export class LocationLootGenerator this.mathUtil, this.cloner, ); - for (const si of items) - { + for (const si of items) { // use locationId as template.Id is the same across all items spawnpointArray.push(new ProbabilityObject(si.locationId, si.probability, si)); } // Choose 1 out of all found spawn positions for spawn id and add to loot array - for (const spawnPointLocationId of spawnpointArray.draw(1, false)) - { + for (const spawnPointLocationId of spawnpointArray.draw(1, false)) { const itemToAdd = items.find((item) => item.locationId === spawnPointLocationId); const lootItem = itemToAdd?.template; - if (!lootItem) - { - this.logger.warning(`Item with spawn point id ${spawnPointLocationId} could not be found, skipping`); + if (!lootItem) { + this.logger.warning( + `Item with spawn point id ${spawnPointLocationId} could not be found, skipping`, + ); continue; } lootItem.Root = this.objectId.generate(); @@ -827,19 +782,16 @@ export class LocationLootGenerator const seasonalItemTplBlacklist = this.seasonalEventService.getInactiveSeasonalEventItems(); // Add remaining forced loot to array - for (const forcedLootLocation of forcedSpawnPoints) - { + for (const forcedLootLocation of forcedSpawnPoints) { const firstLootItemTpl = forcedLootLocation.template.Items[0]._tpl; // Skip spawn positions processed already - if (lootToForceSingleAmountOnMap?.includes(firstLootItemTpl)) - { + if (lootToForceSingleAmountOnMap?.includes(firstLootItemTpl)) { continue; } // Skip adding seasonal items when seasonal event is not active - if (!seasonalEventActive && seasonalItemTplBlacklist.includes(firstLootItemTpl)) - { + if (!seasonalEventActive && seasonalItemTplBlacklist.includes(firstLootItemTpl)) { continue; } @@ -853,12 +805,9 @@ export class LocationLootGenerator const existingLocation = lootLocationTemplates.some( (spawnPoint) => spawnPoint.Id === locationTemplateToAdd.Id, ); - if (!existingLocation) - { + if (!existingLocation) { lootLocationTemplates.push(locationTemplateToAdd); - } - else - { + } else { this.logger.debug( `Attempted to add a forced loot location with Id: ${locationTemplateToAdd.Id} to map ${locationName} that already has that id in use, skipping`, ); @@ -877,12 +826,10 @@ export class LocationLootGenerator chosenComposedKey: string, spawnPoint: Spawnpoint, staticAmmoDist: Record, - ): IContainerItem - { + ): IContainerItem { const chosenItem = spawnPoint.template.Items.find((item) => item._id === chosenComposedKey); const chosenTpl = chosenItem?._tpl; - if (!chosenTpl) - { + if (!chosenTpl) { throw new Error(`Item for tpl ${chosenComposedKey} was not found in the spawn point`); } const itemTemplate = this.itemHelper.getItem(chosenTpl)[1]; @@ -891,10 +838,9 @@ export class LocationLootGenerator const itemWithMods: Item[] = []; // Money/Ammo - don't rely on items in spawnPoint.template.Items so we can randomise it ourselves - if (this.itemHelper.isOfBaseclasses(chosenTpl, [BaseClasses.MONEY, BaseClasses.AMMO])) - { - const stackCount - = itemTemplate._props.StackMaxSize === 1 + if (this.itemHelper.isOfBaseclasses(chosenTpl, [BaseClasses.MONEY, BaseClasses.AMMO])) { + const stackCount = + itemTemplate._props.StackMaxSize === 1 ? 1 : this.randomUtil.getInt(itemTemplate._props.StackMinRandom!, itemTemplate._props.StackMaxRandom!); @@ -903,21 +849,16 @@ export class LocationLootGenerator _tpl: chosenTpl, upd: { StackObjectsCount: stackCount }, }); - } - else if (this.itemHelper.isOfBaseclass(chosenTpl, BaseClasses.AMMO_BOX)) - { + } else if (this.itemHelper.isOfBaseclass(chosenTpl, BaseClasses.AMMO_BOX)) { // Fill with cartridges const ammoBoxItem: Item[] = [{ _id: this.objectId.generate(), _tpl: chosenTpl }]; this.itemHelper.addCartridgesToAmmoBox(ammoBoxItem, itemTemplate); itemWithMods.push(...ammoBoxItem); - } - else if (this.itemHelper.isOfBaseclass(chosenTpl, BaseClasses.MAGAZINE)) - { + } else if (this.itemHelper.isOfBaseclass(chosenTpl, BaseClasses.MAGAZINE)) { // Create array with just magazine const magazineItem: Item[] = [{ _id: this.objectId.generate(), _tpl: chosenTpl }]; - if (this.randomUtil.getChance100(this.locationConfig.staticMagazineLootHasAmmoChancePercent)) - { + if (this.randomUtil.getChance100(this.locationConfig.staticMagazineLootHasAmmoChancePercent)) { // Add randomised amount of cartridges this.itemHelper.fillMagazineWithRandomCartridge( magazineItem, @@ -929,9 +870,7 @@ export class LocationLootGenerator } itemWithMods.push(...magazineItem); - } - else - { + } else { // Also used by armors to get child mods // Get item + children and add into array we return const itemWithChildren = this.itemHelper.findAndReturnChildrenAsItems( @@ -956,8 +895,7 @@ export class LocationLootGenerator * @param itemWithChildren Item with mods to update * @param newId new id to add on chidren of base item */ - protected reparentItemAndChildren(itemWithChildren: Item[], newId = this.objectId.generate()): void - { + protected reparentItemAndChildren(itemWithChildren: Item[], newId = this.objectId.generate()): void { // original id on base item const oldId = itemWithChildren[0]._id; @@ -965,10 +903,8 @@ export class LocationLootGenerator itemWithChildren[0]._id = newId; // Update all parentIds of items attached to base item to use new id - for (const item of itemWithChildren) - { - if (item.parentId === oldId) - { + for (const item of itemWithChildren) { + if (item.parentId === oldId) { item.parentId = newId; } } @@ -980,10 +916,8 @@ export class LocationLootGenerator * @param chosenTpl Tpl we want to get item with * @returns Item object */ - protected getItemInArray(items: Item[], chosenTpl: string): Item | undefined - { - if (this.itemHelper.isOfBaseclass(chosenTpl, BaseClasses.WEAPON)) - { + protected getItemInArray(items: Item[], chosenTpl: string): Item | undefined { + if (this.itemHelper.isOfBaseclass(chosenTpl, BaseClasses.WEAPON)) { return items.find((v) => v._tpl === chosenTpl && v.parentId === undefined); } @@ -995,8 +929,7 @@ export class LocationLootGenerator chosenTpl: string, staticAmmoDist: Record, parentId?: string, - ): IContainerItem - { + ): IContainerItem { const itemTemplate = this.itemHelper.getItem(chosenTpl)[1]; let width = itemTemplate._props.Width!; let height = itemTemplate._props.Height!; @@ -1004,37 +937,30 @@ export class LocationLootGenerator const rootItem = items[0]; // Use passed in parentId as override for new item - if (parentId) - { + if (parentId) { rootItem.parentId = parentId; } if ( - this.itemHelper.isOfBaseclass(chosenTpl, BaseClasses.MONEY) - || this.itemHelper.isOfBaseclass(chosenTpl, BaseClasses.AMMO) - ) - { + this.itemHelper.isOfBaseclass(chosenTpl, BaseClasses.MONEY) || + this.itemHelper.isOfBaseclass(chosenTpl, BaseClasses.AMMO) + ) { // Edge case - some ammos e.g. flares or M406 grenades shouldn't be stacked - const stackCount - = itemTemplate._props.StackMaxSize === 1 + const stackCount = + itemTemplate._props.StackMaxSize === 1 ? 1 : this.randomUtil.getInt(itemTemplate._props.StackMinRandom!, itemTemplate._props.StackMaxRandom!); rootItem.upd = { StackObjectsCount: stackCount }; } // No spawn point, use default template - else if (this.itemHelper.isOfBaseclass(chosenTpl, BaseClasses.WEAPON)) - { + else if (this.itemHelper.isOfBaseclass(chosenTpl, BaseClasses.WEAPON)) { let children: Item[] = []; const defaultPreset = this.cloner.clone(this.presetHelper.getDefaultPreset(chosenTpl)); - if (defaultPreset?._items) - { - try - { + if (defaultPreset?._items) { + try { children = this.itemHelper.reparentItemAndChildren(defaultPreset._items[0], defaultPreset._items); - } - catch (error) - { + } catch (error) { // this item already broke it once without being reproducible tpl = "5839a40f24597726f856b511"; AKS-74UB Default // 5ea03f7400685063ec28bfa8 // ppsh default // 5ba26383d4351e00334c93d9 //mp7_devgru @@ -1049,16 +975,13 @@ export class LocationLootGenerator throw error; } - } - else - { + } else { // RSP30 (62178be9d0050232da3485d9/624c0b3340357b5f566e8766/6217726288ed9f0845317459) doesnt have any default presets and kills this code below as it has no chidren to reparent this.logger.debug(`createItem() No preset found for weapon: ${chosenTpl}`); } const rootItem = items[0]; - if (!rootItem) - { + if (!rootItem) { this.logger.error( this.localisationService.getText("location-missing_root_item", { tpl: chosenTpl, @@ -1069,15 +992,11 @@ export class LocationLootGenerator throw new Error(this.localisationService.getText("location-critical_error_see_log")); } - try - { - if (children?.length > 0) - { + try { + if (children?.length > 0) { items = this.itemHelper.reparentItemAndChildren(rootItem, children); } - } - catch (error) - { + } catch (error) { this.logger.error( this.localisationService.getText("location-unable_to_reparent_item", { tpl: chosenTpl, @@ -1094,8 +1013,7 @@ export class LocationLootGenerator // BotGenerator const magazine = items.filter((item) => item.slotId === "mod_magazine")[0]; // some weapon presets come without magazine; only fill the mag if it exists - if (magazine) - { + if (magazine) { const magTemplate = this.itemHelper.getItem(magazine._tpl)[1]; const weaponTemplate = this.itemHelper.getItem(chosenTpl)[1]; @@ -1121,14 +1039,10 @@ export class LocationLootGenerator height = size.height; } // No spawnpoint to fall back on, generate manually - else if (this.itemHelper.isOfBaseclass(chosenTpl, BaseClasses.AMMO_BOX)) - { + else if (this.itemHelper.isOfBaseclass(chosenTpl, BaseClasses.AMMO_BOX)) { this.itemHelper.addCartridgesToAmmoBox(items, itemTemplate); - } - else if (this.itemHelper.isOfBaseclass(chosenTpl, BaseClasses.MAGAZINE)) - { - if (this.randomUtil.getChance100(this.locationConfig.magazineLootHasAmmoChancePercent)) - { + } else if (this.itemHelper.isOfBaseclass(chosenTpl, BaseClasses.MAGAZINE)) { + if (this.randomUtil.getChance100(this.locationConfig.magazineLootHasAmmoChancePercent)) { // Create array with just magazine const magazineWithCartridges = [rootItem]; this.itemHelper.fillMagazineWithRandomCartridge( @@ -1142,24 +1056,18 @@ export class LocationLootGenerator // Replace existing magazine with above array items.splice(items.indexOf(rootItem), 1, ...magazineWithCartridges); } - } - else if (this.itemHelper.armorItemCanHoldMods(chosenTpl)) - { + } else if (this.itemHelper.armorItemCanHoldMods(chosenTpl)) { const defaultPreset = this.presetHelper.getDefaultPreset(chosenTpl); - if (defaultPreset) - { + if (defaultPreset) { const presetAndMods: Item[] = this.itemHelper.replaceIDs(defaultPreset._items); this.itemHelper.remapRootItemId(presetAndMods); // Use original items parentId otherwise item doesnt get added to container correctly presetAndMods[0].parentId = rootItem.parentId; items = presetAndMods; - } - else - { + } else { // We make base item above, at start of function, no need to do it here - if ((itemTemplate._props.Slots?.length ?? 0) > 0) - { + if ((itemTemplate._props.Slots?.length ?? 0) > 0) { items = this.itemHelper.addChildSlotItems( items, itemTemplate, diff --git a/project/src/generators/LootGenerator.ts b/project/src/generators/LootGenerator.ts index 02a77bc1..761dea1a 100644 --- a/project/src/generators/LootGenerator.ts +++ b/project/src/generators/LootGenerator.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { InventoryHelper } from "@spt/helpers/InventoryHelper"; import { ItemHelper } from "@spt/helpers/ItemHelper"; import { PresetHelper } from "@spt/helpers/PresetHelper"; @@ -16,12 +15,12 @@ import { LocalisationService } from "@spt/services/LocalisationService"; import { RagfairLinkedItemService } from "@spt/services/RagfairLinkedItemService"; import { HashUtil } from "@spt/utils/HashUtil"; import { RandomUtil } from "@spt/utils/RandomUtil"; +import { inject, injectable } from "tsyringe"; -type ItemLimit = { current: number, max: number }; +type ItemLimit = { current: number; max: number }; @injectable() -export class LootGenerator -{ +export class LootGenerator { constructor( @inject("PrimaryLogger") protected logger: ILogger, @inject("HashUtil") protected hashUtil: HashUtil, @@ -34,16 +33,14 @@ export class LootGenerator @inject("LocalisationService") protected localisationService: LocalisationService, @inject("RagfairLinkedItemService") protected ragfairLinkedItemService: RagfairLinkedItemService, @inject("ItemFilterService") protected itemFilterService: ItemFilterService, - ) - {} + ) {} /** * Generate a list of items based on configuration options parameter * @param options parameters to adjust how loot is generated * @returns An array of loot items */ - public createRandomLoot(options: LootRequest): Item[] - { + public createRandomLoot(options: LootRequest): Item[] { const result: Item[] = []; const itemTypeCounts = this.initItemLimitCounter(options.itemLimits); @@ -53,16 +50,13 @@ export class LootGenerator ...options.itemBlacklist, ]); - if (options.useRewarditemBlacklist) - { + if (options.useRewarditemBlacklist) { const itemsToAdd = this.itemFilterService.getItemRewardBlacklist(); itemBlacklist = new Set([...itemBlacklist, ...itemsToAdd]); } - if (!options.allowBossItems) - { - for (const bossItem of this.itemFilterService.getBossItems()) - { + if (!options.allowBossItems) { + for (const bossItem of this.itemFilterService.getBossItems()) { itemBlacklist.add(bossItem); } } @@ -72,15 +66,13 @@ export class LootGenerator options.weaponCrateCount.min, options.weaponCrateCount.max, ); - if (sealedWeaponCrateCount > 0) - { + if (sealedWeaponCrateCount > 0) { // Get list of all sealed containers from db - they're all the same, just for flavor const sealedWeaponContainerPool = Object.values(itemsDb).filter((item) => item._name.includes("event_container_airdrop"), ); - for (let index = 0; index < sealedWeaponCrateCount; index++) - { + for (let index = 0; index < sealedWeaponCrateCount; index++) { // Choose one at random + add to results array const chosenSealedContainer = this.randomUtil.getArrayValue(sealedWeaponContainerPool); result.push({ @@ -97,20 +89,17 @@ export class LootGenerator // Get items from items.json that have a type of item + not in global blacklist + basetype is in whitelist const items = Object.entries(itemsDb).filter( (item) => - !itemBlacklist.has(item[1]._id) - && item[1]._type.toLowerCase() === "item" - && !item[1]._props.QuestItem - && options.itemTypeWhitelist.includes(item[1]._parent), + !itemBlacklist.has(item[1]._id) && + item[1]._type.toLowerCase() === "item" && + !item[1]._props.QuestItem && + options.itemTypeWhitelist.includes(item[1]._parent), ); // Pool has items we could add as loot, proceed - if (items.length > 0) - { + if (items.length > 0) { const randomisedItemCount = this.randomUtil.getInt(options.itemCount.min, options.itemCount.max); - for (let index = 0; index < randomisedItemCount; index++) - { - if (!this.findAndAddRandomItemToLoot(items, itemTypeCounts, options, result)) - { + for (let index = 0; index < randomisedItemCount; index++) { + if (!this.findAndAddRandomItemToLoot(items, itemTypeCounts, options, result)) { // Failed to add, reduce index so we get another attempt index--; } @@ -125,16 +114,13 @@ export class LootGenerator options.weaponPresetCount.min, options.weaponPresetCount.max, ); - if (randomisedWeaponPresetCount > 0) - { + if (randomisedWeaponPresetCount > 0) { const weaponDefaultPresets = globalDefaultPresets.filter((preset) => this.itemHelper.isOfBaseclass(preset._encyclopedia, BaseClasses.WEAPON), ); - if (weaponDefaultPresets.length > 0) - { - for (let index = 0; index < randomisedWeaponPresetCount; index++) - { + if (weaponDefaultPresets.length > 0) { + for (let index = 0; index < randomisedWeaponPresetCount; index++) { if ( !this.findAndAddRandomPresetToLoot( weaponDefaultPresets, @@ -142,8 +128,7 @@ export class LootGenerator itemBlacklistArray, result, ) - ) - { + ) { // Failed to add, reduce index so we get another attempt index--; } @@ -156,8 +141,7 @@ export class LootGenerator options.armorPresetCount.min, options.armorPresetCount.max, ); - if (randomisedArmorPresetCount > 0) - { + if (randomisedArmorPresetCount > 0) { const armorDefaultPresets = globalDefaultPresets.filter((preset) => this.itemHelper.armorItemCanHoldMods(preset._encyclopedia), ); @@ -166,10 +150,8 @@ export class LootGenerator ); // Add some armors to rewards - if (levelFilteredArmorPresets.length > 0) - { - for (let index = 0; index < randomisedArmorPresetCount; index++) - { + if (levelFilteredArmorPresets.length > 0) { + for (let index = 0; index < randomisedArmorPresetCount; index++) { if ( !this.findAndAddRandomPresetToLoot( levelFilteredArmorPresets, @@ -177,8 +159,7 @@ export class LootGenerator itemBlacklistArray, result, ) - ) - { + ) { // Failed to add, reduce index so we get another attempt index--; } @@ -195,14 +176,11 @@ export class LootGenerator * @param options Loot request options - armor level etc * @returns True if item has desired armor level */ - protected isArmorOfDesiredProtectionLevel(armor: IPreset, options: LootRequest): boolean - { + protected isArmorOfDesiredProtectionLevel(armor: IPreset, options: LootRequest): boolean { const relevantSlots = ["front_plate", "helmet_top", "soft_armor_front"]; - for (const slotId of relevantSlots) - { + for (const slotId of relevantSlots) { const armorItem = armor._items.find((item) => item?.slotId?.toLowerCase() === slotId); - if (!armorItem) - { + if (!armorItem) { continue; } @@ -220,11 +198,9 @@ export class LootGenerator * @param limits limits as defined in config * @returns record, key: item tplId, value: current/max item count allowed */ - protected initItemLimitCounter(limits: Record): Record - { + protected initItemLimitCounter(limits: Record): Record { const itemTypeCounts: Record = {}; - for (const itemTypeId in limits) - { + for (const itemTypeId in limits) { itemTypeCounts[itemTypeId] = { current: 0, max: limits[itemTypeId] }; } @@ -241,22 +217,19 @@ export class LootGenerator */ protected findAndAddRandomItemToLoot( items: [string, ITemplateItem][], - itemTypeCounts: Record, + itemTypeCounts: Record, options: LootRequest, result: Item[], - ): boolean - { + ): boolean { const randomItem = this.randomUtil.getArrayValue(items)[1]; const itemLimitCount = itemTypeCounts[randomItem._parent]; - if (itemLimitCount && itemLimitCount.current > itemLimitCount.max) - { + if (itemLimitCount && itemLimitCount.current > itemLimitCount.max) { return false; } // Skip armors as they need to come from presets - if (this.itemHelper.armorItemCanHoldMods(randomItem._id)) - { + if (this.itemHelper.armorItemCanHoldMods(randomItem._id)) { return false; } @@ -270,16 +243,14 @@ export class LootGenerator }; // Special case - handle items that need a stackcount > 1 - if (randomItem._props.StackMaxSize > 1) - { + if (randomItem._props.StackMaxSize > 1) { newLootItem.upd.StackObjectsCount = this.getRandomisedStackCount(randomItem, options); } newLootItem._tpl = randomItem._id; result.push(newLootItem); - if (itemLimitCount) - { + if (itemLimitCount) { // Increment item count as it's in limit array itemLimitCount.current++; } @@ -294,13 +265,11 @@ export class LootGenerator * @param options loot options * @returns stack count */ - protected getRandomisedStackCount(item: ITemplateItem, options: LootRequest): number - { + protected getRandomisedStackCount(item: ITemplateItem, options: LootRequest): number { let min = item._props.StackMinRandom; let max = item._props.StackMaxSize; - if (options.itemStackLimits[item._id]) - { + if (options.itemStackLimits[item._id]) { min = options.itemStackLimits[item._id].min; max = options.itemStackLimits[item._id].max; } @@ -318,23 +287,20 @@ export class LootGenerator */ protected findAndAddRandomPresetToLoot( presetPool: IPreset[], - itemTypeCounts: Record, + itemTypeCounts: Record, itemBlacklist: string[], result: Item[], - ): boolean - { + ): boolean { // Choose random preset and get details from item db using encyclopedia value (encyclopedia === tplId) const chosenPreset = this.randomUtil.getArrayValue(presetPool); - if (!chosenPreset) - { + if (!chosenPreset) { this.logger.warning("Unable to find random preset in given presets, skipping"); return false; } // No `_encyclopedia` property, not possible to reliably get root item tpl - if (!chosenPreset?._encyclopedia) - { + if (!chosenPreset?._encyclopedia) { this.logger.debug(`Preset with id: ${chosenPreset?._id} lacks encyclopedia property, skipping`); return false; @@ -342,22 +308,19 @@ export class LootGenerator // Get preset root item db details via its `_encyclopedia` property const itemDbDetails = this.itemHelper.getItem(chosenPreset._encyclopedia); - if (!itemDbDetails[0]) - { + if (!itemDbDetails[0]) { this.logger.debug(`Unable to find preset with tpl: ${chosenPreset._encyclopedia}, skipping`); return false; } // Skip preset if root item is blacklisted - if (itemBlacklist.includes(chosenPreset._items[0]._tpl)) - { + if (itemBlacklist.includes(chosenPreset._items[0]._tpl)) { return false; } // Some custom mod items lack a parent property - if (!itemDbDetails[1]._parent) - { + if (!itemDbDetails[1]._parent) { this.logger.error(this.localisationService.getText("loot-item_missing_parentid", itemDbDetails[1]?._name)); return false; @@ -365,21 +328,18 @@ export class LootGenerator // Check chosen preset hasn't exceeded spawn limit const itemLimitCount = itemTypeCounts[itemDbDetails[1]._parent]; - if (itemLimitCount && itemLimitCount.current > itemLimitCount.max) - { + if (itemLimitCount && itemLimitCount.current > itemLimitCount.max) { return false; } const presetAndMods: Item[] = this.itemHelper.replaceIDs(chosenPreset._items); this.itemHelper.remapRootItemId(presetAndMods); // Add chosen preset tpl to result array - presetAndMods.forEach((item) => - { + presetAndMods.forEach((item) => { result.push(item); }); - if (itemLimitCount) - { + if (itemLimitCount) { // Increment item count as item has been chosen and its inside itemLimitCount dictionary itemLimitCount.current++; } @@ -393,8 +353,7 @@ export class LootGenerator * @param containerSettings sealed weapon container settings * @returns Array of item with children arrays */ - public getSealedWeaponCaseLoot(containerSettings: ISealedAirdropContainerSettings): Item[][] - { + public getSealedWeaponCaseLoot(containerSettings: ISealedAirdropContainerSettings): Item[][] { const itemsToReturn: Item[][] = []; // Choose a weapon to give to the player (weighted) @@ -404,8 +363,7 @@ export class LootGenerator // Get itemDb details of weapon const weaponDetailsDb = this.itemHelper.getItem(chosenWeaponTpl); - if (!weaponDetailsDb[0]) - { + if (!weaponDetailsDb[0]) { this.logger.error( this.localisationService.getText("loot-non_item_picked_as_sealed_weapon_crate_reward", chosenWeaponTpl), ); @@ -419,9 +377,10 @@ export class LootGenerator : this.randomUtil.getArrayValue(this.presetHelper.getPresets(chosenWeaponTpl)); // No default preset found for weapon, choose a random one - if (!chosenWeaponPreset) - { - this.logger.warning(this.localisationService.getText("loot-default_preset_not_found_using_random", chosenWeaponTpl)); + if (!chosenWeaponPreset) { + this.logger.warning( + this.localisationService.getText("loot-default_preset_not_found_using_random", chosenWeaponTpl), + ); chosenWeaponPreset = this.randomUtil.getArrayValue(this.presetHelper.getPresets(chosenWeaponTpl)); } @@ -453,26 +412,21 @@ export class LootGenerator protected getSealedContainerNonWeaponModRewards( containerSettings: ISealedAirdropContainerSettings, weaponDetailsDb: ITemplateItem, - ): Item[][] - { + ): Item[][] { const rewards: Item[][] = []; - for (const rewardTypeId in containerSettings.rewardTypeLimits) - { + for (const rewardTypeId in containerSettings.rewardTypeLimits) { const settings = containerSettings.rewardTypeLimits[rewardTypeId]; const rewardCount = this.randomUtil.getInt(settings.min, settings.max); - if (rewardCount === 0) - { + if (rewardCount === 0) { continue; } // Edge case - ammo boxes - if (rewardTypeId === BaseClasses.AMMO_BOX) - { + if (rewardTypeId === BaseClasses.AMMO_BOX) { // Get ammoboxes from db - const ammoBoxesDetails = containerSettings.ammoBoxWhitelist.map((tpl) => - { + const ammoBoxesDetails = containerSettings.ammoBoxWhitelist.map((tpl) => { const itemDetails = this.itemHelper.getItem(tpl); return itemDetails[1]; }); @@ -480,15 +434,13 @@ export class LootGenerator // Need to find boxes that matches weapons caliber const weaponCaliber = weaponDetailsDb._props.ammoCaliber; const ammoBoxesMatchingCaliber = ammoBoxesDetails.filter((x) => x._props.ammoCaliber === weaponCaliber); - if (ammoBoxesMatchingCaliber.length === 0) - { + if (ammoBoxesMatchingCaliber.length === 0) { this.logger.debug(`No ammo box with caliber ${weaponCaliber} found, skipping`); continue; } - for (let index = 0; index < rewardCount; index++) - { + for (let index = 0; index < rewardCount; index++) { const chosenAmmoBox = this.randomUtil.getArrayValue(ammoBoxesMatchingCaliber); const ammoBoxItem: Item[] = [{ _id: this.hashUtil.generate(), _tpl: chosenAmmoBox._id }]; this.itemHelper.addCartridgesToAmmoBox(ammoBoxItem, chosenAmmoBox); @@ -501,22 +453,20 @@ export class LootGenerator // Get all items of the desired type + not quest items + not globally blacklisted const rewardItemPool = Object.values(this.databaseService.getItems()).filter( (item) => - item._parent === rewardTypeId - && item._type.toLowerCase() === "item" - && !this.itemFilterService.isItemBlacklisted(item._id) - && !(containerSettings.allowBossItems || this.itemFilterService.isBossItem(item._id)) - && !item._props.QuestItem, + item._parent === rewardTypeId && + item._type.toLowerCase() === "item" && + !this.itemFilterService.isItemBlacklisted(item._id) && + !(containerSettings.allowBossItems || this.itemFilterService.isBossItem(item._id)) && + !item._props.QuestItem, ); - if (rewardItemPool.length === 0) - { + if (rewardItemPool.length === 0) { this.logger.debug(`No items with base type of ${rewardTypeId} found, skipping`); continue; } - for (let index = 0; index < rewardCount; index++) - { + for (let index = 0; index < rewardCount; index++) { // Choose a random item from pool const chosenRewardItem = this.randomUtil.getArrayValue(rewardItemPool); const rewardItem: Item[] = [{ _id: this.hashUtil.generate(), _tpl: chosenRewardItem._id }]; @@ -539,17 +489,14 @@ export class LootGenerator containerSettings: ISealedAirdropContainerSettings, linkedItemsToWeapon: ITemplateItem[], chosenWeaponPreset: IPreset, - ): Item[][] - { + ): Item[][] { const modRewards: Item[][] = []; - for (const rewardTypeId in containerSettings.weaponModRewardLimits) - { + for (const rewardTypeId in containerSettings.weaponModRewardLimits) { const settings = containerSettings.weaponModRewardLimits[rewardTypeId]; const rewardCount = this.randomUtil.getInt(settings.min, settings.max); // Nothing to add, skip reward type - if (rewardCount === 0) - { + if (rewardCount === 0) { continue; } @@ -557,8 +504,7 @@ export class LootGenerator const relatedItems = linkedItemsToWeapon?.filter( (item) => item._parent === rewardTypeId && !this.itemFilterService.isItemBlacklisted(item._id), ); - if (!relatedItems || relatedItems.length === 0) - { + if (!relatedItems || relatedItems.length === 0) { this.logger.debug( `No items found to fulfil reward type: ${rewardTypeId} for weapon: ${chosenWeaponPreset._name}, skipping type`, ); @@ -566,8 +512,7 @@ export class LootGenerator } // Find a random item of the desired type and add as reward - for (let index = 0; index < rewardCount; index++) - { + for (let index = 0; index < rewardCount; index++) { const chosenItem = this.randomUtil.drawRandomFromList(relatedItems); const item: Item[] = [{ _id: this.hashUtil.generate(), _tpl: chosenItem[0]._id }]; @@ -583,13 +528,11 @@ export class LootGenerator * @param rewardContainerDetails * @returns Array of item with children arrays */ - public getRandomLootContainerLoot(rewardContainerDetails: RewardDetails): Item[][] - { + public getRandomLootContainerLoot(rewardContainerDetails: RewardDetails): Item[][] { const itemsToReturn: Item[][] = []; // Get random items and add to newItemRequest - for (let index = 0; index < rewardContainerDetails.rewardCount; index++) - { + for (let index = 0; index < rewardContainerDetails.rewardCount; index++) { // Pick random reward from pool, add to request object const chosenRewardItemTpl = this.weightedRandomHelper.getWeightedValue( rewardContainerDetails.rewardTplPool, diff --git a/project/src/generators/PMCLootGenerator.ts b/project/src/generators/PMCLootGenerator.ts index fd5031ad..add372f1 100644 --- a/project/src/generators/PMCLootGenerator.ts +++ b/project/src/generators/PMCLootGenerator.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { ItemHelper } from "@spt/helpers/ItemHelper"; import { WeightedRandomHelper } from "@spt/helpers/WeightedRandomHelper"; import { ITemplateItem } from "@spt/models/eft/common/tables/ITemplateItem"; @@ -10,14 +9,14 @@ import { DatabaseService } from "@spt/services/DatabaseService"; import { ItemFilterService } from "@spt/services/ItemFilterService"; import { RagfairPriceService } from "@spt/services/RagfairPriceService"; import { SeasonalEventService } from "@spt/services/SeasonalEventService"; +import { inject, injectable } from "tsyringe"; /** * Handle the generation of dynamic PMC loot in pockets and backpacks * and the removal of blacklisted items */ @injectable() -export class PMCLootGenerator -{ +export class PMCLootGenerator { protected pocketLootPool: Record = {}; protected vestLootPool: Record = {}; protected backpackLootPool: Record = {}; @@ -31,8 +30,7 @@ export class PMCLootGenerator @inject("RagfairPriceService") protected ragfairPriceService: RagfairPriceService, @inject("SeasonalEventService") protected seasonalEventService: SeasonalEventService, @inject("WeightedRandomHelper") protected weightedRandomHelper: WeightedRandomHelper, - ) - { + ) { this.pmcConfig = this.configServer.getConfig(ConfigTypes.PMC); } @@ -40,15 +38,12 @@ export class PMCLootGenerator * Create an array of loot items a PMC can have in their pockets * @returns string array of tpls */ - public generatePMCPocketLootPool(botRole: string): Record - { + public generatePMCPocketLootPool(botRole: string): Record { // Hydrate loot dictionary if empty - if (Object.keys(this.pocketLootPool).length === 0) - { + if (Object.keys(this.pocketLootPool).length === 0) { const items = this.databaseService.getItems(); - const pmcPriceOverrides - = this.databaseService.getBots().types[botRole === "pmcBEAR" ? "bear" : "usec"].inventory.items - .Pockets; + const pmcPriceOverrides = + this.databaseService.getBots().types[botRole === "pmcBEAR" ? "bear" : "usec"].inventory.items.Pockets; const allowedItemTypes = this.pmcConfig.pocketLoot.whitelist; const pmcItemBlacklist = this.pmcConfig.pocketLoot.blacklist; @@ -59,22 +54,18 @@ export class PMCLootGenerator const itemsToAdd = Object.values(items).filter( (item) => - allowedItemTypes.includes(item._parent) - && this.itemHelper.isValidItem(item._id) - && !pmcItemBlacklist.includes(item._id) - && !itemBlacklist.includes(item._id) - && this.itemFitsInto1By2Slot(item), + allowedItemTypes.includes(item._parent) && + this.itemHelper.isValidItem(item._id) && + !pmcItemBlacklist.includes(item._id) && + !itemBlacklist.includes(item._id) && + this.itemFitsInto1By2Slot(item), ); - for (const itemToAdd of itemsToAdd) - { + for (const itemToAdd of itemsToAdd) { // If pmc has override, use that. Otherwise use flea price - if (pmcPriceOverrides[itemToAdd._id]) - { + if (pmcPriceOverrides[itemToAdd._id]) { this.pocketLootPool[itemToAdd._id] = pmcPriceOverrides[itemToAdd._id]; - } - else - { + } else { // Set price of item as its weight const price = this.ragfairPriceService.getDynamicItemPrice(itemToAdd._id, Money.ROUBLES); this.pocketLootPool[itemToAdd._id] = price; @@ -82,8 +73,7 @@ export class PMCLootGenerator } const highestPrice = Math.max(...Object.values(this.backpackLootPool)); - for (const key of Object.keys(this.pocketLootPool)) - { + for (const key of Object.keys(this.pocketLootPool)) { // Invert price so cheapest has a larger weight // Times by highest price so most expensive item has weight of 1 this.pocketLootPool[key] = Math.round((1 / this.pocketLootPool[key]) * highestPrice); @@ -99,14 +89,12 @@ export class PMCLootGenerator * Create an array of loot items a PMC can have in their vests * @returns string array of tpls */ - public generatePMCVestLootPool(botRole: string): Record - { + public generatePMCVestLootPool(botRole: string): Record { // Hydrate loot dictionary if empty - if (Object.keys(this.vestLootPool).length === 0) - { + if (Object.keys(this.vestLootPool).length === 0) { const items = this.databaseService.getItems(); - const pmcPriceOverrides - = this.databaseService.getBots().types[botRole === "pmcBEAR" ? "bear" : "usec"].inventory.items + const pmcPriceOverrides = + this.databaseService.getBots().types[botRole === "pmcBEAR" ? "bear" : "usec"].inventory.items .TacticalVest; const allowedItemTypes = this.pmcConfig.vestLoot.whitelist; @@ -118,22 +106,18 @@ export class PMCLootGenerator const itemsToAdd = Object.values(items).filter( (item) => - allowedItemTypes.includes(item._parent) - && this.itemHelper.isValidItem(item._id) - && !pmcItemBlacklist.includes(item._id) - && !itemBlacklist.includes(item._id) - && this.itemFitsInto2By2Slot(item), + allowedItemTypes.includes(item._parent) && + this.itemHelper.isValidItem(item._id) && + !pmcItemBlacklist.includes(item._id) && + !itemBlacklist.includes(item._id) && + this.itemFitsInto2By2Slot(item), ); - for (const itemToAdd of itemsToAdd) - { + for (const itemToAdd of itemsToAdd) { // If pmc has override, use that. Otherwise use flea price - if (pmcPriceOverrides[itemToAdd._id]) - { + if (pmcPriceOverrides[itemToAdd._id]) { this.vestLootPool[itemToAdd._id] = pmcPriceOverrides[itemToAdd._id]; - } - else - { + } else { // Set price of item as its weight const price = this.ragfairPriceService.getDynamicItemPrice(itemToAdd._id, Money.ROUBLES); this.vestLootPool[itemToAdd._id] = price; @@ -141,8 +125,7 @@ export class PMCLootGenerator } const highestPrice = Math.max(...Object.values(this.backpackLootPool)); - for (const key of Object.keys(this.vestLootPool)) - { + for (const key of Object.keys(this.vestLootPool)) { // Invert price so cheapest has a larger weight // Times by highest price so most expensive item has weight of 1 this.vestLootPool[key] = Math.round((1 / this.vestLootPool[key]) * highestPrice); @@ -160,8 +143,7 @@ export class PMCLootGenerator * @param item Item to check size of * @returns true if it fits */ - protected itemFitsInto2By2Slot(item: ITemplateItem): boolean - { + protected itemFitsInto2By2Slot(item: ITemplateItem): boolean { return item._props.Width <= 2 && item._props.Height <= 2; } @@ -171,10 +153,8 @@ export class PMCLootGenerator * @param item Item to check size of * @returns true if it fits */ - protected itemFitsInto1By2Slot(item: ITemplateItem): boolean - { - switch (`${item._props.Width}x${item._props.Height}`) - { + protected itemFitsInto1By2Slot(item: ITemplateItem): boolean { + switch (`${item._props.Width}x${item._props.Height}`) { case "1x1": case "1x2": case "2x1": @@ -189,15 +169,12 @@ export class PMCLootGenerator * Create an array of loot items a PMC can have in their backpack * @returns string array of tpls */ - public generatePMCBackpackLootPool(botRole: string): Record - { + public generatePMCBackpackLootPool(botRole: string): Record { // Hydrate loot dictionary if empty - if (Object.keys(this.backpackLootPool).length === 0) - { + if (Object.keys(this.backpackLootPool).length === 0) { const items = this.databaseService.getItems(); - const pmcPriceOverrides - = this.databaseService.getBots().types[botRole === "pmcBEAR" ? "bear" : "usec"].inventory.items - .Backpack; + const pmcPriceOverrides = + this.databaseService.getBots().types[botRole === "pmcBEAR" ? "bear" : "usec"].inventory.items.Backpack; const allowedItemTypes = this.pmcConfig.backpackLoot.whitelist; const pmcItemBlacklist = this.pmcConfig.backpackLoot.blacklist; @@ -208,21 +185,17 @@ export class PMCLootGenerator const itemsToAdd = Object.values(items).filter( (item) => - allowedItemTypes.includes(item._parent) - && this.itemHelper.isValidItem(item._id) - && !pmcItemBlacklist.includes(item._id) - && !itemBlacklist.includes(item._id), + allowedItemTypes.includes(item._parent) && + this.itemHelper.isValidItem(item._id) && + !pmcItemBlacklist.includes(item._id) && + !itemBlacklist.includes(item._id), ); - for (const itemToAdd of itemsToAdd) - { + for (const itemToAdd of itemsToAdd) { // If pmc has price override, use that. Otherwise use flea price - if (pmcPriceOverrides[itemToAdd._id]) - { + if (pmcPriceOverrides[itemToAdd._id]) { this.backpackLootPool[itemToAdd._id] = pmcPriceOverrides[itemToAdd._id]; - } - else - { + } else { // Set price of item as its weight const price = this.ragfairPriceService.getDynamicItemPrice(itemToAdd._id, Money.ROUBLES); this.backpackLootPool[itemToAdd._id] = price; @@ -230,8 +203,7 @@ export class PMCLootGenerator } const highestPrice = Math.max(...Object.values(this.backpackLootPool)); - for (const key of Object.keys(this.backpackLootPool)) - { + for (const key of Object.keys(this.backpackLootPool)) { // Invert price so cheapest has a larger weight // Times by highest price so most expensive item has weight of 1 this.backpackLootPool[key] = Math.round((1 / this.backpackLootPool[key]) * highestPrice); diff --git a/project/src/generators/PlayerScavGenerator.ts b/project/src/generators/PlayerScavGenerator.ts index c9208c5c..41307c5e 100644 --- a/project/src/generators/PlayerScavGenerator.ts +++ b/project/src/generators/PlayerScavGenerator.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { BotGenerator } from "@spt/generators/BotGenerator"; import { BotGeneratorHelper } from "@spt/helpers/BotGeneratorHelper"; import { BotHelper } from "@spt/helpers/BotHelper"; @@ -22,13 +21,13 @@ 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 { ICloner } from "@spt/utils/cloners/ICloner"; import { HashUtil } from "@spt/utils/HashUtil"; import { RandomUtil } from "@spt/utils/RandomUtil"; +import { ICloner } from "@spt/utils/cloners/ICloner"; +import { inject, injectable } from "tsyringe"; @injectable() -export class PlayerScavGenerator -{ +export class PlayerScavGenerator { protected playerScavConfig: IPlayerScavConfig; constructor( @@ -47,8 +46,7 @@ export class PlayerScavGenerator @inject("BotGenerator") protected botGenerator: BotGenerator, @inject("ConfigServer") protected configServer: ConfigServer, @inject("PrimaryCloner") protected cloner: ICloner, - ) - { + ) { this.playerScavConfig = this.configServer.getConfig(ConfigTypes.PLAYERSCAV); } @@ -57,8 +55,7 @@ export class PlayerScavGenerator * @param sessionID session id to specify what profile is updated * @returns profile object */ - public generate(sessionID: string): IPmcData - { + public generate(sessionID: string): IPmcData { // get karma level from profile const profile = this.saveServer.getProfile(sessionID); const pmcDataClone = this.cloner.clone(profile.characters.pmc); @@ -68,8 +65,7 @@ export class PlayerScavGenerator // use karma level to get correct karmaSettings const playerScavKarmaSettings = this.playerScavConfig.karmaLevel[scavKarmaLevel]; - if (!playerScavKarmaSettings) - { + if (!playerScavKarmaSettings) { this.logger.error(this.localisationService.getText("scav-missing_karma_settings", scavKarmaLevel)); } @@ -144,19 +140,15 @@ export class PlayerScavGenerator possibleItemsToAdd: Record, scavData: IBotBase, containersToAddTo: string[], - ): void - { - for (const tpl in possibleItemsToAdd) - { + ): void { + for (const tpl in possibleItemsToAdd) { const shouldAdd = this.randomUtil.getChance100(possibleItemsToAdd[tpl]); - if (!shouldAdd) - { + if (!shouldAdd) { continue; } const itemResult = this.itemHelper.getItem(tpl); - if (!itemResult[0]) - { + if (!itemResult[0]) { this.logger.warning(this.localisationService.getText("scav-unable_to_add_item_to_player_scav", tpl)); continue; @@ -179,8 +171,7 @@ export class PlayerScavGenerator scavData.Inventory, ); - if (result !== ItemAddedResult.SUCCESS) - { + if (result !== ItemAddedResult.SUCCESS) { this.logger.debug(`Unable to add keycard to bot. Reason: ${ItemAddedResult[result]}`); } } @@ -192,20 +183,17 @@ export class PlayerScavGenerator * @param pmcData pmc profile * @returns karma level */ - protected getScavKarmaLevel(pmcData: IPmcData): number - { + protected getScavKarmaLevel(pmcData: IPmcData): number { const fenceInfo = pmcData.TradersInfo[Traders.FENCE]; // Can be empty during profile creation - if (!fenceInfo) - { + if (!fenceInfo) { this.logger.warning(this.localisationService.getText("scav-missing_karma_level_getting_default")); return 0; } - if (fenceInfo.standing > 6) - { + if (fenceInfo.standing > 6) { return 6; } @@ -219,14 +207,12 @@ export class PlayerScavGenerator * @param botTypeForLoot bot type to use for inventory/chances * @returns IBotType object */ - protected constructBotBaseTemplate(botTypeForLoot: string): IBotType - { + protected constructBotBaseTemplate(botTypeForLoot: string): IBotType { const baseScavType = "assault"; const assaultBase = this.cloner.clone(this.botHelper.getBotTemplate(baseScavType)); // Loot bot is same as base bot, return base with no modification - if (botTypeForLoot === baseScavType) - { + if (botTypeForLoot === baseScavType) { return assaultBase; } @@ -243,13 +229,10 @@ export class PlayerScavGenerator * @param karmaSettings Values to modify the bot template with * @param baseBotNode bot template to modify according to karama level settings */ - protected adjustBotTemplateWithKarmaSpecificSettings(karmaSettings: KarmaLevel, baseBotNode: IBotType): void - { + protected adjustBotTemplateWithKarmaSpecificSettings(karmaSettings: KarmaLevel, baseBotNode: IBotType): void { // Adjust equipment chance values - for (const equipmentKey in karmaSettings.modifiers.equipment) - { - if (karmaSettings.modifiers.equipment[equipmentKey] === 0) - { + for (const equipmentKey in karmaSettings.modifiers.equipment) { + if (karmaSettings.modifiers.equipment[equipmentKey] === 0) { continue; } @@ -257,10 +240,8 @@ export class PlayerScavGenerator } // Adjust mod chance values - for (const modKey in karmaSettings.modifiers.mod) - { - if (karmaSettings.modifiers.mod[modKey] === 0) - { + for (const modKey in karmaSettings.modifiers.mod) { + if (karmaSettings.modifiers.mod[modKey] === 0) { continue; } @@ -268,63 +249,51 @@ export class PlayerScavGenerator } // Adjust item spawn quantity values - for (const itemLimitkey in karmaSettings.itemLimits) - { + for (const itemLimitkey in karmaSettings.itemLimits) { baseBotNode.generation.items[itemLimitkey] = karmaSettings.itemLimits[itemLimitkey]; } // Blacklist equipment - for (const equipmentKey in karmaSettings.equipmentBlacklist) - { + for (const equipmentKey in karmaSettings.equipmentBlacklist) { const blacklistedItemTpls = karmaSettings.equipmentBlacklist[equipmentKey]; - for (const itemToRemove of blacklistedItemTpls) - { + for (const itemToRemove of blacklistedItemTpls) { delete baseBotNode.inventory.equipment[equipmentKey][itemToRemove]; } } } - protected getScavSkills(scavProfile: IPmcData): Skills - { - if (scavProfile.Skills) - { + protected getScavSkills(scavProfile: IPmcData): Skills { + if (scavProfile.Skills) { return scavProfile.Skills; } return this.getDefaultScavSkills(); } - protected getDefaultScavSkills(): Skills - { + protected getDefaultScavSkills(): Skills { return { Common: [], Mastering: [], Points: 0 }; } - protected getScavStats(scavProfile: IPmcData): Stats - { - if (scavProfile.Stats) - { + protected getScavStats(scavProfile: IPmcData): Stats { + if (scavProfile.Stats) { return scavProfile.Stats; } return this.profileHelper.getDefaultCounters(); } - protected getScavLevel(scavProfile: IPmcData): number - { + protected getScavLevel(scavProfile: IPmcData): number { // Info can be undefined on initial account creation - if (!scavProfile.Info?.Level) - { + if (!scavProfile.Info?.Level) { return 1; } return scavProfile.Info.Level; } - protected getScavExperience(scavProfile: IPmcData): number - { + protected getScavExperience(scavProfile: IPmcData): number { // Info can be undefined on initial account creation - if (!scavProfile.Info?.Experience) - { + if (!scavProfile.Info?.Experience) { return 0; } @@ -338,17 +307,14 @@ export class PlayerScavGenerator * @param pmcData pmc profile * @returns */ - protected setScavCooldownTimer(scavData: IPmcData, pmcData: IPmcData): IPmcData - { + protected setScavCooldownTimer(scavData: IPmcData, pmcData: IPmcData): IPmcData { // Set cooldown time. // Make sure to apply ScavCooldownTimer bonus from Hideout if the player has it. let scavLockDuration = this.databaseService.getGlobals().config.SavagePlayCooldown; let modifier = 1; - for (const bonus of pmcData.Bonuses) - { - if (bonus.type === BonusType.SCAV_COOLDOWN_TIMER) - { + for (const bonus of pmcData.Bonuses) { + if (bonus.type === BonusType.SCAV_COOLDOWN_TIMER) { // Value is negative, so add. // Also note that for scav cooldown, multiple bonuses stack additively. modifier += bonus.value / 100; @@ -360,8 +326,7 @@ export class PlayerScavGenerator scavLockDuration *= modifier; const fullProfile = this.profileHelper.getFullProfile(pmcData?.sessionId); - if (fullProfile?.info?.edition?.toLowerCase?.().startsWith?.(AccountTypes.SPT_DEVELOPER)) - { + if (fullProfile?.info?.edition?.toLowerCase?.().startsWith?.(AccountTypes.SPT_DEVELOPER)) { // Set scav cooldown timer to 10 seconds for spt developer account scavLockDuration = 10; } diff --git a/project/src/generators/RagfairAssortGenerator.ts b/project/src/generators/RagfairAssortGenerator.ts index 9ce49b7e..d24de350 100644 --- a/project/src/generators/RagfairAssortGenerator.ts +++ b/project/src/generators/RagfairAssortGenerator.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { ItemHelper } from "@spt/helpers/ItemHelper"; import { PresetHelper } from "@spt/helpers/PresetHelper"; import { IPreset } from "@spt/models/eft/common/IGlobals"; @@ -10,10 +9,10 @@ import { ConfigServer } from "@spt/servers/ConfigServer"; import { DatabaseServer } from "@spt/servers/DatabaseServer"; import { SeasonalEventService } from "@spt/services/SeasonalEventService"; import { HashUtil } from "@spt/utils/HashUtil"; +import { inject, injectable } from "tsyringe"; @injectable() -export class RagfairAssortGenerator -{ +export class RagfairAssortGenerator { protected generatedAssortItems: Item[][] = []; protected ragfairConfig: IRagfairConfig; @@ -34,8 +33,7 @@ export class RagfairAssortGenerator @inject("DatabaseServer") protected databaseServer: DatabaseServer, @inject("SeasonalEventService") protected seasonalEventService: SeasonalEventService, @inject("ConfigServer") protected configServer: ConfigServer, - ) - { + ) { this.ragfairConfig = this.configServer.getConfig(ConfigTypes.RAGFAIR); } @@ -44,10 +42,8 @@ export class RagfairAssortGenerator * Each sub array contains item + children (if any) * @returns array of arrays */ - public getAssortItems(): Item[][] - { - if (!this.assortsAreGenerated()) - { + public getAssortItems(): Item[][] { + if (!this.assortsAreGenerated()) { this.generatedAssortItems = this.generateRagfairAssortItems(); } @@ -58,8 +54,7 @@ export class RagfairAssortGenerator * Check internal generatedAssortItems array has objects * @returns true if array has objects */ - protected assortsAreGenerated(): boolean - { + protected assortsAreGenerated(): boolean { return this.generatedAssortItems.length > 0; } @@ -67,8 +62,7 @@ export class RagfairAssortGenerator * Generate an array of arrays (item + children) the flea can sell * @returns array of arrays (item + children) */ - protected generateRagfairAssortItems(): Item[][] - { + protected generateRagfairAssortItems(): Item[][] { const results: Item[][] = []; /** Get cloned items from db */ @@ -80,8 +74,7 @@ export class RagfairAssortGenerator const seasonalItemTplBlacklist = this.seasonalEventService.getInactiveSeasonalEventItems(); const presets = this.getPresetsToAdd(); - for (const preset of presets) - { + for (const preset of presets) { // Update Ids and clone const presetAndMods: Item[] = this.itemHelper.replaceIDs(preset._items); this.itemHelper.remapRootItemId(presetAndMods); @@ -96,25 +89,21 @@ export class RagfairAssortGenerator results.push(presetAndMods); } - for (const item of dbItemsClone) - { - if (!this.itemHelper.isValidItem(item._id, this.ragfairItemInvalidBaseTypes)) - { + for (const item of dbItemsClone) { + if (!this.itemHelper.isValidItem(item._id, this.ragfairItemInvalidBaseTypes)) { continue; } // Skip seasonal items when not in-season if ( - this.ragfairConfig.dynamic.removeSeasonalItemsWhenNotInEvent - && !seasonalEventActive - && seasonalItemTplBlacklist.includes(item._id) - ) - { + this.ragfairConfig.dynamic.removeSeasonalItemsWhenNotInEvent && + !seasonalEventActive && + seasonalItemTplBlacklist.includes(item._id) + ) { continue; } - if (processedArmorItems.includes(item._id)) - { + if (processedArmorItems.includes(item._id)) { // Already processed continue; } @@ -132,8 +121,7 @@ export class RagfairAssortGenerator * ragfairConfig.dynamic.showDefaultPresetsOnly decides if its all presets or just defaults * @returns IPreset array */ - protected getPresetsToAdd(): IPreset[] - { + protected getPresetsToAdd(): IPreset[] { return this.ragfairConfig.dynamic.showDefaultPresetsOnly ? Object.values(this.presetHelper.getDefaultPresets()) : this.presetHelper.getAllPresets(); @@ -145,8 +133,7 @@ export class RagfairAssortGenerator * @param id id to add to item * @returns Hydrated Item object */ - protected createRagfairAssortRootItem(tplId: string, id = this.hashUtil.generate()): Item - { + protected createRagfairAssortRootItem(tplId: string, id = this.hashUtil.generate()): Item { return { _id: id, _tpl: tplId, diff --git a/project/src/generators/RagfairOfferGenerator.ts b/project/src/generators/RagfairOfferGenerator.ts index 30f2446a..2d5f78bc 100644 --- a/project/src/generators/RagfairOfferGenerator.ts +++ b/project/src/generators/RagfairOfferGenerator.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { RagfairAssortGenerator } from "@spt/generators/RagfairAssortGenerator"; import { BotHelper } from "@spt/helpers/BotHelper"; import { HandbookHelper } from "@spt/helpers/HandbookHelper"; @@ -29,16 +28,16 @@ import { FenceService } from "@spt/services/FenceService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { RagfairOfferService } from "@spt/services/RagfairOfferService"; import { RagfairPriceService } from "@spt/services/RagfairPriceService"; -import { ICloner } from "@spt/utils/cloners/ICloner"; import { HashUtil } from "@spt/utils/HashUtil"; import { RandomUtil } from "@spt/utils/RandomUtil"; import { TimeUtil } from "@spt/utils/TimeUtil"; +import { ICloner } from "@spt/utils/cloners/ICloner"; +import { inject, injectable } from "tsyringe"; @injectable() -export class RagfairOfferGenerator -{ +export class RagfairOfferGenerator { protected ragfairConfig: IRagfairConfig; - protected allowedFleaPriceItemsForBarter: { tpl: string, price: number }[]; + protected allowedFleaPriceItemsForBarter: { tpl: string; price: number }[]; /** Internal counter to ensure each offer created has a unique value for its intId property */ protected offerCounter = 0; @@ -64,8 +63,7 @@ export class RagfairOfferGenerator @inject("ItemHelper") protected itemHelper: ItemHelper, @inject("ConfigServer") protected configServer: ConfigServer, @inject("PrimaryCloner") protected cloner: ICloner, - ) - { + ) { this.ragfairConfig = this.configServer.getConfig(ConfigTypes.RAGFAIR); } @@ -86,8 +84,7 @@ export class RagfairOfferGenerator barterScheme: IBarterScheme[], loyalLevel: number, sellInOnePiece = false, - ): IRagfairOffer - { + ): IRagfairOffer { const offer = this.createOffer(userID, time, items, barterScheme, loyalLevel, sellInOnePiece); this.ragfairOfferService.addOffer(offer); @@ -111,12 +108,10 @@ export class RagfairOfferGenerator barterScheme: IBarterScheme[], loyalLevel: number, isPackOffer = false, - ): IRagfairOffer - { + ): IRagfairOffer { const isTrader = this.ragfairServerHelper.isTrader(userID); - const offerRequirements = barterScheme.map((barter) => - { + const offerRequirements = barterScheme.map((barter) => { const offerRequirement: OfferRequirement = { _tpl: barter._tpl, count: +barter.count.toFixed(2), @@ -124,8 +119,7 @@ export class RagfairOfferGenerator }; // Dogtags define level and side - if (barter.level !== undefined) - { + if (barter.level !== undefined) { offerRequirement.level = barter.level; offerRequirement.side = barter.side; } @@ -139,9 +133,7 @@ export class RagfairOfferGenerator // Hydrate ammo boxes with cartridges + ensure only 1 item is present (ammo box) // On offer refresh dont re-add cartridges to ammo box that already has cartridges - if (this.itemHelper.isOfBaseclass(itemsClone[0]._tpl, BaseClasses.AMMO_BOX) - && itemsClone.length === 1) - { + if (this.itemHelper.isOfBaseclass(itemsClone[0]._tpl, BaseClasses.AMMO_BOX) && itemsClone.length === 1) { this.itemHelper.addCartridgesToAmmoBox(itemsClone, this.itemHelper.getItem(items[0]._tpl)[1]); } @@ -176,11 +168,9 @@ export class RagfairOfferGenerator * @param isTrader Is the user creating the offer a trader * @returns IRagfairOfferUser */ - createUserDataForFleaOffer(userID: string, isTrader: boolean): IRagfairOfferUser - { + createUserDataForFleaOffer(userID: string, isTrader: boolean): IRagfairOfferUser { // Trader offer - if (isTrader) - { + if (isTrader) { return { id: userID, memberType: MemberCategory.TRADER, @@ -188,8 +178,7 @@ export class RagfairOfferGenerator } const isPlayerOffer = this.profileHelper.isPlayer(userID); - if (isPlayerOffer) - { + if (isPlayerOffer) { const playerProfile = this.profileHelper.getPmcProfile(userID)!; return { id: playerProfile._id, @@ -210,7 +199,8 @@ export class RagfairOfferGenerator nickname: this.botHelper.getPmcNicknameOfMaxLength(userID, 50), rating: this.randomUtil.getFloat( this.ragfairConfig.dynamic.rating.min, - this.ragfairConfig.dynamic.rating.max), + this.ragfairConfig.dynamic.rating.max, + ), isRatingGrowing: this.randomUtil.getBool(), avatar: undefined, aid: this.hashUtil.generateAccountId(), @@ -222,11 +212,9 @@ export class RagfairOfferGenerator * @param offerRequirements barter requirements for offer * @returns rouble cost of offer */ - protected convertOfferRequirementsIntoRoubles(offerRequirements: OfferRequirement[]): number - { + protected convertOfferRequirementsIntoRoubles(offerRequirements: OfferRequirement[]): number { let roublePrice = 0; - for (const requirement of offerRequirements) - { + for (const requirement of offerRequirements) { roublePrice += this.paymentHelper.isMoneyTpl(requirement._tpl) ? Math.round(this.calculateRoublePrice(requirement.count, requirement._tpl)) : this.ragfairPriceService.getFleaPriceForItem(requirement._tpl) * requirement.count; // get flea price for barter offer items @@ -241,10 +229,8 @@ export class RagfairOfferGenerator * @param userId persons id to get avatar of * @returns url of avatar */ - protected getAvatarUrl(isTrader: boolean, userId: string): string - { - if (isTrader) - { + protected getAvatarUrl(isTrader: boolean, userId: string): string { + if (isTrader) { return this.databaseService.getTrader(userId).base.avatar; } @@ -257,10 +243,8 @@ export class RagfairOfferGenerator * @param currencyType Type of currency (euro/dollar/rouble) * @returns count of roubles */ - protected calculateRoublePrice(currencyCount: number, currencyType: string): number - { - if (currencyType === Money.ROUBLES) - { + protected calculateRoublePrice(currencyCount: number, currencyType: string): number { + if (currencyType === Money.ROUBLES) { return currencyCount; } @@ -272,10 +256,8 @@ export class RagfairOfferGenerator * @param userId Users Id to check * @returns Users Id */ - protected getTraderId(userId: string): string - { - if (this.profileHelper.isPlayer(userId)) - { + protected getTraderId(userId: string): string { + if (this.profileHelper.isPlayer(userId)) { return this.saveServer.getProfile(userId).characters.pmc._id; } @@ -287,16 +269,13 @@ export class RagfairOfferGenerator * @param userId User to get flea rating of * @returns Flea rating value */ - protected getRating(userId: string): number - { - if (this.profileHelper.isPlayer(userId)) - { + protected getRating(userId: string): number { + if (this.profileHelper.isPlayer(userId)) { // Player offer return this.saveServer.getProfile(userId).characters.pmc.RagfairInfo.rating; } - if (this.ragfairServerHelper.isTrader(userId)) - { + if (this.ragfairServerHelper.isTrader(userId)) { // Trader offer return 1; } @@ -310,16 +289,13 @@ export class RagfairOfferGenerator * @param userID user to check rating of * @returns true if its growing */ - protected getRatingGrowing(userID: string): boolean - { - if (this.profileHelper.isPlayer(userID)) - { + protected getRatingGrowing(userID: string): boolean { + if (this.profileHelper.isPlayer(userID)) { // player offer return this.saveServer.getProfile(userID).characters.pmc.RagfairInfo.isRatingGrowing; } - if (this.ragfairServerHelper.isTrader(userID)) - { + if (this.ragfairServerHelper.isTrader(userID)) { // trader offer return true; } @@ -335,29 +311,25 @@ export class RagfairOfferGenerator * @param time Time the offer is posted * @returns number of seconds until offer expires */ - protected getOfferEndTime(userID: string, time: number): number - { - if (this.profileHelper.isPlayer(userID)) - { + protected getOfferEndTime(userID: string, time: number): number { + if (this.profileHelper.isPlayer(userID)) { // Player offer = current time + offerDurationTimeInHour; - const offerDurationTimeHours - = this.databaseService.getGlobals().config.RagFair.offerDurationTimeInHour; + const offerDurationTimeHours = this.databaseService.getGlobals().config.RagFair.offerDurationTimeInHour; return this.timeUtil.getTimestamp() + Math.round(offerDurationTimeHours * TimeUtil.ONE_HOUR_AS_SECONDS); } - if (this.ragfairServerHelper.isTrader(userID)) - { + if (this.ragfairServerHelper.isTrader(userID)) { // Trader offer return this.databaseService.getTrader(userID).base.nextResupply; } // Generated fake-player offer return Math.round( - time - + this.randomUtil.getInt( - this.ragfairConfig.dynamic.endTimeSeconds.min, - this.ragfairConfig.dynamic.endTimeSeconds.max, - ), + time + + this.randomUtil.getInt( + this.ragfairConfig.dynamic.endTimeSeconds.min, + this.ragfairConfig.dynamic.endTimeSeconds.max, + ), ); } @@ -365,8 +337,7 @@ export class RagfairOfferGenerator * Create multiple offers for items by using a unique list of items we've generated previously * @param expiredOffers optional, expired offers to regenerate */ - public async generateDynamicOffers(expiredOffers?: Item[][]): Promise - { + public async generateDynamicOffers(expiredOffers?: Item[][]): Promise { const replacingExpiredOffers = Boolean(expiredOffers?.length); // get assort items from param if they exist, otherwise grab freshly generated assorts @@ -375,9 +346,11 @@ export class RagfairOfferGenerator : this.ragfairAssortGenerator.getAssortItems(); // Create offers for each item set concurrently - await Promise.all(assortItemsToProcess.map((assortItemWithChildren) => - this.createOffersFromAssort(assortItemWithChildren, replacingExpiredOffers, this.ragfairConfig.dynamic), - )); + await Promise.all( + assortItemsToProcess.map((assortItemWithChildren) => + this.createOffersFromAssort(assortItemWithChildren, replacingExpiredOffers, this.ragfairConfig.dynamic), + ), + ); } /** @@ -389,20 +362,17 @@ export class RagfairOfferGenerator assortItemWithChildren: Item[], isExpiredOffer: boolean, config: Dynamic, - ): Promise - { + ): Promise { const itemDetails = this.itemHelper.getItem(assortItemWithChildren[0]._tpl); const isPreset = this.presetHelper.isPreset(assortItemWithChildren[0].upd.sptPresetId); // Only perform checks on newly generated items, skip expired items being refreshed - if (!(isExpiredOffer || this.ragfairServerHelper.isItemValidRagfairItem(itemDetails))) - { + if (!(isExpiredOffer || this.ragfairServerHelper.isItemValidRagfairItem(itemDetails))) { return; } // Armor presets can hold plates above the allowed flea level, remove if necessary - if (isPreset && this.ragfairConfig.dynamic.blacklist.enableBsgList) - { + if (isPreset && this.ragfairConfig.dynamic.blacklist.enableBsgList) { this.removeBannedPlatesFromPreset(assortItemWithChildren, this.ragfairConfig.dynamic.blacklist.armorPlate); } @@ -414,8 +384,7 @@ export class RagfairOfferGenerator // Store all functions to create offers for this item and pass into Promise.all to run async const assortSingleOfferProcesses = []; - for (let index = 0; index < offerCount; index++) - { + for (let index = 0; index < offerCount; index++) { // Clone the item so we don't have shared references and generate new item IDs const clonedAssort = this.cloner.clone(assortItemWithChildren); this.itemHelper.reparentItemAndChildren(clonedAssort[0], clonedAssort); @@ -439,10 +408,8 @@ export class RagfairOfferGenerator protected removeBannedPlatesFromPreset( presetWithChildren: Item[], plateSettings: IArmorPlateBlacklistSettings, - ): boolean - { - if (!this.itemHelper.armorItemCanHoldMods(presetWithChildren[0]._tpl)) - { + ): boolean { + if (!this.itemHelper.armorItemCanHoldMods(presetWithChildren[0]._tpl)) { // Cant hold armor inserts, skip return false; } @@ -450,24 +417,20 @@ export class RagfairOfferGenerator const plateSlots = presetWithChildren.filter((item) => this.itemHelper.getRemovablePlateSlotIds().includes(item.slotId?.toLowerCase()), ); - if (plateSlots.length === 0) - { + if (plateSlots.length === 0) { // Has no plate slots e.g. "front_plate", exit return false; } let removedPlate = false; - for (const plateSlot of plateSlots) - { + for (const plateSlot of plateSlots) { const plateDetails = this.itemHelper.getItem(plateSlot._tpl)[1]; - if (plateSettings.ignoreSlots.includes(plateSlot.slotId.toLowerCase())) - { + if (plateSettings.ignoreSlots.includes(plateSlot.slotId.toLowerCase())) { continue; } const plateArmorLevel = Number.parseInt(plateDetails._props.armorClass) ?? 0; - if (plateArmorLevel > plateSettings.maxProtectionLevel) - { + if (plateArmorLevel > plateSettings.maxProtectionLevel) { presetWithChildren.splice(presetWithChildren.indexOf(plateSlot), 1); removedPlate = true; } @@ -487,8 +450,7 @@ export class RagfairOfferGenerator itemWithChildren: Item[], isPreset: boolean, itemDetails: [boolean, ITemplateItem], - ): Promise - { + ): Promise { // Set stack size to random value itemWithChildren[0].upd.StackObjectsCount = this.ragfairServerHelper.calculateDynamicStackCount( itemWithChildren[0]._tpl, @@ -496,11 +458,11 @@ export class RagfairOfferGenerator ); const isBarterOffer = this.randomUtil.getChance100(this.ragfairConfig.dynamic.barter.chancePercent); - const isPackOffer - = this.randomUtil.getChance100(this.ragfairConfig.dynamic.pack.chancePercent) - && !isBarterOffer - && itemWithChildren.length === 1 - && this.itemHelper.isOfBaseclasses( + const isPackOffer = + this.randomUtil.getChance100(this.ragfairConfig.dynamic.pack.chancePercent) && + !isBarterOffer && + itemWithChildren.length === 1 && + this.itemHelper.isOfBaseclasses( itemWithChildren[0]._tpl, this.ragfairConfig.dynamic.pack.itemTypeWhitelist, ); @@ -508,27 +470,23 @@ export class RagfairOfferGenerator const randomUserId = this.hashUtil.generate(); // Remove removable plates if % check passes - if (this.itemHelper.armorItemCanHoldMods(itemWithChildren[0]._tpl)) - { + if (this.itemHelper.armorItemCanHoldMods(itemWithChildren[0]._tpl)) { const armorConfig = this.ragfairConfig.dynamic.armor; const shouldRemovePlates = this.randomUtil.getChance100(armorConfig.removeRemovablePlateChance); - if (shouldRemovePlates && this.itemHelper.armorItemHasRemovablePlateSlots(itemWithChildren[0]._tpl)) - { + if (shouldRemovePlates && this.itemHelper.armorItemHasRemovablePlateSlots(itemWithChildren[0]._tpl)) { const offerItemPlatesToRemove = itemWithChildren.filter((item) => armorConfig.plateSlotIdToRemovePool.includes(item.slotId?.toLowerCase()), ); - for (const plateItem of offerItemPlatesToRemove) - { + for (const plateItem of offerItemPlatesToRemove) { itemWithChildren.splice(itemWithChildren.indexOf(plateItem), 1); } } } let barterScheme: IBarterScheme[]; - if (isPackOffer) - { + if (isPackOffer) { // Set pack size const stackSize = this.randomUtil.getInt( this.ragfairConfig.dynamic.pack.itemCountMin, @@ -538,15 +496,11 @@ export class RagfairOfferGenerator // Don't randomise pack items barterScheme = this.createCurrencyBarterScheme(itemWithChildren, isPackOffer, stackSize); - } - else if (isBarterOffer) - { + } else if (isBarterOffer) { // Apply randomised properties this.randomiseOfferItemUpdProperties(randomUserId, itemWithChildren, itemDetails[1]); barterScheme = this.createBarterBarterScheme(itemWithChildren); - } - else - { + } else { // Apply randomised properties this.randomiseOfferItemUpdProperties(randomUserId, itemWithChildren, itemDetails[1]); barterScheme = this.createCurrencyBarterScheme(itemWithChildren, isPackOffer); @@ -566,8 +520,7 @@ export class RagfairOfferGenerator * Generate trader offers on flea using the traders assort data * @param traderID Trader to generate offers for */ - public generateFleaOffersForTrader(traderID: string): void - { + public generateFleaOffersForTrader(traderID: string): void { // Purge this.ragfairOfferService.removeAllOffersByTrader(traderID); @@ -576,8 +529,7 @@ export class RagfairOfferGenerator const assorts = trader.assort; // Trader assorts / assort items are missing - if (!assorts?.items?.length) - { + if (!assorts?.items?.length) { this.logger.error( this.localisationService.getText( "ragfair-no_trader_assorts_cant_generate_flea_offers", @@ -588,28 +540,23 @@ export class RagfairOfferGenerator } const blacklist = this.ragfairConfig.dynamic.blacklist; - for (const item of assorts.items) - { + for (const item of assorts.items) { // We only want to process 'base/root' items, no children - if (item.slotId !== "hideout") - { + if (item.slotId !== "hideout") { // skip mod items continue; } // Run blacklist check on trader offers - if (blacklist.traderItems) - { + if (blacklist.traderItems) { const itemDetails = this.itemHelper.getItem(item._tpl); - if (!itemDetails[0]) - { + if (!itemDetails[0]) { this.logger.warning(this.localisationService.getText("ragfair-tpl_not_a_valid_item", item._tpl)); continue; } // Don't include items that BSG has blacklisted from flea - if (blacklist.enableBsgList && !itemDetails[1]._props.CanSellOnRagfair) - { + if (blacklist.enableBsgList && !itemDetails[1]._props.CanSellOnRagfair) { continue; } } @@ -620,8 +567,7 @@ export class RagfairOfferGenerator : [...[item], ...this.itemHelper.findAndReturnChildrenByAssort(item._id, assorts.items)]; const barterScheme = assorts.barter_scheme[item._id]; - if (!barterScheme) - { + if (!barterScheme) { this.logger.warning( this.localisationService.getText("ragfair-missing_barter_scheme", { itemId: item._id, @@ -649,23 +595,19 @@ export class RagfairOfferGenerator * @param itemWithMods Item and mods, get condition of first item (only first array item is modified) * @param itemDetails db details of first item */ - protected randomiseOfferItemUpdProperties(userID: string, itemWithMods: Item[], itemDetails: ITemplateItem): void - { + protected randomiseOfferItemUpdProperties(userID: string, itemWithMods: Item[], itemDetails: ITemplateItem): void { // Add any missing properties to first item in array this.addMissingConditions(itemWithMods[0]); - if (!(this.profileHelper.isPlayer(userID) || this.ragfairServerHelper.isTrader(userID))) - { + if (!(this.profileHelper.isPlayer(userID) || this.ragfairServerHelper.isTrader(userID))) { const parentId = this.getDynamicConditionIdForTpl(itemDetails._id); - if (!parentId) - { + if (!parentId) { // No condition details found, don't proceed with modifying item conditions return; } // Roll random chance to randomise item condition - if (this.randomUtil.getChance100(this.ragfairConfig.dynamic.condition[parentId].conditionChance * 100)) - { + if (this.randomUtil.getChance100(this.ragfairConfig.dynamic.condition[parentId].conditionChance * 100)) { this.randomiseItemCondition(parentId, itemWithMods, itemDetails); } } @@ -676,14 +618,11 @@ export class RagfairOfferGenerator * @param tpl Item to look for matching condition object * @returns condition id */ - protected getDynamicConditionIdForTpl(tpl: string): string | undefined - { + protected getDynamicConditionIdForTpl(tpl: string): string | undefined { // Get keys from condition config dictionary const configConditions = Object.keys(this.ragfairConfig.dynamic.condition); - for (const baseClass of configConditions) - { - if (this.itemHelper.isOfBaseclass(tpl, baseClass)) - { + for (const baseClass of configConditions) { + if (this.itemHelper.isOfBaseclass(tpl, baseClass)) { return baseClass; } } @@ -701,8 +640,7 @@ export class RagfairOfferGenerator conditionSettingsId: string, itemWithMods: Item[], itemDetails: ITemplateItem, - ): void - { + ): void { const rootItem = itemWithMods[0]; const itemConditionValues: Condition = this.ragfairConfig.dynamic.condition[conditionSettingsId]; @@ -714,18 +652,16 @@ export class RagfairOfferGenerator // Randomise armor + plates + armor related things if ( - this.itemHelper.armorItemCanHoldMods(rootItem._tpl) - || this.itemHelper.isOfBaseclasses(rootItem._tpl, [BaseClasses.ARMOR_PLATE, BaseClasses.ARMORED_EQUIPMENT]) - ) - { + this.itemHelper.armorItemCanHoldMods(rootItem._tpl) || + this.itemHelper.isOfBaseclasses(rootItem._tpl, [BaseClasses.ARMOR_PLATE, BaseClasses.ARMORED_EQUIPMENT]) + ) { this.randomiseArmorDurabilityValues(itemWithMods, currentMultiplier, maxMultiplier); // Add hits to visor const visorMod = itemWithMods.find( (item) => item.parentId === BaseClasses.ARMORED_EQUIPMENT && item.slotId === "mod_equipment_000", ); - if (this.randomUtil.getChance100(25) && visorMod) - { + if (this.randomUtil.getChance100(25) && visorMod) { this.itemHelper.addUpdObjectToItem(visorMod); visorMod.upd.FaceShield = { Hits: this.randomUtil.getInt(1, 3) }; @@ -735,48 +671,42 @@ export class RagfairOfferGenerator } // Randomise Weapons - if (this.itemHelper.isOfBaseclass(itemDetails._id, BaseClasses.WEAPON)) - { + if (this.itemHelper.isOfBaseclass(itemDetails._id, BaseClasses.WEAPON)) { this.randomiseWeaponDurability(itemWithMods[0], itemDetails, maxMultiplier, currentMultiplier); return; } - if (rootItem.upd.MedKit) - { + if (rootItem.upd.MedKit) { // Randomize health rootItem.upd.MedKit.HpResource = Math.round(rootItem.upd.MedKit.HpResource * maxMultiplier) || 1; return; } - if (rootItem.upd.Key && itemDetails._props.MaximumNumberOfUsage > 1) - { + if (rootItem.upd.Key && itemDetails._props.MaximumNumberOfUsage > 1) { // Randomize key uses - rootItem.upd.Key.NumberOfUsages - = Math.round(itemDetails._props.MaximumNumberOfUsage * (1 - maxMultiplier)) || 0; + rootItem.upd.Key.NumberOfUsages = + Math.round(itemDetails._props.MaximumNumberOfUsage * (1 - maxMultiplier)) || 0; return; } - if (rootItem.upd.FoodDrink) - { + if (rootItem.upd.FoodDrink) { // randomize food/drink value rootItem.upd.FoodDrink.HpPercent = Math.round(itemDetails._props.MaxResource * maxMultiplier) || 1; return; } - if (rootItem.upd.RepairKit) - { + if (rootItem.upd.RepairKit) { // randomize repair kit (armor/weapon) uses rootItem.upd.RepairKit.Resource = Math.round(itemDetails._props.MaxRepairResource * maxMultiplier) || 1; return; } - if (this.itemHelper.isOfBaseclass(itemDetails._id, BaseClasses.FUEL)) - { + if (this.itemHelper.isOfBaseclass(itemDetails._id, BaseClasses.FUEL)) { const totalCapacity = itemDetails._props.MaxResource; const remainingFuel = Math.round(totalCapacity * maxMultiplier); rootItem.upd.Resource = { UnitsConsumed: totalCapacity - remainingFuel, Value: remainingFuel }; @@ -795,14 +725,11 @@ export class RagfairOfferGenerator itemDbDetails: ITemplateItem, maxMultiplier: number, currentMultiplier: number, - ): void - { + ): void { // Max const baseMaxDurability = itemDbDetails._props.MaxDurability; const lowestMaxDurability = this.randomUtil.getFloat(maxMultiplier, 1) * baseMaxDurability; - const chosenMaxDurability = Math.round( - this.randomUtil.getFloat(lowestMaxDurability, baseMaxDurability), - ); + const chosenMaxDurability = Math.round(this.randomUtil.getFloat(lowestMaxDurability, baseMaxDurability)); // Current const lowestCurrentDurability = this.randomUtil.getFloat(currentMultiplier, 1) * chosenMaxDurability; @@ -824,18 +751,14 @@ export class RagfairOfferGenerator armorWithMods: Item[], currentMultiplier: number, maxMultiplier: number, - ): void - { - for (const armorItem of armorWithMods) - { + ): void { + for (const armorItem of armorWithMods) { const itemDbDetails = this.itemHelper.getItem(armorItem._tpl)[1]; - if (Number.parseInt(itemDbDetails._props.armorClass) > 1) - { + if (Number.parseInt(itemDbDetails._props.armorClass) > 1) { this.itemHelper.addUpdObjectToItem(armorItem); const baseMaxDurability = itemDbDetails._props.MaxDurability; - const lowestMaxDurability - = this.randomUtil.getFloat(maxMultiplier, 1) * baseMaxDurability; + const lowestMaxDurability = this.randomUtil.getFloat(maxMultiplier, 1) * baseMaxDurability; const chosenMaxDurability = Math.round( this.randomUtil.getFloat(lowestMaxDurability, baseMaxDurability), ); @@ -859,8 +782,7 @@ export class RagfairOfferGenerator * HpResource for medical items * @param item item to add conditions to */ - protected addMissingConditions(item: Item): void - { + protected addMissingConditions(item: Item): void { const props = this.itemHelper.getItem(item._tpl)[1]._props; const isRepairable = "Durability" in props; const isMedkit = "MaxHpResource" in props; @@ -868,37 +790,32 @@ export class RagfairOfferGenerator const isConsumable = props.MaxResource > 1 && "foodUseTime" in props; const isRepairKit = "MaxRepairResource" in props; - if (isRepairable && props.Durability > 0) - { + if (isRepairable && props.Durability > 0) { item.upd.Repairable = { Durability: props.Durability, MaxDurability: props.Durability }; return; } - if (isMedkit && props.MaxHpResource > 0) - { + if (isMedkit && props.MaxHpResource > 0) { item.upd.MedKit = { HpResource: props.MaxHpResource }; return; } - if (isKey) - { + if (isKey) { item.upd.Key = { NumberOfUsages: 0 }; return; } // Food/drink - if (isConsumable) - { + if (isConsumable) { item.upd.FoodDrink = { HpPercent: props.MaxResource }; return; } - if (isRepairKit) - { + if (isRepairKit) { item.upd.RepairKit = { Resource: props.MaxRepairResource }; } } @@ -908,8 +825,7 @@ export class RagfairOfferGenerator * @param offerItems Items for sale in offer * @returns Barter scheme */ - protected createBarterBarterScheme(offerItems: Item[]): IBarterScheme[] - { + protected createBarterBarterScheme(offerItems: Item[]): IBarterScheme[] { // get flea price of item being sold const priceOfItemOffer = this.ragfairPriceService.getDynamicOfferPriceForOffer( offerItems, @@ -918,8 +834,7 @@ export class RagfairOfferGenerator ); // Dont make items under a designated rouble value into barter offers - if (priceOfItemOffer < this.ragfairConfig.dynamic.barter.minRoubleCostToBecomeBarter) - { + if (priceOfItemOffer < this.ragfairConfig.dynamic.barter.minRoubleCostToBecomeBarter) { return this.createCurrencyBarterScheme(offerItems, false); } @@ -940,14 +855,13 @@ export class RagfairOfferGenerator // Filter possible barters to items that match the price range + not itself const filtered = fleaPrices.filter( (x) => - x.price >= desiredItemCost - offerCostVariance - && x.price <= desiredItemCost + offerCostVariance - && x.tpl !== offerItems[0]._tpl, + x.price >= desiredItemCost - offerCostVariance && + x.price <= desiredItemCost + offerCostVariance && + x.tpl !== offerItems[0]._tpl, ); // No items on flea have a matching price, fall back to currency - if (filtered.length === 0) - { + if (filtered.length === 0) { return this.createCurrencyBarterScheme(offerItems, false); } @@ -961,11 +875,9 @@ export class RagfairOfferGenerator * Get an array of flea prices + item tpl, cached in generator class inside `allowedFleaPriceItemsForBarter` * @returns array with tpl/price values */ - protected getFleaPricesAsArray(): { tpl: string, price: number }[] - { + protected getFleaPricesAsArray(): { tpl: string; price: number }[] { // Generate if needed - if (!this.allowedFleaPriceItemsForBarter) - { + if (!this.allowedFleaPriceItemsForBarter) { const fleaPrices = this.databaseService.getPrices(); // Only get prices for items that also exist in items.json @@ -993,11 +905,10 @@ export class RagfairOfferGenerator offerWithChildren: Item[], isPackOffer: boolean, multipler = 1, - ): IBarterScheme[] - { + ): IBarterScheme[] { const currency = this.ragfairServerHelper.getDynamicOfferCurrency(); - const price = this.ragfairPriceService.getDynamicOfferPriceForOffer(offerWithChildren, currency, isPackOffer) - * multipler; + const price = + this.ragfairPriceService.getDynamicOfferPriceForOffer(offerWithChildren, currency, isPackOffer) * multipler; return [{ count: price, _tpl: currency }]; } diff --git a/project/src/generators/RepeatableQuestGenerator.ts b/project/src/generators/RepeatableQuestGenerator.ts index ea780337..a5d991ba 100644 --- a/project/src/generators/RepeatableQuestGenerator.ts +++ b/project/src/generators/RepeatableQuestGenerator.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { RepeatableQuestRewardGenerator } from "@spt/generators/RepeatableQuestRewardGenerator"; import { ItemHelper } from "@spt/helpers/ItemHelper"; import { RepeatableQuestHelper } from "@spt/helpers/RepeatableQuestHelper"; @@ -20,14 +19,14 @@ import { ILogger } from "@spt/models/spt/utils/ILogger"; import { ConfigServer } from "@spt/servers/ConfigServer"; import { DatabaseService } from "@spt/services/DatabaseService"; import { LocalisationService } from "@spt/services/LocalisationService"; -import { ICloner } from "@spt/utils/cloners/ICloner"; import { MathUtil } from "@spt/utils/MathUtil"; import { ObjectId } from "@spt/utils/ObjectId"; import { ProbabilityObjectArray, RandomUtil } from "@spt/utils/RandomUtil"; +import { ICloner } from "@spt/utils/cloners/ICloner"; +import { inject, injectable } from "tsyringe"; @injectable() -export class RepeatableQuestGenerator -{ +export class RepeatableQuestGenerator { protected questConfig: IQuestConfig; constructor( @@ -43,8 +42,7 @@ export class RepeatableQuestGenerator protected repeatableQuestRewardGenerator: RepeatableQuestRewardGenerator, @inject("ConfigServer") protected configServer: ConfigServer, @inject("PrimaryCloner") protected cloner: ICloner, - ) - { + ) { this.questConfig = this.configServer.getConfig(ConfigTypes.QUEST); } @@ -62,8 +60,7 @@ export class RepeatableQuestGenerator pmcTraderInfo: Record, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig, - ): IRepeatableQuest - { + ): IRepeatableQuest { const questType = this.randomUtil.drawRandomFromList(questTypePool.types)[0]; // get traders from whitelist and filter by quest type availability @@ -74,8 +71,7 @@ export class RepeatableQuestGenerator traders = traders.filter((x) => pmcTraderInfo[x].unlocked); const traderId = this.randomUtil.drawRandomFromList(traders)[0]; - switch (questType) - { + switch (questType) { case "Elimination": return this.generateEliminationQuest(pmcLevel, traderId, questTypePool, repeatableConfig); case "Completion": @@ -102,8 +98,7 @@ export class RepeatableQuestGenerator traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig, - ): IRepeatableQuest - { + ): IRepeatableQuest { const eliminationConfig = this.repeatableQuestHelper.getEliminationConfigByPmcLevel(pmcLevel, repeatableConfig); const locationsConfig = repeatableConfig.locations; let targetsConfig = this.repeatableQuestHelper.probabilityObjectArray(eliminationConfig.targets); @@ -153,16 +148,14 @@ export class RepeatableQuestGenerator dist: number, kill: number, weaponRequirement: number, - ): number | undefined - { + ): number | undefined { return Math.sqrt(Math.sqrt(target) + bodyPart + dist + weaponRequirement) * kill; } targetsConfig = targetsConfig.filter((x) => Object.keys(questTypePool.pool.Elimination.targets).includes(x.key), ); - if (targetsConfig.length === 0 || targetsConfig.every((x) => x.data.isBoss)) - { + if (targetsConfig.length === 0 || targetsConfig.every((x) => x.data.isBoss)) { // There are no more targets left for elimination; delete it as a possible quest type // also if only bosses are left we need to leave otherwise it's a guaranteed boss elimination // -> then it would not be a quest with low probability anymore @@ -179,29 +172,22 @@ export class RepeatableQuestGenerator // we use any also if the random condition is not met in case only "any" was in the pool let locationKey = "any"; if ( - locations.includes("any") - && (eliminationConfig.specificLocationProb < Math.random() || locations.length <= 1) - ) - { + locations.includes("any") && + (eliminationConfig.specificLocationProb < Math.random() || locations.length <= 1) + ) { locationKey = "any"; delete questTypePool.pool.Elimination.targets[targetKey]; - } - else - { + } else { locations = locations.filter((l) => l !== "any"); - if (locations.length > 0) - { + if (locations.length > 0) { locationKey = this.randomUtil.drawRandomFromList(locations)[0]; questTypePool.pool.Elimination.targets[targetKey].locations = locations.filter( (l) => l !== locationKey, ); - if (questTypePool.pool.Elimination.targets[targetKey].locations.length === 0) - { + if (questTypePool.pool.Elimination.targets[targetKey].locations.length === 0) { delete questTypePool.pool.Elimination.targets[targetKey]; } - } - else - { + } else { // never should reach this if everything works out this.logger.debug("Ecountered issue when creating Elimination quest. Please report."); } @@ -210,20 +196,17 @@ export class RepeatableQuestGenerator // draw the target body part and calculate the difficulty factor let bodyPartsToClient = undefined; let bodyPartDifficulty = 0; - if (eliminationConfig.bodyPartProb > Math.random()) - { + if (eliminationConfig.bodyPartProb > Math.random()) { // if we add a bodyPart condition, we draw randomly one or two parts // each bodyPart of the BODYPARTS ProbabilityObjectArray includes the string(s) which need to be presented to the client in ProbabilityObjectArray.data // e.g. we draw "Arms" from the probability array but must present ["LeftArm", "RightArm"] to the client bodyPartsToClient = []; const bodyParts = bodypartsConfig.draw(this.randomUtil.randInt(1, 3), false); let probability = 0; - for (const bi of bodyParts) - { + for (const bi of bodyParts) { // more than one part lead to an "OR" condition hence more parts reduce the difficulty probability += bodypartsConfig.probability(bi); - for (const biClient of bodypartsConfig.data(bi)) - { + for (const biClient of bodypartsConfig.data(bi)) { bodyPartsToClient.push(biClient); } } @@ -235,8 +218,7 @@ export class RepeatableQuestGenerator let distanceDifficulty = 0; let isDistanceRequirementAllowed = !eliminationConfig.distLocationBlacklist.includes(locationKey); - if (targetsConfig.data(targetKey).isBoss) - { + if (targetsConfig.data(targetKey).isBoss) { // Get all boss spawn information const bossSpawns = Object.values(this.databaseService.getLocations()) .filter((x) => "base" in x && "Id" in x.base) @@ -254,29 +236,24 @@ export class RepeatableQuestGenerator isDistanceRequirementAllowed = isDistanceRequirementAllowed && allowedSpawns.length > 0; } - if (eliminationConfig.distProb > Math.random() && isDistanceRequirementAllowed) - { + if (eliminationConfig.distProb > Math.random() && isDistanceRequirementAllowed) { // Random distance with lower values more likely; simple distribution for starters... distance = Math.floor( - Math.abs(Math.random() - Math.random()) * (1 + eliminationConfig.maxDist - eliminationConfig.minDist) - + eliminationConfig.minDist, + Math.abs(Math.random() - Math.random()) * (1 + eliminationConfig.maxDist - eliminationConfig.minDist) + + eliminationConfig.minDist, ); distance = Math.ceil(distance / 5) * 5; distanceDifficulty = (maxDistDifficulty * distance) / eliminationConfig.maxDist; } let allowedWeaponsCategory: string = undefined; - if (eliminationConfig.weaponCategoryRequirementProb > Math.random()) - { + if (eliminationConfig.weaponCategoryRequirementProb > Math.random()) { // Filter out close range weapons from far distance requirement - if (distance > 50) - { + if (distance > 50) { weaponCategoryRequirementConfig = weaponCategoryRequirementConfig.filter((category) => ["Shotgun", "Pistol"].includes(category.key), ); - } - else if (distance < 20) - { + } else if (distance < 20) { // Filter out far range weapons from close distance requirement weaponCategoryRequirementConfig = weaponCategoryRequirementConfig.filter((category) => ["MarksmanRifle", "DMR"].includes(category.key), @@ -292,8 +269,7 @@ export class RepeatableQuestGenerator // Only allow a specific weapon requirement if a weapon category was not chosen let allowedWeapon: string = undefined; - if (!allowedWeaponsCategory && eliminationConfig.weaponRequirementProb > Math.random()) - { + if (!allowedWeaponsCategory && eliminationConfig.weaponRequirementProb > Math.random()) { const weaponRequirement = weaponRequirementConfig.draw(1, false); const allowedWeaponsCategory = weaponRequirementConfig.data(weaponRequirement[0])[0]; const allowedWeapons = this.itemHelper.getItemTplsOfBaseType(allowedWeaponsCategory); @@ -323,8 +299,7 @@ export class RepeatableQuestGenerator const quest = this.generateRepeatableTemplate("Elimination", traderId, repeatableConfig.side); // ASSUMPTION: All fence quests are for scavs - if (traderId === Traders.FENCE) - { + if (traderId === Traders.FENCE) { quest.side = "Scav"; } @@ -333,8 +308,7 @@ export class RepeatableQuestGenerator availableForFinishCondition.counter.conditions = []; // Only add specific location condition if specific map selected - if (locationKey !== "any") - { + if (locationKey !== "any") { availableForFinishCondition.counter.conditions.push( this.generateEliminationLocation(locationsConfig[locationKey]), ); @@ -374,15 +348,12 @@ export class RepeatableQuestGenerator targetKey: string, targetsConfig: ProbabilityObjectArray, eliminationConfig: IEliminationConfig, - ): number - { - if (targetsConfig.data(targetKey).isBoss) - { + ): number { + if (targetsConfig.data(targetKey).isBoss) { return this.randomUtil.randInt(eliminationConfig.minBossKills, eliminationConfig.maxBossKills + 1); } - if (targetsConfig.data(targetKey).isPmc) - { + if (targetsConfig.data(targetKey).isPmc) { return this.randomUtil.randInt(eliminationConfig.minPmcKills, eliminationConfig.maxPmcKills + 1); } @@ -396,8 +367,7 @@ export class RepeatableQuestGenerator * @param {string} location the location on which to fulfill the elimination quest * @returns {IEliminationCondition} object of "Elimination"-location-subcondition */ - protected generateEliminationLocation(location: string[]): IQuestConditionCounterCondition - { + protected generateEliminationLocation(location: string[]): IQuestConditionCounterCondition { const propsObject: IQuestConditionCounterCondition = { id: this.objectId.generate(), dynamicLocale: true, @@ -423,8 +393,7 @@ export class RepeatableQuestGenerator distance: number, allowedWeapon: string, allowedWeaponCategory: string, - ): IQuestConditionCounterCondition - { + ): IQuestConditionCounterCondition { const killConditionProps: IQuestConditionCounterCondition = { target: target, value: 1, @@ -433,33 +402,28 @@ export class RepeatableQuestGenerator conditionType: "Kills", }; - if (target.startsWith("boss")) - { + if (target.startsWith("boss")) { killConditionProps.target = "Savage"; killConditionProps.savageRole = [target]; } // Has specific body part hit condition - if (targetedBodyParts) - { + if (targetedBodyParts) { killConditionProps.bodyPart = targetedBodyParts; } // Dont allow distance + melee requirement - if (distance && allowedWeaponCategory !== "5b5f7a0886f77409407a7f96") - { + if (distance && allowedWeaponCategory !== "5b5f7a0886f77409407a7f96") { killConditionProps.distance = { compareMethod: ">=", value: distance }; } // Has specific weapon requirement - if (allowedWeapon) - { + if (allowedWeapon) { killConditionProps.weapon = [allowedWeapon]; } // Has specific weapon category requirement - if (allowedWeaponCategory?.length > 0) - { + if (allowedWeaponCategory?.length > 0) { // TODO - fix - does weaponCategories exist? // killConditionProps.weaponCategories = [allowedWeaponCategory]; } @@ -479,8 +443,7 @@ export class RepeatableQuestGenerator pmcLevel: number, traderId: string, repeatableConfig: IRepeatableQuestConfig, - ): IRepeatableQuest - { + ): IRepeatableQuest { const completionConfig = repeatableConfig.questConfig.Completion; const levelsConfig = repeatableConfig.rewardScaling.levels; const roublesConfig = repeatableConfig.rewardScaling.roubles; @@ -506,21 +469,18 @@ export class RepeatableQuestGenerator // We also have the option to use whitelist and/or blacklist which is defined in repeatableQuests.json as // [{"minPlayerLevel": 1, "itemIds": ["id1",...]}, {"minPlayerLevel": 15, "itemIds": ["id3",...]}] - if (repeatableConfig.questConfig.Completion.useWhitelist) - { - const itemWhitelist - = this.databaseService.getTemplates().repeatableQuests.data.Completion.itemsWhitelist; + if (repeatableConfig.questConfig.Completion.useWhitelist) { + const itemWhitelist = this.databaseService.getTemplates().repeatableQuests.data.Completion.itemsWhitelist; // Filter and concatenate the arrays according to current player level const itemIdsWhitelisted = itemWhitelist .filter((p) => p.minPlayerLevel <= pmcLevel) .reduce((a, p) => a.concat(p.itemIds), []); - itemSelection = itemSelection.filter((x) => - { + itemSelection = itemSelection.filter((x) => { // Whitelist can contain item tpls and item base type ids return ( - itemIdsWhitelisted.some((v) => this.itemHelper.isOfBaseclass(x[0], v)) - || itemIdsWhitelisted.includes(x[0]) + itemIdsWhitelisted.some((v) => this.itemHelper.isOfBaseclass(x[0], v)) || + itemIdsWhitelisted.includes(x[0]) ); }); // check if items are missing @@ -528,27 +488,23 @@ export class RepeatableQuestGenerator // const missing = itemIdsWhitelisted.filter(l => !flatList.includes(l)); } - if (repeatableConfig.questConfig.Completion.useBlacklist) - { - const itemBlacklist - = this.databaseService.getTemplates().repeatableQuests.data.Completion.itemsBlacklist; + if (repeatableConfig.questConfig.Completion.useBlacklist) { + const itemBlacklist = this.databaseService.getTemplates().repeatableQuests.data.Completion.itemsBlacklist; // we filter and concatenate the arrays according to current player level const itemIdsBlacklisted = itemBlacklist .filter((p) => p.minPlayerLevel <= pmcLevel) .reduce((a, p) => a.concat(p.itemIds), []); - itemSelection = itemSelection.filter((x) => - { + itemSelection = itemSelection.filter((x) => { return ( - itemIdsBlacklisted.every((v) => !this.itemHelper.isOfBaseclass(x[0], v)) - || !itemIdsBlacklisted.includes(x[0]) + itemIdsBlacklisted.every((v) => !this.itemHelper.isOfBaseclass(x[0], v)) || + !itemIdsBlacklisted.includes(x[0]) ); }); } - if (itemSelection.length === 0) - { + if (itemSelection.length === 0) { this.logger.error( this.localisationService.getText( "repeatable-completion_quest_whitelist_too_small_or_blacklist_too_restrictive", @@ -561,11 +517,9 @@ export class RepeatableQuestGenerator // Draw items to ask player to retrieve let isAmmo = 0; const randomNumbersUsed = []; - for (let i = 0; i < distinctItemsToRetrieveCount; i++) - { + for (let i = 0; i < distinctItemsToRetrieveCount; i++) { let randomNumber = this.randomUtil.randInt(itemSelection.length); - while (randomNumbersUsed.includes(randomNumber) && randomNumbersUsed.length !== itemSelection.length) - { + while (randomNumbersUsed.includes(randomNumber) && randomNumbersUsed.length !== itemSelection.length) { randomNumber = this.randomUtil.randInt(itemSelection.length); } @@ -575,11 +529,9 @@ export class RepeatableQuestGenerator const itemUnitPrice = this.itemHelper.getItemPrice(itemSelected[0]); let minValue = completionConfig.minRequestedAmount; let maxValue = completionConfig.maxRequestedAmount; - if (this.itemHelper.isOfBaseclass(itemSelected[0], BaseClasses.AMMO)) - { + if (this.itemHelper.isOfBaseclass(itemSelected[0], BaseClasses.AMMO)) { // Prevent multiple ammo requirements from being picked, stop after 6 attempts - if (isAmmo > 0 && isAmmo < 6) - { + if (isAmmo > 0 && isAmmo < 6) { isAmmo++; i--; continue; @@ -592,8 +544,7 @@ export class RepeatableQuestGenerator // get the value range within budget maxValue = Math.min(maxValue, Math.floor(roublesBudget / itemUnitPrice)); - if (maxValue > minValue) - { + if (maxValue > minValue) { // if it doesn't blow the budget we have for the request, draw a random amount of the selected // item type to be requested value = this.randomUtil.randInt(minValue, maxValue + 1); @@ -603,17 +554,13 @@ export class RepeatableQuestGenerator // push a CompletionCondition with the item and the amount of the item quest.conditions.AvailableForFinish.push(this.generateCompletionAvailableForFinish(itemSelected[0], value)); - if (roublesBudget > 0) - { + if (roublesBudget > 0) { // reduce the list possible items to fulfill the new budget constraint itemSelection = itemSelection.filter((x) => this.itemHelper.getItemPrice(x[0]) < roublesBudget); - if (itemSelection.length === 0) - { + if (itemSelection.length === 0) { break; } - } - else - { + } else { break; } } @@ -637,21 +584,18 @@ export class RepeatableQuestGenerator * @param {integer} value amount of items of this specific type to request * @returns {object} object of "Completion"-condition */ - protected generateCompletionAvailableForFinish(itemTpl: string, value: number): IQuestCondition - { + protected generateCompletionAvailableForFinish(itemTpl: string, value: number): IQuestCondition { let minDurability = 0; let onlyFoundInRaid = true; if ( - this.itemHelper.isOfBaseclass(itemTpl, BaseClasses.WEAPON) - || this.itemHelper.isOfBaseclass(itemTpl, BaseClasses.ARMOR) - ) - { + this.itemHelper.isOfBaseclass(itemTpl, BaseClasses.WEAPON) || + this.itemHelper.isOfBaseclass(itemTpl, BaseClasses.ARMOR) + ) { minDurability = this.randomUtil.getArrayValue([60, 80]); } // By default all collected items must be FiR, except dog tags - if (this.itemHelper.isDogtag(itemTpl)) - { + if (this.itemHelper.isDogtag(itemTpl)) { onlyFoundInRaid = false; } @@ -685,14 +629,12 @@ export class RepeatableQuestGenerator traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig, - ): IRepeatableQuest - { + ): IRepeatableQuest { const explorationConfig = repeatableConfig.questConfig.Exploration; - const requiresSpecificExtract - = Math.random() < repeatableConfig.questConfig.Exploration.specificExits.probability; + const requiresSpecificExtract = + Math.random() < repeatableConfig.questConfig.Exploration.specificExits.probability; - if (Object.keys(questTypePool.pool.Exploration.locations).length === 0) - { + if (Object.keys(questTypePool.pool.Exploration.locations).length === 0) { // there are no more locations left for exploration; delete it as a possible quest type questTypePool.types = questTypePool.types.filter((t) => t !== "Exploration"); return undefined; @@ -733,8 +675,7 @@ export class RepeatableQuestGenerator quest.conditions.AvailableForFinish[0].id = this.objectId.generate(); quest.location = this.getQuestLocationByMapId(locationKey); - if (requiresSpecificExtract) - { + if (requiresSpecificExtract) { // Fetch extracts for the requested side const mapExits = this.getLocationExitsForSide(locationKey, repeatableConfig.side); @@ -744,20 +685,17 @@ export class RepeatableQuestGenerator // Exclude exits with a requirement to leave (e.g. car extracts) const possibleExits = exitPool.filter( (exit) => - !("PassageRequirement" in exit) - || repeatableConfig.questConfig.Exploration.specificExits.passageRequirementWhitelist.includes( + !("PassageRequirement" in exit) || + repeatableConfig.questConfig.Exploration.specificExits.passageRequirementWhitelist.includes( exit.PassageRequirement, ), ); - if (possibleExits.length === 0) - { + if (possibleExits.length === 0) { this.logger.error( `Unable to choose specific exit on map: ${locationKey}, Possible exit pool was empty`, ); - } - else - { + } else { // Choose one of the exits we filtered above const chosenExit = this.randomUtil.drawRandomFromList(possibleExits, 1)[0]; @@ -787,11 +725,8 @@ export class RepeatableQuestGenerator * @param playerSide Scav/Pmc * @returns Array of Exit objects */ - protected getLocationExitsForSide(locationKey: string, playerSide: string): Exit[] - { - const mapExtracts = this.databaseService - .getLocation(locationKey.toLocaleLowerCase()) - .allExtracts; + protected getLocationExitsForSide(locationKey: string, playerSide: string): Exit[] { + const mapExtracts = this.databaseService.getLocation(locationKey.toLocaleLowerCase()).allExtracts; return mapExtracts.filter((exit) => exit.Side === playerSide); } @@ -801,8 +736,7 @@ export class RepeatableQuestGenerator traderId: string, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig, - ): IRepeatableQuest - { + ): IRepeatableQuest { const pickupConfig = repeatableConfig.questConfig.Pickup; const quest = this.generateRepeatableTemplate("Pickup", traderId, repeatableConfig.side); @@ -848,8 +782,7 @@ export class RepeatableQuestGenerator * @param locationKey e.g factory4_day * @returns guid */ - protected getQuestLocationByMapId(locationKey: string): string - { + protected getQuestLocationByMapId(locationKey: string): string { return this.questConfig.locationIdMap[locationKey]; } @@ -860,8 +793,7 @@ export class RepeatableQuestGenerator * @param {string} exit The exit name to generate the condition for * @returns {object} Exit condition */ - protected generateExplorationExitCondition(exit: Exit): IQuestConditionCounterCondition - { + protected generateExplorationExitCondition(exit: Exit): IQuestConditionCounterCondition { return { conditionType: "ExitName", exitName: exit.Name, id: this.objectId.generate(), dynamicLocale: true }; } @@ -876,8 +808,7 @@ export class RepeatableQuestGenerator * (needs to be filled with reward and conditions by called to make a valid quest) */ // @Incomplete: define Type for "type". - protected generateRepeatableTemplate(type: string, traderId: string, side: string): IRepeatableQuest - { + protected generateRepeatableTemplate(type: string, traderId: string, side: string): IRepeatableQuest { const questClone = this.cloner.clone( this.databaseService.getTemplates().repeatableQuests.templates[type], ); @@ -893,9 +824,7 @@ export class RepeatableQuestGenerator questClone.templateId = this.questConfig.questTemplateIds[side.toLowerCase()][type.toLowerCase()]; // Force REF templates to use prapors ID - solves missing text issue - const desiredTraderId = (traderId === Traders.REF) - ? Traders.PRAPOR - : traderId; + const desiredTraderId = traderId === Traders.REF ? Traders.PRAPOR : traderId; questClone.name = questClone.name .replace("{traderId}", traderId) diff --git a/project/src/generators/RepeatableQuestRewardGenerator.ts b/project/src/generators/RepeatableQuestRewardGenerator.ts index 079ec3ed..4e6cac65 100644 --- a/project/src/generators/RepeatableQuestRewardGenerator.ts +++ b/project/src/generators/RepeatableQuestRewardGenerator.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { HandbookHelper } from "@spt/helpers/HandbookHelper"; import { ItemHelper } from "@spt/helpers/ItemHelper"; import { PresetHelper } from "@spt/helpers/PresetHelper"; @@ -10,7 +9,12 @@ import { ConfigTypes } from "@spt/models/enums/ConfigTypes"; import { Money } from "@spt/models/enums/Money"; import { QuestRewardType } from "@spt/models/enums/QuestRewardType"; import { Traders } from "@spt/models/enums/Traders"; -import { IBaseQuestConfig, IQuestConfig, IRepeatableQuestConfig, IRewardScaling } from "@spt/models/spt/config/IQuestConfig"; +import { + IBaseQuestConfig, + IQuestConfig, + IRepeatableQuestConfig, + IRewardScaling, +} from "@spt/models/spt/config/IQuestConfig"; import { IQuestRewardValues } from "@spt/models/spt/repeatable/IQuestRewardValues"; import { ExhaustableArray } from "@spt/models/spt/server/ExhaustableArray"; import { ILogger } from "@spt/models/spt/utils/ILogger"; @@ -19,14 +23,14 @@ import { DatabaseService } from "@spt/services/DatabaseService"; import { ItemFilterService } from "@spt/services/ItemFilterService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { SeasonalEventService } from "@spt/services/SeasonalEventService"; -import { ICloner } from "@spt/utils/cloners/ICloner"; import { MathUtil } from "@spt/utils/MathUtil"; import { ObjectId } from "@spt/utils/ObjectId"; import { RandomUtil } from "@spt/utils/RandomUtil"; +import { ICloner } from "@spt/utils/cloners/ICloner"; +import { inject, injectable } from "tsyringe"; @injectable() -export class RepeatableQuestRewardGenerator -{ +export class RepeatableQuestRewardGenerator { protected questConfig: IQuestConfig; constructor( @@ -43,8 +47,7 @@ export class RepeatableQuestRewardGenerator @inject("SeasonalEventService") protected seasonalEventService: SeasonalEventService, @inject("ConfigServer") protected configServer: ConfigServer, @inject("PrimaryCloner") protected cloner: ICloner, - ) - { + ) { this.questConfig = this.configServer.getConfig(ConfigTypes.QUEST); } @@ -74,8 +77,7 @@ export class RepeatableQuestRewardGenerator traderId: string, repeatableConfig: IRepeatableQuestConfig, questConfig: IBaseQuestConfig, - ): IQuestRewards - { + ): IQuestRewards { // Get vars to configure rewards with const rewardParams = this.getQuestRewardValues(repeatableConfig.rewardScaling, difficulty, pmcLevel); @@ -89,9 +91,12 @@ export class RepeatableQuestRewardGenerator let rewardIndex = 0; // Add xp reward - if (rewardParams.rewardXP > 0) - { - rewards.Success.push({ value: rewardParams.rewardXP, type: QuestRewardType.EXPERIENCE, index: rewardIndex }); + if (rewardParams.rewardXP > 0) { + rewards.Success.push({ + value: rewardParams.rewardXP, + type: QuestRewardType.EXPERIENCE, + index: rewardIndex, + }); rewardIndex++; } @@ -100,24 +105,19 @@ export class RepeatableQuestRewardGenerator rewardIndex++; // Add GP coin reward - rewards.Success.push(this.generateItemReward( - Money.GP, - rewardParams.gpCoinRewardCount, - rewardIndex, - )); + rewards.Success.push(this.generateItemReward(Money.GP, rewardParams.gpCoinRewardCount, rewardIndex)); rewardIndex++; // Add preset weapon to reward if checks pass - const traderWhitelistDetails = repeatableConfig.traderWhitelist - .find((traderWhitelist) => traderWhitelist.traderId === traderId); + const traderWhitelistDetails = repeatableConfig.traderWhitelist.find( + (traderWhitelist) => traderWhitelist.traderId === traderId, + ); if ( - traderWhitelistDetails?.rewardCanBeWeapon - && this.randomUtil.getChance100(traderWhitelistDetails.weaponRewardChancePercent) - ) - { + traderWhitelistDetails?.rewardCanBeWeapon && + this.randomUtil.getChance100(traderWhitelistDetails.weaponRewardChancePercent) + ) { const chosenWeapon = this.getRandomWeaponPresetWithinBudget(itemRewardBudget, rewardIndex); - if (chosenWeapon) - { + if (chosenWeapon) { rewards.Success.push(chosenWeapon.weapon); // Subtract price of preset from item budget so we dont give player too much stuff @@ -130,8 +130,7 @@ export class RepeatableQuestRewardGenerator this.logger.debug( `Generating daily quest for: ${traderId} with budget: ${itemRewardBudget} totalling: ${rewardParams.rewardNumItems} items`, ); - if (inBudgetRewardItemPool.length > 0) - { + if (inBudgetRewardItemPool.length > 0) { const itemsToReward = this.getRewardableItemsFromPoolWithinBudget( inBudgetRewardItemPool, rewardParams.rewardNumItems, @@ -140,16 +139,14 @@ export class RepeatableQuestRewardGenerator ); // Add item rewards - for (const itemReward of itemsToReward) - { + for (const itemReward of itemsToReward) { rewards.Success.push(this.generateItemReward(itemReward.item._id, itemReward.stackSize, rewardIndex)); rewardIndex++; } } // Add rep reward to rewards array - if (rewardParams.rewardReputation > 0) - { + if (rewardParams.rewardReputation > 0) { const reward: IQuestReward = { target: traderId, value: rewardParams.rewardReputation, @@ -163,8 +160,7 @@ export class RepeatableQuestRewardGenerator } // Chance of adding skill reward - if (this.randomUtil.getChance100(rewardParams.skillRewardChance * 100)) - { + if (this.randomUtil.getChance100(rewardParams.skillRewardChance * 100)) { const targetSkill = this.randomUtil.getArrayValue(questConfig.possibleSkillRewards); const reward: IQuestReward = { target: targetSkill, @@ -183,8 +179,8 @@ export class RepeatableQuestRewardGenerator protected getQuestRewardValues( rewardScaling: IRewardScaling, difficulty: number, - pmcLevel: number): IQuestRewardValues - { + pmcLevel: number, + ): IQuestRewardValues { // difficulty could go from 0.2 ... -> for lowest difficulty receive 0.2*nominal reward const levelsConfig = rewardScaling.levels; const roublesConfig = rewardScaling.roubles; @@ -197,38 +193,39 @@ export class RepeatableQuestRewardGenerator const reputationConfig = rewardScaling.reputation; const effectiveDifficulty = Number.isNaN(difficulty) ? 1 : difficulty; - if (Number.isNaN(difficulty)) - { + if (Number.isNaN(difficulty)) { this.logger.warning(this.localisationService.getText("repeatable-difficulty_was_nan")); } return { skillPointReward: this.mathUtil.interp1(pmcLevel, levelsConfig, skillPointRewardConfig), skillRewardChance: this.mathUtil.interp1(pmcLevel, levelsConfig, skillRewardChanceConfig), - rewardReputation: Math.round( - 100 - * effectiveDifficulty - * this.mathUtil.interp1(pmcLevel, levelsConfig, reputationConfig) - * this.randomUtil.getFloat(1 - rewardSpreadConfig, 1 + rewardSpreadConfig), - ) / 100, + rewardReputation: + Math.round( + 100 * + effectiveDifficulty * + this.mathUtil.interp1(pmcLevel, levelsConfig, reputationConfig) * + this.randomUtil.getFloat(1 - rewardSpreadConfig, 1 + rewardSpreadConfig), + ) / 100, rewardNumItems: this.randomUtil.randInt( 1, Math.round(this.mathUtil.interp1(pmcLevel, levelsConfig, itemsConfig)) + 1, ), rewardRoubles: Math.floor( - effectiveDifficulty - * this.mathUtil.interp1(pmcLevel, levelsConfig, roublesConfig) - * this.randomUtil.getFloat(1 - rewardSpreadConfig, 1 + rewardSpreadConfig), + effectiveDifficulty * + this.mathUtil.interp1(pmcLevel, levelsConfig, roublesConfig) * + this.randomUtil.getFloat(1 - rewardSpreadConfig, 1 + rewardSpreadConfig), ), - gpCoinRewardCount: Math.ceil( // Ceil value to ensure it never drops below 1 - effectiveDifficulty - * this.mathUtil.interp1(pmcLevel, levelsConfig, gpCoinConfig) - * this.randomUtil.getFloat(1 - rewardSpreadConfig, 1 + rewardSpreadConfig), + gpCoinRewardCount: Math.ceil( + // Ceil value to ensure it never drops below 1 + effectiveDifficulty * + this.mathUtil.interp1(pmcLevel, levelsConfig, gpCoinConfig) * + this.randomUtil.getFloat(1 - rewardSpreadConfig, 1 + rewardSpreadConfig), ), rewardXP: Math.floor( - effectiveDifficulty - * this.mathUtil.interp1(pmcLevel, levelsConfig, xpConfig) - * this.randomUtil.getFloat(1 - rewardSpreadConfig, 1 + rewardSpreadConfig), + effectiveDifficulty * + this.mathUtil.interp1(pmcLevel, levelsConfig, xpConfig) * + this.randomUtil.getFloat(1 - rewardSpreadConfig, 1 + rewardSpreadConfig), ), }; } @@ -245,33 +242,25 @@ export class RepeatableQuestRewardGenerator itemPool: ITemplateItem[], maxItemCount: number, itemRewardBudget: number, - repeatableConfig: IRepeatableQuestConfig): { item: ITemplateItem, stackSize: number }[] - { - const itemsToReturn: { item: ITemplateItem, stackSize: number }[] = []; - let exhausableItemPool = new ExhaustableArray( - itemPool, - this.randomUtil, - this.cloner, - ); + repeatableConfig: IRepeatableQuestConfig, + ): { item: ITemplateItem; stackSize: number }[] { + const itemsToReturn: { item: ITemplateItem; stackSize: number }[] = []; + let exhausableItemPool = new ExhaustableArray(itemPool, this.randomUtil, this.cloner); - for (let i = 0; i < maxItemCount; i++) - { + for (let i = 0; i < maxItemCount; i++) { // Default stack size to 1 let rewardItemStackCount = 1; // Get a random item const chosenItemFromPool = exhausableItemPool.getRandomValue(); - if (!exhausableItemPool.hasValues()) - { + if (!exhausableItemPool.hasValues()) { break; } // Handle edge case - ammo - if (this.itemHelper.isOfBaseclass(chosenItemFromPool._id, BaseClasses.AMMO)) - { + if (this.itemHelper.isOfBaseclass(chosenItemFromPool._id, BaseClasses.AMMO)) { // Don't reward ammo that stacks to less than what's allowed in config - if (chosenItemFromPool._props.StackMaxSize < repeatableConfig.rewardAmmoStackMinSize) - { + if (chosenItemFromPool._props.StackMaxSize < repeatableConfig.rewardAmmoStackMinSize) { i--; continue; } @@ -286,8 +275,7 @@ export class RepeatableQuestRewardGenerator // 25% chance to double, triple or quadruple reward stack // (Only occurs when item is stackable and not weapon, armor or ammo) - if (this.canIncreaseRewardItemStackSize(chosenItemFromPool, 70000, 25)) - { + if (this.canIncreaseRewardItemStackSize(chosenItemFromPool, 70000, 25)) { rewardItemStackCount = this.getRandomisedRewardItemStackSizeByPrice(chosenItemFromPool); } @@ -298,8 +286,7 @@ export class RepeatableQuestRewardGenerator this.logger.debug(`Added item: ${chosenItemFromPool._id} with price: ${rewardItemStackCount * itemCost}`); // If we still have budget narrow down possible items - if (itemRewardBudget > 0) - { + if (itemRewardBudget > 0) { // Filter possible reward items to only items with a price below the remaining budget exhausableItemPool = new ExhaustableArray( this.filterRewardPoolWithinBudget(itemPool, itemRewardBudget, 0), @@ -307,8 +294,7 @@ export class RepeatableQuestRewardGenerator this.cloner, ); - if (!exhausableItemPool.hasValues()) - { + if (!exhausableItemPool.hasValues()) { this.logger.debug(`Reward pool empty with: ${itemRewardBudget} roubles of budget remaining`); break; // No reward items left, exit } @@ -330,8 +316,7 @@ export class RepeatableQuestRewardGenerator protected getRandomWeaponPresetWithinBudget( roublesBudget: number, rewardIndex: number, - ): { weapon: IQuestReward, price: number } | undefined - { + ): { weapon: IQuestReward; price: number } | undefined { // Add a random default preset weapon as reward const defaultPresetPool = new ExhaustableArray( Object.values(this.presetHelper.getDefaultWeaponPresets()), @@ -339,11 +324,9 @@ export class RepeatableQuestRewardGenerator this.cloner, ); - while (defaultPresetPool.hasValues()) - { + while (defaultPresetPool.hasValues()) { const randomPreset = defaultPresetPool.getRandomValue(); - if (!randomPreset) - { + if (!randomPreset) { continue; } @@ -352,14 +335,14 @@ export class RepeatableQuestRewardGenerator // Does preset items fit our budget const presetPrice = this.itemHelper.getItemAndChildrenPrice(tpls); - if (presetPrice <= roublesBudget) - { + if (presetPrice <= roublesBudget) { this.logger.debug(`Added weapon: ${tpls[0]} with price: ${presetPrice}`); const chosenPreset = this.cloner.clone(randomPreset); return { weapon: this.generatePresetReward(chosenPreset._encyclopedia, 1, rewardIndex, chosenPreset._items), - price: presetPrice }; + price: presetPrice, + }; } } @@ -376,10 +359,8 @@ export class RepeatableQuestRewardGenerator rewardItems: ITemplateItem[], roublesBudget: number, minPrice: number, - ): ITemplateItem[] - { - return rewardItems.filter((item) => - { + ): ITemplateItem[] { + return rewardItems.filter((item) => { const itemPrice = this.presetHelper.getDefaultPresetOrItemPrice(item._id); return itemPrice < roublesBudget && itemPrice > minPrice; }); @@ -390,17 +371,17 @@ export class RepeatableQuestRewardGenerator * @param item Reward item to get stack size for * @returns matching stack size for the passed in items price */ - protected getRandomisedRewardItemStackSizeByPrice(item: ITemplateItem): number - { + protected getRandomisedRewardItemStackSizeByPrice(item: ITemplateItem): number { const rewardItemPrice = this.presetHelper.getDefaultPresetOrItemPrice(item._id); // Define price tiers and corresponding stack size options const priceTiers: { - priceThreshold: number - stackSizes: number[] }[] = [ + priceThreshold: number; + stackSizes: number[]; + }[] = [ { priceThreshold: 3000, stackSizes: [2, 3, 4] }, { priceThreshold: 10000, stackSizes: [2, 3] }, - { priceThreshold: Infinity, stackSizes: [2] }, // Default for prices 10001+ RUB + { priceThreshold: Number.POSITIVE_INFINITY, stackSizes: [2] }, // Default for prices 10001+ RUB ]; // Find the appropriate price tier and return a random stack size from its options @@ -418,16 +399,16 @@ export class RepeatableQuestRewardGenerator protected canIncreaseRewardItemStackSize( item: ITemplateItem, maxRoublePriceToStack: number, - randomChanceToPass?: number): boolean - { - const isEligibleForStackSizeIncrease - = this.presetHelper.getDefaultPresetOrItemPrice(item._id) < maxRoublePriceToStack - && !this.itemHelper.isOfBaseclasses(item._id, [ + randomChanceToPass?: number, + ): boolean { + const isEligibleForStackSizeIncrease = + this.presetHelper.getDefaultPresetOrItemPrice(item._id) < maxRoublePriceToStack && + !this.itemHelper.isOfBaseclasses(item._id, [ BaseClasses.WEAPON, BaseClasses.ARMORED_EQUIPMENT, BaseClasses.AMMO, - ]) - && !this.itemHelper.itemRequiresSoftInserts(item._id); + ]) && + !this.itemHelper.itemRequiresSoftInserts(item._id); return isEligibleForStackSizeIncrease && this.randomUtil.getChance100(randomChanceToPass ?? 100); } @@ -444,8 +425,7 @@ export class RepeatableQuestRewardGenerator itemSelected: ITemplateItem, roublesBudget: number, rewardNumItems: number, - ): number - { + ): number { // Calculate budget per reward item const stackRoubleBudget = roublesBudget / rewardNumItems; @@ -472,8 +452,7 @@ export class RepeatableQuestRewardGenerator repeatableConfig: IRepeatableQuestConfig, roublesBudget: number, traderId: string, - ): ITemplateItem[] - { + ): ITemplateItem[] { // First filter for type and baseclass to avoid lookup in handbook for non-available items const rewardableItemPool = this.getRewardableItems(repeatableConfig, traderId); const minPrice = Math.min(25000, 0.5 * roublesBudget); @@ -484,8 +463,7 @@ export class RepeatableQuestRewardGenerator minPrice, ); - if (rewardableItemPoolWithinBudget.length === 0) - { + if (rewardableItemPoolWithinBudget.length === 0) { this.logger.warning( this.localisationService.getText("repeatable-no_reward_item_found_in_price_range", { minPrice: minPrice, @@ -510,15 +488,15 @@ export class RepeatableQuestRewardGenerator * @param preset Optional array of preset items * @returns {object} Object of "Reward"-item-type */ - protected generateItemReward(tpl: string, count: number, index: number): IQuestReward - { + protected generateItemReward(tpl: string, count: number, index: number): IQuestReward { const id = this.objectId.generate(); const questRewardItem: IQuestReward = { target: id, value: count, type: QuestRewardType.ITEM, index: index, - items: [] }; + items: [], + }; const rootItem = { _id: id, _tpl: tpl, upd: { StackObjectsCount: count, SpawnedInSession: true } }; questRewardItem.items = [rootItem]; @@ -535,20 +513,19 @@ export class RepeatableQuestRewardGenerator * @param preset Optional array of preset items * @returns {object} Object of "Reward"-item-type */ - protected generatePresetReward(tpl: string, count: number, index: number, preset?: Item[]): IQuestReward - { + protected generatePresetReward(tpl: string, count: number, index: number, preset?: Item[]): IQuestReward { const id = this.objectId.generate(); const questRewardItem: IQuestReward = { target: id, value: count, type: QuestRewardType.ITEM, index: index, - items: [] }; + items: [], + }; // Get presets root item const rootItem = preset.find((item) => item._tpl === tpl); - if (!rootItem) - { + if (!rootItem) { this.logger.warning(`Root item of preset: ${tpl} not found`); } @@ -571,34 +548,28 @@ export class RepeatableQuestRewardGenerator public getRewardableItems( repeatableQuestConfig: IRepeatableQuestConfig, traderId: string, - ): [string, ITemplateItem][] - { + ): [string, ITemplateItem][] { // Get an array of seasonal items that should not be shown right now as seasonal event is not active const seasonalItems = this.seasonalEventService.getInactiveSeasonalEventItems(); // Check for specific baseclasses which don't make sense as reward item // also check if the price is greater than 0; there are some items whose price can not be found // those are not in the game yet (e.g. AGS grenade launcher) - return Object.entries(this.databaseService.getItems()).filter( - ([tpl, itemTemplate]) => - { - // Base "Item" item has no parent, ignore it - if (itemTemplate._parent === "") - { - return false; - } + return Object.entries(this.databaseService.getItems()).filter(([tpl, itemTemplate]) => { + // Base "Item" item has no parent, ignore it + if (itemTemplate._parent === "") { + return false; + } - if (seasonalItems.includes(tpl)) - { - return false; - } + if (seasonalItems.includes(tpl)) { + return false; + } - const traderWhitelist = repeatableQuestConfig.traderWhitelist.find( - (trader) => trader.traderId === traderId, - ); - return this.isValidRewardItem(tpl, repeatableQuestConfig, traderWhitelist?.rewardBaseWhitelist); - }, - ); + const traderWhitelist = repeatableQuestConfig.traderWhitelist.find( + (trader) => trader.traderId === traderId, + ); + return this.isValidRewardItem(tpl, repeatableQuestConfig, traderWhitelist?.rewardBaseWhitelist); + }); } /** @@ -611,63 +582,48 @@ export class RepeatableQuestRewardGenerator tpl: string, repeatableQuestConfig: IRepeatableQuestConfig, itemBaseWhitelist: string[], - ): boolean - { + ): boolean { // Return early if not valid item to give as reward - if (!this.itemHelper.isValidItem(tpl)) - { + if (!this.itemHelper.isValidItem(tpl)) { return false; } // Check item is not blacklisted - if (this.itemFilterService.isItemBlacklisted(tpl) - || this.itemFilterService.isItemRewardBlacklisted(tpl) - || repeatableQuestConfig.rewardBlacklist.includes(tpl) - || this.itemFilterService.isItemBlacklisted(tpl)) - { + if ( + this.itemFilterService.isItemBlacklisted(tpl) || + this.itemFilterService.isItemRewardBlacklisted(tpl) || + repeatableQuestConfig.rewardBlacklist.includes(tpl) || + this.itemFilterService.isItemBlacklisted(tpl) + ) { return false; } // Item has blacklisted base types - if (this.itemHelper.isOfBaseclasses(tpl, [...repeatableQuestConfig.rewardBaseTypeBlacklist])) - { + if (this.itemHelper.isOfBaseclasses(tpl, [...repeatableQuestConfig.rewardBaseTypeBlacklist])) { return false; } // Skip boss items - if (this.itemFilterService.isBossItem(tpl)) - { + if (this.itemFilterService.isBossItem(tpl)) { return false; } // Trader has specific item base types they can give as rewards to player - if (itemBaseWhitelist !== undefined - && !this.itemHelper.isOfBaseclasses(tpl, [...itemBaseWhitelist])) - { + if (itemBaseWhitelist !== undefined && !this.itemHelper.isOfBaseclasses(tpl, [...itemBaseWhitelist])) { return false; } return true; } - protected getMoneyReward( - traderId: string, - rewardRoubles: number, - rewardIndex: number, - ): IQuestReward - { + protected getMoneyReward(traderId: string, rewardRoubles: number, rewardIndex: number): IQuestReward { // Determine currency based on trader // PK and Fence use Euros, everyone else is Roubles - const currency - = traderId === Traders.PEACEKEEPER || traderId === Traders.FENCE - ? Money.EUROS - : Money.ROUBLES; + const currency = traderId === Traders.PEACEKEEPER || traderId === Traders.FENCE ? Money.EUROS : Money.ROUBLES; // Convert reward amount to Euros if necessary - const rewardAmountToGivePlayer - = currency === Money.EUROS - ? this.handbookHelper.fromRUB(rewardRoubles, Money.EUROS) - : rewardRoubles; + const rewardAmountToGivePlayer = + currency === Money.EUROS ? this.handbookHelper.fromRUB(rewardRoubles, Money.EUROS) : rewardRoubles; // Get chosen currency + amount and return return this.generateItemReward(currency, rewardAmountToGivePlayer, rewardIndex); diff --git a/project/src/generators/ScavCaseRewardGenerator.ts b/project/src/generators/ScavCaseRewardGenerator.ts index b0a55d66..9f46bcb1 100644 --- a/project/src/generators/ScavCaseRewardGenerator.ts +++ b/project/src/generators/ScavCaseRewardGenerator.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { ItemHelper } from "@spt/helpers/ItemHelper"; import { PresetHelper } from "@spt/helpers/PresetHelper"; import { Item } from "@spt/models/eft/common/tables/IItem"; @@ -20,13 +19,13 @@ import { RagfairPriceService } from "@spt/services/RagfairPriceService"; import { SeasonalEventService } from "@spt/services/SeasonalEventService"; import { HashUtil } from "@spt/utils/HashUtil"; import { RandomUtil } from "@spt/utils/RandomUtil"; +import { inject, injectable } from "tsyringe"; /** * Handle the creation of randomised scav case rewards */ @injectable() -export class ScavCaseRewardGenerator -{ +export class ScavCaseRewardGenerator { protected scavCaseConfig: IScavCaseConfig; protected dbItemsCache: ITemplateItem[]; protected dbAmmoItemsCache: ITemplateItem[]; @@ -42,8 +41,7 @@ export class ScavCaseRewardGenerator @inject("SeasonalEventService") protected seasonalEventService: SeasonalEventService, @inject("ItemFilterService") protected itemFilterService: ItemFilterService, @inject("ConfigServer") protected configServer: ConfigServer, - ) - { + ) { this.scavCaseConfig = this.configServer.getConfig(ConfigTypes.SCAVCASE); } @@ -52,8 +50,7 @@ export class ScavCaseRewardGenerator * @param recipeId recipe of the scav case craft * @returns Product array */ - public generate(recipeId: string): Item[][] - { + public generate(recipeId: string): Item[][] { this.cacheDbItems(); // Get scavcase details from hideout/scavcase.json @@ -90,61 +87,50 @@ export class ScavCaseRewardGenerator * Get all db items that are not blacklisted in scavcase config or global blacklist * Store in class field */ - protected cacheDbItems(): void - { + protected cacheDbItems(): void { // TODO: pre-loop and get array of valid items, e.g. non-node/non-blacklisted, then loop over those results for below code // Get an array of seasonal items that should not be shown right now as seasonal event is not active const inactiveSeasonalItems = this.seasonalEventService.getInactiveSeasonalEventItems(); - if (!this.dbItemsCache) - { - this.dbItemsCache = Object.values(this.databaseService.getItems()).filter((item) => - { + if (!this.dbItemsCache) { + this.dbItemsCache = Object.values(this.databaseService.getItems()).filter((item) => { // Base "Item" item has no parent, ignore it - if (item._parent === "") - { + if (item._parent === "") { return false; } - if (item._type === "Node") - { + if (item._type === "Node") { return false; } - if (item._props.QuestItem) - { + if (item._props.QuestItem) { return false; } // Skip item if item id is on blacklist if ( - item._type !== "Item" - || this.scavCaseConfig.rewardItemBlacklist.includes(item._id) - || this.itemFilterService.isItemBlacklisted(item._id) - ) - { + item._type !== "Item" || + this.scavCaseConfig.rewardItemBlacklist.includes(item._id) || + this.itemFilterService.isItemBlacklisted(item._id) + ) { return false; } // Globally reward-blacklisted - if (this.itemFilterService.isItemRewardBlacklisted(item._id)) - { + if (this.itemFilterService.isItemRewardBlacklisted(item._id)) { return false; } - if (!this.scavCaseConfig.allowBossItemsAsRewards && this.itemFilterService.isBossItem(item._id)) - { + if (!this.scavCaseConfig.allowBossItemsAsRewards && this.itemFilterService.isBossItem(item._id)) { return false; } // Skip item if parent id is blacklisted - if (this.itemHelper.isOfBaseclasses(item._id, this.scavCaseConfig.rewardItemParentBlacklist)) - { + if (this.itemHelper.isOfBaseclasses(item._id, this.scavCaseConfig.rewardItemParentBlacklist)) { return false; } - if (inactiveSeasonalItems.includes(item._id)) - { + if (inactiveSeasonalItems.includes(item._id)) { return false; } @@ -152,56 +138,46 @@ export class ScavCaseRewardGenerator }); } - if (!this.dbAmmoItemsCache) - { - this.dbAmmoItemsCache = Object.values(this.databaseService.getItems()).filter((item) => - { + if (!this.dbAmmoItemsCache) { + this.dbAmmoItemsCache = Object.values(this.databaseService.getItems()).filter((item) => { // Base "Item" item has no parent, ignore it - if (item._parent === "") - { + if (item._parent === "") { return false; } - if (item._type !== "Item") - { + if (item._type !== "Item") { return false; } // Not ammo, skip - if (!this.itemHelper.isOfBaseclass(item._id, BaseClasses.AMMO)) - { + if (!this.itemHelper.isOfBaseclass(item._id, BaseClasses.AMMO)) { return false; } // Skip item if item id is on blacklist if ( - this.scavCaseConfig.rewardItemBlacklist.includes(item._id) - || this.itemFilterService.isItemBlacklisted(item._id) - ) - { + this.scavCaseConfig.rewardItemBlacklist.includes(item._id) || + this.itemFilterService.isItemBlacklisted(item._id) + ) { return false; } // Globally reward-blacklisted - if (this.itemFilterService.isItemRewardBlacklisted(item._id)) - { + if (this.itemFilterService.isItemRewardBlacklisted(item._id)) { return false; } - if (!this.scavCaseConfig.allowBossItemsAsRewards && this.itemFilterService.isBossItem(item._id)) - { + if (!this.scavCaseConfig.allowBossItemsAsRewards && this.itemFilterService.isBossItem(item._id)) { return false; } // Skip seasonal items - if (inactiveSeasonalItems.includes(item._id)) - { + if (inactiveSeasonalItems.includes(item._id)) { return false; } // Skip ammo that doesn't stack as high as value in config - if (item._props.StackMaxSize < this.scavCaseConfig.ammoRewards.minStackSize) - { + if (item._props.StackMaxSize < this.scavCaseConfig.ammoRewards.minStackSize) { return false; } @@ -220,35 +196,26 @@ export class ScavCaseRewardGenerator items: ITemplateItem[], itemFilters: RewardCountAndPriceDetails, rarity: string, - ): ITemplateItem[] - { + ): ITemplateItem[] { const result: ITemplateItem[] = []; let rewardWasMoney = false; let rewardWasAmmo = false; const randomCount = this.randomUtil.getInt(itemFilters.minCount, itemFilters.maxCount); - for (let i = 0; i < randomCount; i++) - { - if (this.rewardShouldBeMoney() && !rewardWasMoney) - { + for (let i = 0; i < randomCount; i++) { + if (this.rewardShouldBeMoney() && !rewardWasMoney) { // Only allow one reward to be money result.push(this.getRandomMoney()); - if (!this.scavCaseConfig.allowMultipleMoneyRewardsPerRarity) - { + if (!this.scavCaseConfig.allowMultipleMoneyRewardsPerRarity) { rewardWasMoney = true; } - } - else if (this.rewardShouldBeAmmo() && !rewardWasAmmo) - { + } else if (this.rewardShouldBeAmmo() && !rewardWasAmmo) { // Only allow one reward to be ammo result.push(this.getRandomAmmo(rarity)); - if (!this.scavCaseConfig.allowMultipleAmmoRewardsPerRarity) - { + if (!this.scavCaseConfig.allowMultipleAmmoRewardsPerRarity) { rewardWasAmmo = true; } - } - else - { + } else { result.push(this.randomUtil.getArrayValue(items)); } } @@ -260,8 +227,7 @@ export class ScavCaseRewardGenerator * Choose if money should be a reward based on the moneyRewardChancePercent config chance in scavCaseConfig * @returns true if reward should be money */ - protected rewardShouldBeMoney(): boolean - { + protected rewardShouldBeMoney(): boolean { return this.randomUtil.getChance100(this.scavCaseConfig.moneyRewards.moneyRewardChancePercent); } @@ -269,16 +235,14 @@ export class ScavCaseRewardGenerator * Choose if ammo should be a reward based on the ammoRewardChancePercent config chance in scavCaseConfig * @returns true if reward should be ammo */ - protected rewardShouldBeAmmo(): boolean - { + protected rewardShouldBeAmmo(): boolean { return this.randomUtil.getChance100(this.scavCaseConfig.ammoRewards.ammoRewardChancePercent); } /** * Choose from rouble/dollar/euro at random */ - protected getRandomMoney(): ITemplateItem - { + protected getRandomMoney(): ITemplateItem { const money: ITemplateItem[] = []; const items = this.databaseService.getItems(); money.push(items[Money.ROUBLES]); @@ -294,25 +258,21 @@ export class ScavCaseRewardGenerator * @param rarity The rarity this ammo reward is for * @returns random ammo item from items.json */ - protected getRandomAmmo(rarity: string): ITemplateItem - { - const possibleAmmoPool = this.dbAmmoItemsCache.filter((ammo) => - { + protected getRandomAmmo(rarity: string): ITemplateItem { + const possibleAmmoPool = this.dbAmmoItemsCache.filter((ammo) => { // Is ammo handbook price between desired range const handbookPrice = this.ragfairPriceService.getStaticPriceForItem(ammo._id); if ( - handbookPrice >= this.scavCaseConfig.ammoRewards.ammoRewardValueRangeRub[rarity].min - && handbookPrice <= this.scavCaseConfig.ammoRewards.ammoRewardValueRangeRub[rarity].max - ) - { + handbookPrice >= this.scavCaseConfig.ammoRewards.ammoRewardValueRangeRub[rarity].min && + handbookPrice <= this.scavCaseConfig.ammoRewards.ammoRewardValueRangeRub[rarity].max + ) { return true; } return false; }); - if (possibleAmmoPool.length === 0) - { + if (possibleAmmoPool.length === 0) { this.logger.warning("Unable to get a list of ammo that matches desired criteria for scav case reward"); } @@ -326,28 +286,23 @@ export class ScavCaseRewardGenerator * @param rewardItems items to convert * @returns Product array */ - protected randomiseContainerItemRewards(rewardItems: ITemplateItem[], rarity: string): Item[][] - { + protected randomiseContainerItemRewards(rewardItems: ITemplateItem[], rarity: string): Item[][] { /** Each array is an item + children */ const result: Item[][] = []; - for (const rewardItemDb of rewardItems) - { + for (const rewardItemDb of rewardItems) { let resultItem: Item[] = [{ _id: this.hashUtil.generate(), _tpl: rewardItemDb._id, upd: undefined }]; const rootItem = resultItem[0]; - if (this.itemHelper.isOfBaseclass(rewardItemDb._id, BaseClasses.AMMO_BOX)) - { + if (this.itemHelper.isOfBaseclass(rewardItemDb._id, BaseClasses.AMMO_BOX)) { this.itemHelper.addCartridgesToAmmoBox(resultItem, rewardItemDb); } // Armor or weapon = use default preset from globals.json else if ( - this.itemHelper.armorItemHasRemovableOrSoftInsertSlots(rewardItemDb._id) - || this.itemHelper.isOfBaseclass(rewardItemDb._id, BaseClasses.WEAPON) - ) - { + this.itemHelper.armorItemHasRemovableOrSoftInsertSlots(rewardItemDb._id) || + this.itemHelper.isOfBaseclass(rewardItemDb._id, BaseClasses.WEAPON) + ) { const preset = this.presetHelper.getDefaultPreset(rewardItemDb._id); - if (!preset) - { + if (!preset) { this.logger.warning(`No preset for item: ${rewardItemDb._id} ${rewardItemDb._name}, skipping`); continue; @@ -358,15 +313,12 @@ export class ScavCaseRewardGenerator this.itemHelper.remapRootItemId(presetAndMods); resultItem = presetAndMods; - } - else if (this.itemHelper.isOfBaseclasses(rewardItemDb._id, [BaseClasses.AMMO, BaseClasses.MONEY])) - { + } else if (this.itemHelper.isOfBaseclasses(rewardItemDb._id, [BaseClasses.AMMO, BaseClasses.MONEY])) { rootItem.upd = { StackObjectsCount: this.getRandomAmountRewardForScavCase(rewardItemDb, rarity) }; } // Clean up upd object if it wasn't used - if (!rootItem.upd) - { + if (!rootItem.upd) { delete rootItem.upd; } @@ -384,13 +336,10 @@ export class ScavCaseRewardGenerator protected getFilteredItemsByPrice( dbItems: ITemplateItem[], itemFilters: RewardCountAndPriceDetails, - ): ITemplateItem[] - { - return dbItems.filter((item) => - { + ): ITemplateItem[] { + return dbItems.filter((item) => { const handbookPrice = this.ragfairPriceService.getStaticPriceForItem(item._id); - if (handbookPrice >= itemFilters.minPriceRub && handbookPrice <= itemFilters.maxPriceRub) - { + if (handbookPrice >= itemFilters.minPriceRub && handbookPrice <= itemFilters.maxPriceRub) { return true; } }); @@ -401,14 +350,12 @@ export class ScavCaseRewardGenerator * @param scavCaseDetails scavcase.json values * @returns ScavCaseRewardCountsAndPrices object */ - protected getScavCaseRewardCountsAndPrices(scavCaseDetails: IHideoutScavCase): ScavCaseRewardCountsAndPrices - { + protected getScavCaseRewardCountsAndPrices(scavCaseDetails: IHideoutScavCase): ScavCaseRewardCountsAndPrices { const rewardTypes = Object.keys(scavCaseDetails.EndProducts) as Array; // Default is ["Common", "Rare", "Superrare"]; const result: Partial = {}; // Make partial object as we're going to add all the data immediately after // Create reward min/max counts for each type - for (const rewardType of rewardTypes) - { + for (const rewardType of rewardTypes) { result[rewardType] = { minCount: scavCaseDetails.EndProducts[rewardType].min, maxCount: scavCaseDetails.EndProducts[rewardType].max, @@ -426,20 +373,15 @@ export class ScavCaseRewardGenerator * @param rarity rarity (common/rare/superrare) * @returns value to set stack count to */ - protected getRandomAmountRewardForScavCase(itemToCalculate: ITemplateItem, rarity: string): number - { + protected getRandomAmountRewardForScavCase(itemToCalculate: ITemplateItem, rarity: string): number { let amountToGive = 1; - if (itemToCalculate._parent === BaseClasses.AMMO) - { + if (itemToCalculate._parent === BaseClasses.AMMO) { amountToGive = this.randomUtil.getInt( this.scavCaseConfig.ammoRewards.minStackSize, itemToCalculate._props.StackMaxSize, ); - } - else if (itemToCalculate._parent === BaseClasses.MONEY) - { - switch (itemToCalculate._id) - { + } else if (itemToCalculate._parent === BaseClasses.MONEY) { + switch (itemToCalculate._id) { case Money.ROUBLES: amountToGive = this.randomUtil.getInt( this.scavCaseConfig.moneyRewards.rubCount[rarity].min, diff --git a/project/src/generators/WeatherGenerator.ts b/project/src/generators/WeatherGenerator.ts index f2e57f01..302a633b 100644 --- a/project/src/generators/WeatherGenerator.ts +++ b/project/src/generators/WeatherGenerator.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { ApplicationContext } from "@spt/context/ApplicationContext"; import { WeightedRandomHelper } from "@spt/helpers/WeightedRandomHelper"; import { IWeather, IWeatherData } from "@spt/models/eft/weather/IWeatherData"; @@ -10,10 +9,10 @@ import { ConfigServer } from "@spt/servers/ConfigServer"; import { SeasonalEventService } from "@spt/services/SeasonalEventService"; import { RandomUtil } from "@spt/utils/RandomUtil"; import { TimeUtil } from "@spt/utils/TimeUtil"; +import { inject, injectable } from "tsyringe"; @injectable() -export class WeatherGenerator -{ +export class WeatherGenerator { protected weatherConfig: IWeatherConfig; // Note: If this value gets save/load support, raid time could be tracked across server restarts @@ -28,8 +27,7 @@ export class WeatherGenerator @inject("SeasonalEventService") protected seasonalEventService: SeasonalEventService, @inject("ApplicationContext") protected applicationContext: ApplicationContext, @inject("ConfigServer") protected configServer: ConfigServer, - ) - { + ) { this.weatherConfig = this.configServer.getConfig(ConfigTypes.WEATHER); } @@ -38,8 +36,7 @@ export class WeatherGenerator * @param data Weather data * @returns IWeatherData */ - public calculateGameTime(data: IWeatherData): IWeatherData - { + public calculateGameTime(data: IWeatherData): IWeatherData { const computedDate = new Date(); const formattedDate = this.timeUtil.formatDate(computedDate); @@ -60,8 +57,7 @@ export class WeatherGenerator * @param currentDate current date * @returns formatted time */ - protected getBsgFormattedInRaidTime(): string - { + protected getBsgFormattedInRaidTime(): string { const clientAcceleratedDate = this.getInRaidTime(); return this.getBSGFormattedTime(clientAcceleratedDate); @@ -72,13 +68,12 @@ export class WeatherGenerator * @param currentDate (new Date()) * @returns Date object of current in-raid time */ - public getInRaidTime(): Date - { + public getInRaidTime(): Date { // tarkov time = (real time * 7 % 24 hr) + 3 hour const russiaOffset = this.timeUtil.getHoursAsSeconds(3) * 1000; return new Date( - (russiaOffset + new Date().getTime() * this.weatherConfig.acceleration) - % (this.timeUtil.getHoursAsSeconds(24) * 1000), + (russiaOffset + new Date().getTime() * this.weatherConfig.acceleration) % + (this.timeUtil.getHoursAsSeconds(24) * 1000), ); } @@ -87,8 +82,7 @@ export class WeatherGenerator * @param date date to format into bsg style * @returns Time formatted in BSG format */ - protected getBSGFormattedTime(date: Date): string - { + protected getBSGFormattedTime(date: Date): string { return this.timeUtil.formatTime(date).replace("-", ":").replace("-", ":"); } @@ -96,8 +90,7 @@ export class WeatherGenerator * Return randomised Weather data with help of config/weather.json * @returns Randomised weather data */ - public generateWeather(): IWeather - { + public generateWeather(): IWeather { const rain = this.getWeightedRain(); const result: IWeather = { @@ -124,8 +117,7 @@ export class WeatherGenerator * Set IWeather date/time/timestamp values to now * @param weather Object to update */ - protected setCurrentDateTime(weather: IWeather): void - { + protected setCurrentDateTime(weather: IWeather): void { const currentDate = this.getInRaidTime(); const normalTime = this.getBSGFormattedTime(currentDate); const formattedDate = this.timeUtil.formatDate(currentDate); @@ -136,48 +128,42 @@ export class WeatherGenerator weather.time = datetime; // matches weather.timestamp } - protected getWeightedWindDirection(): WindDirection - { + protected getWeightedWindDirection(): WindDirection { return this.weightedRandomHelper.weightedRandom( this.weatherConfig.weather.windDirection.values, this.weatherConfig.weather.windDirection.weights, ).item; } - protected getWeightedClouds(): number - { + protected getWeightedClouds(): number { return this.weightedRandomHelper.weightedRandom( this.weatherConfig.weather.clouds.values, this.weatherConfig.weather.clouds.weights, ).item; } - protected getWeightedWindSpeed(): number - { + protected getWeightedWindSpeed(): number { return this.weightedRandomHelper.weightedRandom( this.weatherConfig.weather.windSpeed.values, this.weatherConfig.weather.windSpeed.weights, ).item; } - protected getWeightedFog(): number - { + protected getWeightedFog(): number { return this.weightedRandomHelper.weightedRandom( this.weatherConfig.weather.fog.values, this.weatherConfig.weather.fog.weights, ).item; } - protected getWeightedRain(): number - { + protected getWeightedRain(): number { return this.weightedRandomHelper.weightedRandom( this.weatherConfig.weather.rain.values, this.weatherConfig.weather.rain.weights, ).item; } - protected getRandomFloat(node: string): number - { + protected getRandomFloat(node: string): number { return Number.parseFloat( this.randomUtil .getFloat(this.weatherConfig.weather[node].min, this.weatherConfig.weather[node].max) diff --git a/project/src/generators/weapongen/IInventoryMagGen.ts b/project/src/generators/weapongen/IInventoryMagGen.ts index e2edfe3d..2a6f3ec8 100644 --- a/project/src/generators/weapongen/IInventoryMagGen.ts +++ b/project/src/generators/weapongen/IInventoryMagGen.ts @@ -1,8 +1,7 @@ import { InventoryMagGen } from "@spt/generators/weapongen/InventoryMagGen"; -export interface IInventoryMagGen -{ - getPriority(): number - canHandleInventoryMagGen(inventoryMagGen: InventoryMagGen): boolean - process(inventoryMagGen: InventoryMagGen): void +export interface IInventoryMagGen { + getPriority(): number; + canHandleInventoryMagGen(inventoryMagGen: InventoryMagGen): boolean; + process(inventoryMagGen: InventoryMagGen): void; } diff --git a/project/src/generators/weapongen/InventoryMagGen.ts b/project/src/generators/weapongen/InventoryMagGen.ts index 3df71c4e..03a7f8bd 100644 --- a/project/src/generators/weapongen/InventoryMagGen.ts +++ b/project/src/generators/weapongen/InventoryMagGen.ts @@ -2,39 +2,32 @@ import { Inventory } from "@spt/models/eft/common/tables/IBotBase"; import { GenerationData } from "@spt/models/eft/common/tables/IBotType"; import { ITemplateItem } from "@spt/models/eft/common/tables/ITemplateItem"; -export class InventoryMagGen -{ +export class InventoryMagGen { constructor( private magCounts: GenerationData, private magazineTemplate: ITemplateItem, private weaponTemplate: ITemplateItem, private ammoTemplate: ITemplateItem, private pmcInventory: Inventory, - ) - {} + ) {} - public getMagCount(): GenerationData - { + public getMagCount(): GenerationData { return this.magCounts; } - public getMagazineTemplate(): ITemplateItem - { + public getMagazineTemplate(): ITemplateItem { return this.magazineTemplate; } - public getWeaponTemplate(): ITemplateItem - { + public getWeaponTemplate(): ITemplateItem { return this.weaponTemplate; } - public getAmmoTemplate(): ITemplateItem - { + public getAmmoTemplate(): ITemplateItem { return this.ammoTemplate; } - public getPmcInventory(): Inventory - { + public getPmcInventory(): Inventory { return this.pmcInventory; } } diff --git a/project/src/generators/weapongen/implementations/BarrelInventoryMagGen.ts b/project/src/generators/weapongen/implementations/BarrelInventoryMagGen.ts index eced6be8..96b2f72c 100644 --- a/project/src/generators/weapongen/implementations/BarrelInventoryMagGen.ts +++ b/project/src/generators/weapongen/implementations/BarrelInventoryMagGen.ts @@ -1,39 +1,31 @@ -import { inject, injectable } from "tsyringe"; import { IInventoryMagGen } from "@spt/generators/weapongen/IInventoryMagGen"; import { InventoryMagGen } from "@spt/generators/weapongen/InventoryMagGen"; import { BotWeaponGeneratorHelper } from "@spt/helpers/BotWeaponGeneratorHelper"; import { RandomUtil } from "@spt/utils/RandomUtil"; +import { inject, injectable } from "tsyringe"; @injectable() -export class BarrelInventoryMagGen implements IInventoryMagGen -{ +export class BarrelInventoryMagGen implements IInventoryMagGen { constructor( @inject("RandomUtil") protected randomUtil: RandomUtil, @inject("BotWeaponGeneratorHelper") protected botWeaponGeneratorHelper: BotWeaponGeneratorHelper, - ) - {} + ) {} - getPriority(): number - { + getPriority(): number { return 50; } - canHandleInventoryMagGen(inventoryMagGen: InventoryMagGen): boolean - { + canHandleInventoryMagGen(inventoryMagGen: InventoryMagGen): boolean { return inventoryMagGen.getWeaponTemplate()._props.ReloadMode === "OnlyBarrel"; } - process(inventoryMagGen: InventoryMagGen): void - { + process(inventoryMagGen: InventoryMagGen): void { // Can't be done by _props.ammoType as grenade launcher shoots grenades with ammoType of "buckshot" let randomisedAmmoStackSize: number; - if (inventoryMagGen.getAmmoTemplate()._props.StackMaxRandom === 1) - { + if (inventoryMagGen.getAmmoTemplate()._props.StackMaxRandom === 1) { // doesnt stack randomisedAmmoStackSize = this.randomUtil.getInt(3, 6); - } - else - { + } else { randomisedAmmoStackSize = this.randomUtil.getInt( inventoryMagGen.getAmmoTemplate()._props.StackMinRandom, inventoryMagGen.getAmmoTemplate()._props.StackMaxRandom, diff --git a/project/src/generators/weapongen/implementations/ExternalInventoryMagGen.ts b/project/src/generators/weapongen/implementations/ExternalInventoryMagGen.ts index 0722644b..9ce8b221 100644 --- a/project/src/generators/weapongen/implementations/ExternalInventoryMagGen.ts +++ b/project/src/generators/weapongen/implementations/ExternalInventoryMagGen.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { IInventoryMagGen } from "@spt/generators/weapongen/IInventoryMagGen"; import { InventoryMagGen } from "@spt/generators/weapongen/InventoryMagGen"; import { BotGeneratorHelper } from "@spt/helpers/BotGeneratorHelper"; @@ -10,10 +9,10 @@ import { ItemAddedResult } from "@spt/models/enums/ItemAddedResult"; import { ILogger } from "@spt/models/spt/utils/ILogger"; import { LocalisationService } from "@spt/services/LocalisationService"; import { RandomUtil } from "@spt/utils/RandomUtil"; +import { inject, injectable } from "tsyringe"; @injectable() -export class ExternalInventoryMagGen implements IInventoryMagGen -{ +export class ExternalInventoryMagGen implements IInventoryMagGen { constructor( @inject("PrimaryLogger") protected logger: ILogger, @inject("ItemHelper") protected itemHelper: ItemHelper, @@ -21,21 +20,17 @@ export class ExternalInventoryMagGen implements IInventoryMagGen @inject("BotWeaponGeneratorHelper") protected botWeaponGeneratorHelper: BotWeaponGeneratorHelper, @inject("BotGeneratorHelper") protected botGeneratorHelper: BotGeneratorHelper, @inject("RandomUtil") protected randomUtil: RandomUtil, - ) - {} + ) {} - getPriority(): number - { + getPriority(): number { return 99; } - canHandleInventoryMagGen(inventoryMagGen: InventoryMagGen): boolean - { + canHandleInventoryMagGen(inventoryMagGen: InventoryMagGen): boolean { return true; // Fallback, if code reaches here it means no other implementation can handle this type of magazine } - process(inventoryMagGen: InventoryMagGen): void - { + process(inventoryMagGen: InventoryMagGen): void { // Cout of attempts to fit a magazine into bot inventory let fitAttempts = 0; @@ -48,8 +43,7 @@ export class ExternalInventoryMagGen implements IInventoryMagGen const randomizedMagazineCount = Number( this.botWeaponGeneratorHelper.getRandomizedMagazineCount(inventoryMagGen.getMagCount()), ); - for (let i = 0; i < randomizedMagazineCount; i++) - { + for (let i = 0; i < randomizedMagazineCount; i++) { const magazineWithAmmo = this.botWeaponGeneratorHelper.createMagazineWithAmmo( magazineTpl, inventoryMagGen.getAmmoTemplate()._id, @@ -64,18 +58,15 @@ export class ExternalInventoryMagGen implements IInventoryMagGen inventoryMagGen.getPmcInventory(), ); - if (fitsIntoInventory === ItemAddedResult.NO_CONTAINERS) - { + if (fitsIntoInventory === ItemAddedResult.NO_CONTAINERS) { // No containers to fit magazines, stop trying break; } // No space for magazine and we haven't reached desired magazine count - if (fitsIntoInventory === ItemAddedResult.NO_SPACE && i < randomizedMagazineCount) - { + if (fitsIntoInventory === ItemAddedResult.NO_SPACE && i < randomizedMagazineCount) { // Prevent infinite loop by only allowing 5 attempts at fitting a magazine into inventory - if (fitAttempts > 5) - { + if (fitAttempts > 5) { this.logger.debug( `Failed ${fitAttempts} times to add magazine ${magazineTpl} to bot inventory, stopping`, ); @@ -87,8 +78,7 @@ export class ExternalInventoryMagGen implements IInventoryMagGen * so we fallback to default magazine and try again. * Temporary workaround to Killa spawning with no extra mags if he spawns with a drum mag */ - if (magazineTpl === defaultMagazineTpl) - { + if (magazineTpl === defaultMagazineTpl) { // We were already on default - stop here to prevent infinite looping break; } @@ -99,8 +89,7 @@ export class ExternalInventoryMagGen implements IInventoryMagGen // Set chosen magazine tpl to the weapons default magazine tpl and try to fit into inventory next loop magazineTpl = defaultMagazineTpl; magTemplate = this.itemHelper.getItem(magazineTpl)[1]; - if (!magTemplate) - { + if (!magTemplate) { this.logger.error( this.localisationService.getText("bot-unable_to_find_default_magazine_item", magazineTpl), ); @@ -109,14 +98,12 @@ export class ExternalInventoryMagGen implements IInventoryMagGen } // Edge case - some weapons (SKS) have an internal magazine as default, choose random non-internal magazine to add to bot instead - if (magTemplate._props.ReloadMagType === "InternalMagazine") - { + if (magTemplate._props.ReloadMagType === "InternalMagazine") { const result = this.getRandomExternalMagazineForInternalMagazineGun( inventoryMagGen.getWeaponTemplate()._id, attemptedMagBlacklist, ); - if (!result?._id) - { + if (!result?._id) { this.logger.debug( `Unable to add additional magazine into bot inventory for weapon: ${weapon._name}, attempted: ${fitAttempts} times`, ); @@ -133,8 +120,7 @@ export class ExternalInventoryMagGen implements IInventoryMagGen i--; } - if (fitsIntoInventory === ItemAddedResult.SUCCESS) - { + if (fitsIntoInventory === ItemAddedResult.SUCCESS) { // Reset fit counter now it succeeded fitAttempts = 0; } @@ -149,12 +135,10 @@ export class ExternalInventoryMagGen implements IInventoryMagGen protected getRandomExternalMagazineForInternalMagazineGun( weaponTpl: string, magazineBlacklist: string[], - ): ITemplateItem | undefined - { + ): ITemplateItem | undefined { // The mag Slot data for the weapon const magSlot = this.itemHelper.getItem(weaponTpl)[1]._props.Slots.find((x) => x._name === "mod_magazine"); - if (!magSlot) - { + if (!magSlot) { return undefined; } @@ -162,15 +146,13 @@ export class ExternalInventoryMagGen implements IInventoryMagGen const magazinePool = magSlot._props.filters[0].Filter.filter((x) => !magazineBlacklist.includes(x)).map( (x) => this.itemHelper.getItem(x)[1], ); - if (!magazinePool) - { + if (!magazinePool) { return undefined; } // Non-internal magazines that fit into the weapon const externalMagazineOnlyPool = magazinePool.filter((x) => x._props.ReloadMagType !== "InternalMagazine"); - if (!externalMagazineOnlyPool || externalMagazineOnlyPool?.length === 0) - { + if (!externalMagazineOnlyPool || externalMagazineOnlyPool?.length === 0) { return undefined; } diff --git a/project/src/generators/weapongen/implementations/InternalMagazineInventoryMagGen.ts b/project/src/generators/weapongen/implementations/InternalMagazineInventoryMagGen.ts index 3905fef5..4383a7be 100644 --- a/project/src/generators/weapongen/implementations/InternalMagazineInventoryMagGen.ts +++ b/project/src/generators/weapongen/implementations/InternalMagazineInventoryMagGen.ts @@ -1,26 +1,21 @@ -import { inject, injectable } from "tsyringe"; import { IInventoryMagGen } from "@spt/generators/weapongen/IInventoryMagGen"; import { InventoryMagGen } from "@spt/generators/weapongen/InventoryMagGen"; import { BotWeaponGeneratorHelper } from "@spt/helpers/BotWeaponGeneratorHelper"; +import { inject, injectable } from "tsyringe"; @injectable() -export class InternalMagazineInventoryMagGen implements IInventoryMagGen -{ - constructor(@inject("BotWeaponGeneratorHelper") protected botWeaponGeneratorHelper: BotWeaponGeneratorHelper) - {} +export class InternalMagazineInventoryMagGen implements IInventoryMagGen { + constructor(@inject("BotWeaponGeneratorHelper") protected botWeaponGeneratorHelper: BotWeaponGeneratorHelper) {} - public getPriority(): number - { + public getPriority(): number { return 0; } - public canHandleInventoryMagGen(inventoryMagGen: InventoryMagGen): boolean - { + public canHandleInventoryMagGen(inventoryMagGen: InventoryMagGen): boolean { return inventoryMagGen.getMagazineTemplate()._props.ReloadMagType === "InternalMagazine"; } - public process(inventoryMagGen: InventoryMagGen): void - { + public process(inventoryMagGen: InventoryMagGen): void { const bulletCount = this.botWeaponGeneratorHelper.getRandomizedBulletCount( inventoryMagGen.getMagCount(), inventoryMagGen.getMagazineTemplate(), diff --git a/project/src/generators/weapongen/implementations/UbglExternalMagGen.ts b/project/src/generators/weapongen/implementations/UbglExternalMagGen.ts index dbcdefa8..dd6d4705 100644 --- a/project/src/generators/weapongen/implementations/UbglExternalMagGen.ts +++ b/project/src/generators/weapongen/implementations/UbglExternalMagGen.ts @@ -1,28 +1,23 @@ -import { inject, injectable } from "tsyringe"; import { IInventoryMagGen } from "@spt/generators/weapongen/IInventoryMagGen"; import { InventoryMagGen } from "@spt/generators/weapongen/InventoryMagGen"; import { BotWeaponGeneratorHelper } from "@spt/helpers/BotWeaponGeneratorHelper"; import { BaseClasses } from "@spt/models/enums/BaseClasses"; import { EquipmentSlots } from "@spt/models/enums/EquipmentSlots"; +import { inject, injectable } from "tsyringe"; @injectable() -export class UbglExternalMagGen implements IInventoryMagGen -{ - constructor(@inject("BotWeaponGeneratorHelper") protected botWeaponGeneratorHelper: BotWeaponGeneratorHelper) - {} +export class UbglExternalMagGen implements IInventoryMagGen { + constructor(@inject("BotWeaponGeneratorHelper") protected botWeaponGeneratorHelper: BotWeaponGeneratorHelper) {} - public getPriority(): number - { + public getPriority(): number { return 1; } - public canHandleInventoryMagGen(inventoryMagGen: InventoryMagGen): boolean - { + public canHandleInventoryMagGen(inventoryMagGen: InventoryMagGen): boolean { return inventoryMagGen.getWeaponTemplate()._parent === BaseClasses.UBGL; } - public process(inventoryMagGen: InventoryMagGen): void - { + public process(inventoryMagGen: InventoryMagGen): void { const bulletCount = this.botWeaponGeneratorHelper.getRandomizedBulletCount( inventoryMagGen.getMagCount(), inventoryMagGen.getMagazineTemplate(), diff --git a/project/src/helpers/AssortHelper.ts b/project/src/helpers/AssortHelper.ts index c5d74b55..178441a7 100644 --- a/project/src/helpers/AssortHelper.ts +++ b/project/src/helpers/AssortHelper.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { ItemHelper } from "@spt/helpers/ItemHelper"; import { QuestHelper } from "@spt/helpers/QuestHelper"; import { IPmcData } from "@spt/models/eft/common/IPmcData"; @@ -7,18 +6,17 @@ import { QuestStatus } from "@spt/models/enums/QuestStatus"; import { ILogger } from "@spt/models/spt/utils/ILogger"; import { DatabaseServer } from "@spt/servers/DatabaseServer"; import { LocalisationService } from "@spt/services/LocalisationService"; +import { inject, injectable } from "tsyringe"; @injectable() -export class AssortHelper -{ +export class AssortHelper { constructor( @inject("PrimaryLogger") protected logger: ILogger, @inject("ItemHelper") protected itemHelper: ItemHelper, @inject("DatabaseServer") protected databaseServer: DatabaseServer, @inject("LocalisationService") protected localisationService: LocalisationService, @inject("QuestHelper") protected questHelper: QuestHelper, - ) - {} + ) {} /** * Remove assorts from a trader that have not been unlocked yet (via player completing corresponding quest) @@ -34,32 +32,27 @@ export class AssortHelper traderAssorts: ITraderAssort, mergedQuestAssorts: Record>, flea = false, - ): ITraderAssort - { + ): ITraderAssort { let strippedTraderAssorts = traderAssorts; // Trader assort does not always contain loyal_level_items - if (!traderAssorts.loyal_level_items) - { + if (!traderAssorts.loyal_level_items) { this.logger.warning(this.localisationService.getText("assort-missing_loyalty_level_object", traderId)); return traderAssorts; } // Iterate over all assorts, removing items that haven't yet been unlocked by quests (ASSORTMENT_UNLOCK) - for (const assortId in traderAssorts.loyal_level_items) - { + for (const assortId in traderAssorts.loyal_level_items) { // Get quest id that unlocks assort + statuses quest can be in to show assort const unlockValues = this.getQuestIdAndStatusThatShowAssort(mergedQuestAssorts, assortId); - if (!unlockValues) - { + if (!unlockValues) { continue; } // Remove assort if quest in profile does not have status that unlocks assort const questStatusInProfile = this.questHelper.getQuestStatus(pmcProfile, unlockValues.questId); - if (!unlockValues.status.includes(questStatusInProfile)) - { + if (!unlockValues.status.includes(questStatusInProfile)) { strippedTraderAssorts = this.removeItemFromAssort(traderAssorts, assortId, flea); } } @@ -76,10 +69,8 @@ export class AssortHelper protected getQuestIdAndStatusThatShowAssort( mergedQuestAssorts: Record>, assortId: string, - ): { questId: string, status: QuestStatus[] } - { - if (assortId in mergedQuestAssorts.started) - { + ): { questId: string; status: QuestStatus[] } { + if (assortId in mergedQuestAssorts.started) { // Assort unlocked by starting quest, assort is visible to player when : started or ready to hand in + handed in return { questId: mergedQuestAssorts.started[assortId], @@ -87,13 +78,11 @@ export class AssortHelper }; } - if (assortId in mergedQuestAssorts.success) - { + if (assortId in mergedQuestAssorts.success) { return { questId: mergedQuestAssorts.success[assortId], status: [QuestStatus.Success] }; } - if (assortId in mergedQuestAssorts.fail) - { + if (assortId in mergedQuestAssorts.fail) { return { questId: mergedQuestAssorts.fail[assortId], status: [QuestStatus.Fail] }; } @@ -107,23 +96,19 @@ export class AssortHelper * @param assort traders assorts * @returns traders assorts minus locked loyalty assorts */ - public stripLockedLoyaltyAssort(pmcProfile: IPmcData, traderId: string, assort: ITraderAssort): ITraderAssort - { + public stripLockedLoyaltyAssort(pmcProfile: IPmcData, traderId: string, assort: ITraderAssort): ITraderAssort { let strippedAssort = assort; // Trader assort does not always contain loyal_level_items - if (!assort.loyal_level_items) - { + if (!assort.loyal_level_items) { this.logger.warning(this.localisationService.getText("assort-missing_loyalty_level_object", traderId)); return strippedAssort; } // Remove items restricted by loyalty levels above those reached by the player - for (const itemId in assort.loyal_level_items) - { - if (assort.loyal_level_items[itemId] > pmcProfile.TradersInfo[traderId].loyaltyLevel) - { + for (const itemId in assort.loyal_level_items) { + if (assort.loyal_level_items[itemId] > pmcProfile.TradersInfo[traderId].loyaltyLevel) { strippedAssort = this.removeItemFromAssort(assort, itemId); } } @@ -137,16 +122,12 @@ export class AssortHelper * @param itemID item id to remove from asort * @returns Modified assort */ - public removeItemFromAssort(assort: ITraderAssort, itemID: string, flea = false): ITraderAssort - { + public removeItemFromAssort(assort: ITraderAssort, itemID: string, flea = false): ITraderAssort { const idsToRemove = this.itemHelper.findAndReturnChildrenByItems(assort.items, itemID); - if (assort.barter_scheme[itemID] && flea) - { - for (const barterSchemes of assort.barter_scheme[itemID]) - { - for (const barterScheme of barterSchemes) - { + if (assort.barter_scheme[itemID] && flea) { + for (const barterSchemes of assort.barter_scheme[itemID]) { + for (const barterScheme of barterSchemes) { barterScheme.sptQuestLocked = true; } } @@ -155,12 +136,9 @@ export class AssortHelper delete assort.barter_scheme[itemID]; delete assort.loyal_level_items[itemID]; - for (const i in idsToRemove) - { - for (const a in assort.items) - { - if (assort.items[a]._id === idsToRemove[i]) - { + for (const i in idsToRemove) { + for (const a in assort.items) { + if (assort.items[a]._id === idsToRemove[i]) { assort.items.splice(Number.parseInt(a), 1); } } diff --git a/project/src/helpers/BotDifficultyHelper.ts b/project/src/helpers/BotDifficultyHelper.ts index 3fea0dc3..897cf41e 100644 --- a/project/src/helpers/BotDifficultyHelper.ts +++ b/project/src/helpers/BotDifficultyHelper.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { BotHelper } from "@spt/helpers/BotHelper"; import { Difficulty } from "@spt/models/eft/common/tables/IBotType"; import { ConfigTypes } from "@spt/models/enums/ConfigTypes"; @@ -7,12 +6,12 @@ import { ILogger } from "@spt/models/spt/utils/ILogger"; import { ConfigServer } from "@spt/servers/ConfigServer"; import { DatabaseService } from "@spt/services/DatabaseService"; import { LocalisationService } from "@spt/services/LocalisationService"; -import { ICloner } from "@spt/utils/cloners/ICloner"; import { RandomUtil } from "@spt/utils/RandomUtil"; +import { ICloner } from "@spt/utils/cloners/ICloner"; +import { inject, injectable } from "tsyringe"; @injectable() -export class BotDifficultyHelper -{ +export class BotDifficultyHelper { protected pmcConfig: IPmcConfig; constructor( @@ -23,8 +22,7 @@ export class BotDifficultyHelper @inject("BotHelper") protected botHelper: BotHelper, @inject("ConfigServer") protected configServer: ConfigServer, @inject("PrimaryCloner") protected cloner: ICloner, - ) - { + ) { this.pmcConfig = this.configServer.getConfig(ConfigTypes.PMC); } @@ -41,8 +39,7 @@ export class BotDifficultyHelper difficulty: string, usecType: string, bearType: string, - ): Difficulty - { + ): Difficulty { const difficultySettings = this.getDifficultySettings(pmcType, difficulty); const friendlyType = pmcType === "bear" ? bearType : usecType; @@ -55,13 +52,10 @@ export class BotDifficultyHelper this.addBotToEnemyList(difficultySettings, this.pmcConfig.enemyTypes, friendlyType); // Add same/opposite side to enemy list - const hostilePMCTypes = hostileToSameSide - ? [enemyType, friendlyType] - : [enemyType]; + const hostilePMCTypes = hostileToSameSide ? [enemyType, friendlyType] : [enemyType]; this.addBotToEnemyList(difficultySettings, hostilePMCTypes); - if (hostileToSameSide) - { + if (hostileToSameSide) { this.setDifficultyToHostileToBearAndUsec(difficultySettings); } @@ -74,27 +68,22 @@ export class BotDifficultyHelper * @param typesToAdd Bot types to add to enemy list * @param typeBeingEdited Bot type to ignore and not add to enemy list */ - protected addBotToEnemyList(difficultySettings: Difficulty, typesToAdd: string[], typeBeingEdited?: string): void - { + protected addBotToEnemyList(difficultySettings: Difficulty, typesToAdd: string[], typeBeingEdited?: string): void { const enemyBotTypesKey = "ENEMY_BOT_TYPES"; // Null guard - if (!difficultySettings.Mind[enemyBotTypesKey]) - { + if (!difficultySettings.Mind[enemyBotTypesKey]) { difficultySettings.Mind[enemyBotTypesKey] = []; } const enemyArray = difficultySettings.Mind[enemyBotTypesKey]; - for (const botTypeToAdd of typesToAdd) - { - if (typeBeingEdited?.toLowerCase() === botTypeToAdd.toLowerCase()) - { + for (const botTypeToAdd of typesToAdd) { + if (typeBeingEdited?.toLowerCase() === botTypeToAdd.toLowerCase()) { this.logger.debug(`unable to add enemy ${botTypeToAdd} to its own enemy list, skipping`); continue; } - if (!enemyArray.includes(botTypeToAdd)) - { + if (!enemyArray.includes(botTypeToAdd)) { enemyArray.push(botTypeToAdd); } } @@ -105,8 +94,7 @@ export class BotDifficultyHelper * Look up value in bot.json/chanceSameSideIsHostilePercent * @param difficultySettings pmc difficulty settings */ - protected setDifficultyToHostileToBearAndUsec(difficultySettings: Difficulty): void - { + protected setDifficultyToHostileToBearAndUsec(difficultySettings: Difficulty): void { difficultySettings.Mind.CAN_RECEIVE_PLAYER_REQUESTS_BEAR = false; difficultySettings.Mind.CAN_RECEIVE_PLAYER_REQUESTS_USEC = false; difficultySettings.Mind.DEFAULT_USEC_BEHAVIOUR = "Attack"; @@ -119,14 +107,12 @@ export class BotDifficultyHelper * @param difficulty difficulty to get settings for (easy/normal etc) * @returns Difficulty object */ - public getBotDifficultySettings(type: string, difficulty: string): Difficulty - { + public getBotDifficultySettings(type: string, difficulty: string): Difficulty { const botDb = this.databaseService.getBots(); const desiredType = type.toLowerCase(); const bot = botDb.types[desiredType]; - if (!bot) - { + if (!bot) { // No bot found, get fallback difficulty values this.logger.warning(this.localisationService.getText("bot-unable_to_get_bot_fallback_to_assault", type)); botDb.types[desiredType] = this.cloner.clone(botDb.types.assault); @@ -134,8 +120,7 @@ export class BotDifficultyHelper // Get settings from raw bot json template file const difficultySettings = this.botHelper.getBotTemplate(desiredType).difficulty[difficulty]; - if (!difficultySettings) - { + if (!difficultySettings) { // No bot settings found, use 'assault' bot difficulty instead this.logger.warning( this.localisationService.getText("bot-unable_to_get_bot_difficulty_fallback_to_assault", { @@ -143,8 +128,9 @@ export class BotDifficultyHelper difficulty: difficulty, }), ); - botDb.types[desiredType].difficulty[difficulty] - = this.cloner.clone(botDb.types.assault.difficulty[difficulty]); + botDb.types[desiredType].difficulty[difficulty] = this.cloner.clone( + botDb.types.assault.difficulty[difficulty], + ); } return this.cloner.clone(difficultySettings); @@ -156,10 +142,9 @@ export class BotDifficultyHelper * @param difficulty what difficulty to retrieve * @returns Difficulty object */ - protected getDifficultySettings(type: string, difficulty: string): Difficulty - { - let difficultySetting - = this.pmcConfig.difficulty.toLowerCase() === "asonline" + protected getDifficultySettings(type: string, difficulty: string): Difficulty { + let difficultySetting = + this.pmcConfig.difficulty.toLowerCase() === "asonline" ? difficulty : this.pmcConfig.difficulty.toLowerCase(); @@ -173,10 +158,8 @@ export class BotDifficultyHelper * @param dropDownDifficulty Dropdown difficulty value to convert * @returns bot difficulty */ - public convertBotDifficultyDropdownToBotDifficulty(dropDownDifficulty: string): string - { - switch (dropDownDifficulty.toLowerCase()) - { + public convertBotDifficultyDropdownToBotDifficulty(dropDownDifficulty: string): string { + switch (dropDownDifficulty.toLowerCase()) { case "medium": return "normal"; case "random": @@ -190,8 +173,7 @@ export class BotDifficultyHelper * Choose a random difficulty from - easy/normal/hard/impossible * @returns random difficulty */ - public chooseRandomDifficulty(): string - { + public chooseRandomDifficulty(): string { return this.randomUtil.getArrayValue(["easy", "normal", "hard", "impossible"]); } } diff --git a/project/src/helpers/BotGeneratorHelper.ts b/project/src/helpers/BotGeneratorHelper.ts index 48096ba2..50c6101a 100644 --- a/project/src/helpers/BotGeneratorHelper.ts +++ b/project/src/helpers/BotGeneratorHelper.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { ApplicationContext } from "@spt/context/ApplicationContext"; import { ContextVariableType } from "@spt/context/ContextVariableType"; import { ContainerHelper } from "@spt/helpers/ContainerHelper"; @@ -20,10 +19,10 @@ import { ConfigServer } from "@spt/servers/ConfigServer"; import { DatabaseService } from "@spt/services/DatabaseService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { RandomUtil } from "@spt/utils/RandomUtil"; +import { inject, injectable } from "tsyringe"; @injectable() -export class BotGeneratorHelper -{ +export class BotGeneratorHelper { protected botConfig: IBotConfig; protected pmcConfig: IPmcConfig; @@ -38,8 +37,7 @@ export class BotGeneratorHelper @inject("ApplicationContext") protected applicationContext: ApplicationContext, @inject("LocalisationService") protected localisationService: LocalisationService, @inject("ConfigServer") protected configServer: ConfigServer, - ) - { + ) { this.botConfig = this.configServer.getConfig(ConfigTypes.BOT); this.pmcConfig = this.configServer.getConfig(ConfigTypes.PMC); } @@ -51,8 +49,7 @@ export class BotGeneratorHelper * @param botRole Used by weapons to randomize the durability values. Null for non-equipped items * @returns Item Upd object with extra properties */ - public generateExtraPropertiesForItem(itemTemplate: ITemplateItem, botRole?: string): { upd?: Upd } - { + public generateExtraPropertiesForItem(itemTemplate: ITemplateItem, botRole?: string): { upd?: Upd } { // Get raid settings, if no raid, default to day const raidSettings = this.applicationContext .getLatestValue(ContextVariableType.RAID_CONFIGURATION) @@ -61,44 +58,33 @@ export class BotGeneratorHelper const itemProperties: Upd = {}; - if (itemTemplate._props.MaxDurability) - { - if (itemTemplate._props.weapClass) - { + if (itemTemplate._props.MaxDurability) { + if (itemTemplate._props.weapClass) { // Is weapon itemProperties.Repairable = this.generateWeaponRepairableProperties(itemTemplate, botRole); - } - else if (itemTemplate._props.armorClass) - { + } else if (itemTemplate._props.armorClass) { // Is armor itemProperties.Repairable = this.generateArmorRepairableProperties(itemTemplate, botRole); } } - if (itemTemplate._props.HasHinge) - { + if (itemTemplate._props.HasHinge) { itemProperties.Togglable = { On: true }; } - if (itemTemplate._props.Foldable) - { + if (itemTemplate._props.Foldable) { itemProperties.Foldable = { Folded: false }; } - if (itemTemplate._props.weapFireType?.length) - { - if (itemTemplate._props.weapFireType.includes("fullauto")) - { + if (itemTemplate._props.weapFireType?.length) { + if (itemTemplate._props.weapFireType.includes("fullauto")) { itemProperties.FireMode = { FireMode: "fullauto" }; - } - else - { + } else { itemProperties.FireMode = { FireMode: this.randomUtil.getArrayValue(itemTemplate._props.weapFireType) }; } } - if (itemTemplate._props.MaxHpResource) - { + if (itemTemplate._props.MaxHpResource) { itemProperties.MedKit = { HpResource: this.getRandomizedResourceValue( itemTemplate._props.MaxHpResource, @@ -107,8 +93,7 @@ export class BotGeneratorHelper }; } - if (itemTemplate._props.MaxResource && itemTemplate._props.foodUseTime) - { + if (itemTemplate._props.MaxResource && itemTemplate._props.foodUseTime) { itemProperties.FoodDrink = { HpPercent: this.getRandomizedResourceValue( itemTemplate._props.MaxResource, @@ -117,8 +102,7 @@ export class BotGeneratorHelper }; } - if (itemTemplate._parent === BaseClasses.FLASHLIGHT) - { + if (itemTemplate._parent === BaseClasses.FLASHLIGHT) { // Get chance from botconfig for bot type const lightLaserActiveChance = raidIsNight ? this.getBotEquipmentSettingFromConfig(botRole, "lightIsActiveNightChancePercent", 50) @@ -127,9 +111,7 @@ export class BotGeneratorHelper IsActive: this.randomUtil.getChance100(lightLaserActiveChance), SelectedMode: 0, }; - } - else if (itemTemplate._parent === BaseClasses.TACTICAL_COMBO) - { + } else if (itemTemplate._parent === BaseClasses.TACTICAL_COMBO) { // Get chance from botconfig for bot type, use 50% if no value found const lightLaserActiveChance = this.getBotEquipmentSettingFromConfig( botRole, @@ -142,8 +124,7 @@ export class BotGeneratorHelper }; } - if (itemTemplate._parent === BaseClasses.NIGHTVISION) - { + if (itemTemplate._parent === BaseClasses.NIGHTVISION) { // Get chance from botconfig for bot type const nvgActiveChance = raidIsNight ? this.getBotEquipmentSettingFromConfig(botRole, "nvgIsActiveChanceNightPercent", 90) @@ -152,8 +133,7 @@ export class BotGeneratorHelper } // Togglable face shield - if (itemTemplate._props.HasHinge && itemTemplate._props.FaceShieldComponent) - { + if (itemTemplate._props.HasHinge && itemTemplate._props.FaceShieldComponent) { // Get chance from botconfig for bot type, use 75% if no value found const faceShieldActiveChance = this.getBotEquipmentSettingFromConfig( botRole, @@ -172,15 +152,12 @@ export class BotGeneratorHelper * @param randomizationValues Value provided from config * @returns Randomized value from maxHpResource */ - protected getRandomizedResourceValue(maxResource: number, randomizationValues: IRandomisedResourceValues): number - { - if (!randomizationValues) - { + protected getRandomizedResourceValue(maxResource: number, randomizationValues: IRandomisedResourceValues): number { + if (!randomizationValues) { return maxResource; } - if (this.randomUtil.getChance100(randomizationValues.chanceMaxResourcePercent)) - { + if (this.randomUtil.getChance100(randomizationValues.chanceMaxResourcePercent)) { return maxResource; } @@ -201,15 +178,12 @@ export class BotGeneratorHelper botRole: string | undefined, setting: keyof EquipmentFilters, defaultValue: number, - ): number - { - if (!botRole) - { + ): number { + if (!botRole) { return defaultValue; } const botEquipmentSettings = this.botConfig.equipment[this.getBotEquipmentRole(botRole)]; - if (!botEquipmentSettings) - { + if (!botEquipmentSettings) { this.logger.warning( this.localisationService.getText("bot-missing_equipment_settings", { botRole: botRole, @@ -220,8 +194,7 @@ export class BotGeneratorHelper return defaultValue; } - if (botEquipmentSettings[setting] === undefined || typeof botEquipmentSettings[setting] !== "number") - { + if (botEquipmentSettings[setting] === undefined || typeof botEquipmentSettings[setting] !== "number") { this.logger.warning( this.localisationService.getText("bot-missing_equipment_settings_property", { botRole: botRole, @@ -242,8 +215,7 @@ export class BotGeneratorHelper * @param botRole type of bot being generated for * @returns Repairable object */ - protected generateWeaponRepairableProperties(itemTemplate: ITemplateItem, botRole?: string): Repairable - { + protected generateWeaponRepairableProperties(itemTemplate: ITemplateItem, botRole?: string): Repairable { const maxDurability = this.durabilityLimitsHelper.getRandomizedMaxWeaponDurability(itemTemplate, botRole); const currentDurability = this.durabilityLimitsHelper.getRandomizedWeaponDurability( itemTemplate, @@ -260,17 +232,13 @@ export class BotGeneratorHelper * @param botRole type of bot being generated for * @returns Repairable object */ - protected generateArmorRepairableProperties(itemTemplate: ITemplateItem, botRole?: string): Repairable - { + protected generateArmorRepairableProperties(itemTemplate: ITemplateItem, botRole?: string): Repairable { let maxDurability: number; let currentDurability: number; - if (Number.parseInt(`${itemTemplate._props.armorClass}`) === 0) - { + if (Number.parseInt(`${itemTemplate._props.armorClass}`) === 0) { maxDurability = itemTemplate._props.MaxDurability!; currentDurability = itemTemplate._props.MaxDurability!; - } - else - { + } else { maxDurability = this.durabilityLimitsHelper.getRandomizedMaxArmorDurability(itemTemplate, botRole); currentDurability = this.durabilityLimitsHelper.getRandomizedArmorDurability( itemTemplate, @@ -286,15 +254,13 @@ export class BotGeneratorHelper itemsEquipped: Item[], tplToCheck: string, modSlot: string, - ): IChooseRandomCompatibleModResult - { + ): IChooseRandomCompatibleModResult { // TODO: Can probably be optimized to cache itemTemplates as items are added to inventory const equippedItemsDb = itemsEquipped.map((item) => this.itemHelper.getItem(item._tpl)[1]); const itemToEquipDb = this.itemHelper.getItem(tplToCheck); const itemToEquip = itemToEquipDb[1]; - if (!itemToEquipDb[0]) - { + if (!itemToEquipDb[0]) { this.logger.warning( this.localisationService.getText("bot-invalid_item_compatibility_check", { itemTpl: tplToCheck, @@ -306,8 +272,7 @@ export class BotGeneratorHelper } // No props property - if (!itemToEquip._props) - { + if (!itemToEquip._props) { this.logger.warning( this.localisationService.getText("bot-compatibility_check_missing_props", { id: itemToEquip._id, @@ -321,8 +286,7 @@ export class BotGeneratorHelper // Check if any of the current weapon mod templates have the incoming item defined as incompatible const blockingItem = equippedItemsDb.find((x) => x._props.ConflictingItems?.includes(tplToCheck)); - if (blockingItem) - { + if (blockingItem) { return { incompatible: true, found: false, @@ -333,8 +297,7 @@ export class BotGeneratorHelper // Check inverse to above, if the incoming item has any existing mods in its conflicting items array const blockingModItem = itemsEquipped.find((item) => itemToEquip._props.ConflictingItems?.includes(item._tpl)); - if (blockingModItem) - { + if (blockingModItem) { return { incompatible: true, found: false, @@ -356,11 +319,9 @@ export class BotGeneratorHelper itemsEquipped: Item[], tplToCheck: string, equipmentSlot: string, - ): IChooseRandomCompatibleModResult - { + ): IChooseRandomCompatibleModResult { // Skip slots that have no incompatibilities - if (["Scabbard", "Backpack", "SecureContainer", "Holster", "ArmBand"].includes(equipmentSlot)) - { + if (["Scabbard", "Backpack", "SecureContainer", "Holster", "ArmBand"].includes(equipmentSlot)) { return { incompatible: false, found: false, reason: "" }; } @@ -369,8 +330,7 @@ export class BotGeneratorHelper const itemToEquipDb = this.itemHelper.getItem(tplToCheck); const itemToEquip = itemToEquipDb[1]; - if (!itemToEquipDb[0]) - { + if (!itemToEquipDb[0]) { this.logger.warning( this.localisationService.getText("bot-invalid_item_compatibility_check", { itemTpl: tplToCheck, @@ -381,8 +341,7 @@ export class BotGeneratorHelper return { incompatible: true, found: false, reason: `item: ${tplToCheck} does not exist in the database` }; } - if (!itemToEquip._props) - { + if (!itemToEquip._props) { this.logger.warning( this.localisationService.getText("bot-compatibility_check_missing_props", { id: itemToEquip._id, @@ -396,8 +355,7 @@ export class BotGeneratorHelper // Does an equipped item have a property that blocks the desired item - check for prop "BlocksX" .e.g BlocksEarpiece / BlocksFaceCover let blockingItem = equippedItemsDb.find((item) => item._props[`Blocks${equipmentSlot}`]); - if (blockingItem) - { + if (blockingItem) { // this.logger.warning(`1 incompatibility found between - ${itemToEquip[1]._name} and ${blockingItem._name} - ${equipmentSlot}`); return { incompatible: true, @@ -409,8 +367,7 @@ export class BotGeneratorHelper // Check if any of the current inventory templates have the incoming item defined as incompatible blockingItem = equippedItemsDb.find((x) => x._props.ConflictingItems?.includes(tplToCheck)); - if (blockingItem) - { + if (blockingItem) { // this.logger.warning(`2 incompatibility found between - ${itemToEquip[1]._name} and ${blockingItem._props.Name} - ${equipmentSlot}`); return { incompatible: true, @@ -421,11 +378,9 @@ export class BotGeneratorHelper } // Does item being checked get blocked/block existing item - if (itemToEquip._props.BlocksHeadwear) - { + if (itemToEquip._props.BlocksHeadwear) { const existingHeadwear = itemsEquipped.find((x) => x.slotId === "Headwear"); - if (existingHeadwear) - { + if (existingHeadwear) { return { incompatible: true, found: false, @@ -436,11 +391,9 @@ export class BotGeneratorHelper } // Does item being checked get blocked/block existing item - if (itemToEquip._props.BlocksFaceCover) - { + if (itemToEquip._props.BlocksFaceCover) { const existingFaceCover = itemsEquipped.find((item) => item.slotId === "FaceCover"); - if (existingFaceCover) - { + if (existingFaceCover) { return { incompatible: true, found: false, @@ -451,11 +404,9 @@ export class BotGeneratorHelper } // Does item being checked get blocked/block existing item - if (itemToEquip._props.BlocksEarpiece) - { + if (itemToEquip._props.BlocksEarpiece) { const existingEarpiece = itemsEquipped.find((item) => item.slotId === "Earpiece"); - if (existingEarpiece) - { + if (existingEarpiece) { return { incompatible: true, found: false, @@ -466,11 +417,9 @@ export class BotGeneratorHelper } // Does item being checked get blocked/block existing item - if (itemToEquip._props.BlocksArmorVest) - { + if (itemToEquip._props.BlocksArmorVest) { const existingArmorVest = itemsEquipped.find((item) => item.slotId === "ArmorVest"); - if (existingArmorVest) - { + if (existingArmorVest) { return { incompatible: true, found: false, @@ -482,8 +431,7 @@ export class BotGeneratorHelper // Check if the incoming item has any inventory items defined as incompatible const blockingInventoryItem = itemsEquipped.find((x) => itemToEquip._props.ConflictingItems?.includes(x._tpl)); - if (blockingInventoryItem) - { + if (blockingInventoryItem) { // this.logger.warning(`3 incompatibility found between - ${itemToEquip[1]._name} and ${blockingInventoryItem._tpl} - ${equipmentSlot}`) return { incompatible: true, @@ -500,8 +448,7 @@ export class BotGeneratorHelper * @param botRole Role to convert * @returns Equipment role (e.g. pmc / assault / bossTagilla) */ - public getBotEquipmentRole(botRole: string): string - { + public getBotEquipmentRole(botRole: string): string { return [this.pmcConfig.usecType.toLowerCase(), this.pmcConfig.bearType.toLowerCase()].includes( botRole.toLowerCase(), ) @@ -525,23 +472,18 @@ export class BotGeneratorHelper itemWithChildren: Item[], inventory: Inventory, containersIdFull?: Set, - ): ItemAddedResult - { + ): ItemAddedResult { /** Track how many containers are unable to be found */ let missingContainerCount = 0; - for (const equipmentSlotId of equipmentSlots) - { - if (containersIdFull?.has(equipmentSlotId)) - { + for (const equipmentSlotId of equipmentSlots) { + if (containersIdFull?.has(equipmentSlotId)) { continue; } // Get container to put item into const container = inventory.items.find((item) => item.slotId === equipmentSlotId); - if (!container) - { + if (!container) { missingContainerCount++; - if (missingContainerCount === equipmentSlots.length) - { + if (missingContainerCount === equipmentSlots.length) { // Bot doesnt have any containers we want to add item to this.logger.debug( `Unable to add item: ${itemWithChildren[0]._tpl} to bot as it lacks the following containers: ${equipmentSlots.join( @@ -558,16 +500,14 @@ export class BotGeneratorHelper // Get container details from db const containerTemplate = this.itemHelper.getItem(container._tpl); - if (!containerTemplate[0]) - { + if (!containerTemplate[0]) { this.logger.warning(this.localisationService.getText("bot-missing_container_with_tpl", container._tpl)); // Bad item, skip continue; } - if (!containerTemplate[1]._props.Grids?.length) - { + if (!containerTemplate[1]._props.Grids?.length) { // Container has no slots to hold items continue; } @@ -578,21 +518,18 @@ export class BotGeneratorHelper // Iterate over each grid in the container and look for a big enough space for the item to be placed in let currentGridCount = 1; const totalSlotGridCount = containerTemplate[1]._props.Grids.length; - for (const slotGrid of containerTemplate[1]._props.Grids) - { + for (const slotGrid of containerTemplate[1]._props.Grids) { // Grid is empty, skip or item size is bigger than grid if ( - slotGrid._props.cellsH === 0 - || slotGrid._props.cellsV === 0 - || itemSize[0] * itemSize[1] > slotGrid._props.cellsV * slotGrid._props.cellsH - ) - { + slotGrid._props.cellsH === 0 || + slotGrid._props.cellsV === 0 || + itemSize[0] * itemSize[1] > slotGrid._props.cellsV * slotGrid._props.cellsH + ) { continue; } // Can't put item type in grid, skip all grids as we're assuming they have the same rules - if (!this.itemAllowedInContainer(slotGrid, rootItemTplId)) - { + if (!this.itemAllowedInContainer(slotGrid, rootItemTplId)) { // Multiple containers, maybe next one allows item, only break out of loop for this containers grids break; } @@ -604,13 +541,11 @@ export class BotGeneratorHelper // Get root items in container we can iterate over to find out what space is free const containerItemsToCheck = existingContainerItems.filter((x) => x.slotId === slotGrid._name); - for (const item of containerItemsToCheck) - { + for (const item of containerItemsToCheck) { // Look for children on items, insert into array if found // (used later when figuring out how much space weapon takes up) const itemWithChildren = this.itemHelper.findAndReturnChildrenAsItems(inventory.items, item._id); - if (itemWithChildren.length > 1) - { + if (itemWithChildren.length > 1) { existingContainerItems.splice(existingContainerItems.indexOf(item), 1, ...itemWithChildren); } } @@ -627,8 +562,7 @@ export class BotGeneratorHelper const findSlotResult = this.containerHelper.findSlotForItem(slotGridMap, itemSize[0], itemSize[1]); // Open slot found, add item to inventory - if (findSlotResult.success) - { + if (findSlotResult.success) { const parentItem = itemWithChildren.find((i) => i._id === rootItemId)!; // Set items parent to container id @@ -646,8 +580,7 @@ export class BotGeneratorHelper } // If we've checked all grids in container and reached this point, there's no space for item - if (currentGridCount >= totalSlotGridCount) - { + if (currentGridCount >= totalSlotGridCount) { break; } @@ -656,11 +589,9 @@ export class BotGeneratorHelper } // if we got to this point, the item couldnt be placed on the container - if (containersIdFull) - { + if (containersIdFull) { // if the item was a one by one, we know it must be full. Or if the maps cant find a slot for a one by one - if (itemSize[0] === 1 && itemSize[1] === 1) - { + if (itemSize[0] === 1 && itemSize[1] === 1) { containersIdFull.add(equipmentSlotId); } } @@ -675,38 +606,32 @@ export class BotGeneratorHelper * @param itemTpl Item tpl being placed * @returns True if allowed */ - protected itemAllowedInContainer(slotGrid: Grid, itemTpl: string): boolean - { + protected itemAllowedInContainer(slotGrid: Grid, itemTpl: string): boolean { const propFilters = slotGrid._props.filters; const excludedFilter = propFilters[0]?.ExcludedFilter ?? []; const filter = propFilters[0]?.Filter ?? []; - if (propFilters.length === 0) - { + if (propFilters.length === 0) { // no filters, item is fine to add return true; } // Check if item base type is excluded - if (excludedFilter || filter) - { + if (excludedFilter || filter) { const itemDetails = this.itemHelper.getItem(itemTpl)[1]; // if item to add is found in exclude filter, not allowed - if (excludedFilter?.includes(itemDetails._parent)) - { + if (excludedFilter?.includes(itemDetails._parent)) { return false; } // If Filter array only contains 1 filter and its for basetype 'item', allow it - if (filter?.length === 1 && filter.includes(BaseClasses.ITEM)) - { + if (filter?.length === 1 && filter.includes(BaseClasses.ITEM)) { return true; } // If allowed filter has something in it + filter doesnt have basetype 'item', not allowed - if (filter?.length > 0 && !filter.includes(itemDetails._parent)) - { + if (filter?.length > 0 && !filter.includes(itemDetails._parent)) { return false; } } diff --git a/project/src/helpers/BotHelper.ts b/project/src/helpers/BotHelper.ts index 248f6598..5230f4e3 100644 --- a/project/src/helpers/BotHelper.ts +++ b/project/src/helpers/BotHelper.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { MinMax } from "@spt/models/common/MinMax"; import { Difficulty, IBotType } from "@spt/models/eft/common/tables/IBotType"; import { ConfigTypes } from "@spt/models/enums/ConfigTypes"; @@ -8,10 +7,10 @@ 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 { inject, injectable } from "tsyringe"; @injectable() -export class BotHelper -{ +export class BotHelper { protected botConfig: IBotConfig; protected pmcConfig: IPmcConfig; @@ -20,8 +19,7 @@ export class BotHelper @inject("DatabaseService") protected databaseService: DatabaseService, @inject("RandomUtil") protected randomUtil: RandomUtil, @inject("ConfigServer") protected configServer: ConfigServer, - ) - { + ) { this.botConfig = this.configServer.getConfig(ConfigTypes.BOT); this.pmcConfig = this.configServer.getConfig(ConfigTypes.PMC); } @@ -31,8 +29,7 @@ export class BotHelper * @param role botRole to get template for * @returns IBotType object */ - public getBotTemplate(role: string): IBotType - { + public getBotTemplate(role: string): IBotType { return this.databaseService.getBots().types[role.toLowerCase()]; } @@ -41,18 +38,15 @@ export class BotHelper * @param botRole bot role to check * @returns true if is pmc */ - public isBotPmc(botRole: string): boolean - { + public isBotPmc(botRole: string): boolean { return ["usec", "bear", "pmc", "pmcbear", "pmcusec"].includes(botRole?.toLowerCase()); } - public isBotBoss(botRole: string): boolean - { + public isBotBoss(botRole: string): boolean { return this.botConfig.bosses.some((x) => x.toLowerCase() === botRole?.toLowerCase()); } - public isBotFollower(botRole: string): boolean - { + public isBotFollower(botRole: string): boolean { return botRole?.toLowerCase().startsWith("follower"); } @@ -61,13 +55,11 @@ export class BotHelper * @param difficultySettings bot settings to alter * @param typeToAdd bot type to add to friendly list */ - public addBotToFriendlyList(difficultySettings: Difficulty, typeToAdd: string): void - { + public addBotToFriendlyList(difficultySettings: Difficulty, typeToAdd: string): void { const friendlyBotTypesKey = "FRIENDLY_BOT_TYPES"; // Null guard - if (!difficultySettings.Mind[friendlyBotTypesKey]) - { + if (!difficultySettings.Mind[friendlyBotTypesKey]) { difficultySettings.Mind[friendlyBotTypesKey] = []; } @@ -79,27 +71,22 @@ export class BotHelper * @param difficultySettings bot settings to alter * @param typesToAdd bot type to add to revenge list */ - public addBotToRevengeList(difficultySettings: Difficulty, typesToAdd: string[]): void - { + public addBotToRevengeList(difficultySettings: Difficulty, typesToAdd: string[]): void { const revengePropKey = "REVENGE_BOT_TYPES"; // Nothing to add - if (!typesToAdd) - { + if (!typesToAdd) { return; } // Null guard - if (!difficultySettings.Mind[revengePropKey]) - { + if (!difficultySettings.Mind[revengePropKey]) { difficultySettings.Mind[revengePropKey] = []; } const revengeArray = difficultySettings.Mind[revengePropKey]; - for (const botTypeToAdd of typesToAdd) - { - if (!revengeArray.includes(botTypeToAdd)) - { + for (const botTypeToAdd of typesToAdd) { + if (!revengeArray.includes(botTypeToAdd)) { revengeArray.push(botTypeToAdd); } } @@ -110,32 +97,28 @@ export class BotHelper * @param botRole the bot role to check if should be a pmc * @returns true if should be a pmc */ - public shouldBotBePmc(botRole: string): boolean - { + public shouldBotBePmc(botRole: string): boolean { const botRoleLowered = botRole.toLowerCase(); // Handle when map waves have these types in the bot type - if (this.botRoleIsPmc(botRoleLowered)) - { + if (this.botRoleIsPmc(botRoleLowered)) { return true; } const botConvertMinMax = this.pmcConfig.convertIntoPmcChance[botRoleLowered]; // no bot type defined in config, default to false - if (!botConvertMinMax) - { + if (!botConvertMinMax) { return false; } return this.rollChanceToBePmc(botRoleLowered, botConvertMinMax); } - public rollChanceToBePmc(role: string, botConvertMinMax: MinMax): boolean - { + public rollChanceToBePmc(role: string, botConvertMinMax: MinMax): boolean { return ( - role.toLowerCase() in this.pmcConfig.convertIntoPmcChance - && this.randomUtil.getChance100(this.randomUtil.getInt(botConvertMinMax.min, botConvertMinMax.max)) + role.toLowerCase() in this.pmcConfig.convertIntoPmcChance && + this.randomUtil.getChance100(this.randomUtil.getInt(botConvertMinMax.min, botConvertMinMax.max)) ); } @@ -144,8 +127,7 @@ export class BotHelper * @param botRole Role to check * @returns True if role is PMC */ - public botRoleIsPmc(botRole: string): boolean - { + public botRoleIsPmc(botRole: string): boolean { return [this.pmcConfig.usecType.toLowerCase(), this.pmcConfig.bearType.toLowerCase()].includes( botRole.toLowerCase(), ); @@ -160,11 +142,9 @@ export class BotHelper public getBotRandomizationDetails( botLevel: number, botEquipConfig: EquipmentFilters, - ): RandomisationDetails | undefined - { + ): RandomisationDetails | undefined { // No randomisation details found, skip - if (!botEquipConfig || Object.keys(botEquipConfig).length === 0 || !botEquipConfig.randomisation) - { + if (!botEquipConfig || Object.keys(botEquipConfig).length === 0 || !botEquipConfig.randomisation) { return undefined; } @@ -175,8 +155,7 @@ export class BotHelper * Choose between pmcBEAR and pmcUSEC at random based on the % defined in pmcConfig.isUsec * @returns pmc role */ - public getRandomizedPmcRole(): string - { + public getRandomizedPmcRole(): string { return this.randomUtil.getChance100(this.pmcConfig.isUsec) ? this.pmcConfig.usecType : this.pmcConfig.bearType; } @@ -185,10 +164,8 @@ export class BotHelper * @param botRole role to get side for * @returns side (usec/bear) */ - public getPmcSideByRole(botRole: string): string - { - switch (botRole.toLowerCase()) - { + public getPmcSideByRole(botRole: string): string { + switch (botRole.toLowerCase()) { case this.pmcConfig.bearType.toLowerCase(): return "Bear"; case this.pmcConfig.usecType.toLowerCase(): @@ -202,19 +179,14 @@ export class BotHelper * Get a randomized PMC side based on bot config value 'isUsec' * @returns pmc side as string */ - protected getRandomizedPmcSide(): string - { + protected getRandomizedPmcSide(): string { return this.randomUtil.getChance100(this.pmcConfig.isUsec) ? "Usec" : "Bear"; } - public getPmcNicknameOfMaxLength(userId: string, maxLength: number): string - { + public getPmcNicknameOfMaxLength(userId: string, maxLength: number): string { // recurivse if name is longer than max characters allowed (15 characters) const randomType = this.randomUtil.getInt(0, 1) === 0 ? "usec" : "bear"; - const name - = this.randomUtil.getStringArrayValue(this.databaseService.getBots().types[randomType].firstName); - return name.length > maxLength - ? this.getPmcNicknameOfMaxLength(userId, maxLength) - : name; + const name = this.randomUtil.getStringArrayValue(this.databaseService.getBots().types[randomType].firstName); + return name.length > maxLength ? this.getPmcNicknameOfMaxLength(userId, maxLength) : name; } } diff --git a/project/src/helpers/BotWeaponGeneratorHelper.ts b/project/src/helpers/BotWeaponGeneratorHelper.ts index 1ecd0af5..a22fd140 100644 --- a/project/src/helpers/BotWeaponGeneratorHelper.ts +++ b/project/src/helpers/BotWeaponGeneratorHelper.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { BotGeneratorHelper } from "@spt/helpers/BotGeneratorHelper"; import { ItemHelper } from "@spt/helpers/ItemHelper"; import { WeightedRandomHelper } from "@spt/helpers/WeightedRandomHelper"; @@ -14,10 +13,10 @@ import { DatabaseServer } from "@spt/servers/DatabaseServer"; import { LocalisationService } from "@spt/services/LocalisationService"; import { HashUtil } from "@spt/utils/HashUtil"; import { RandomUtil } from "@spt/utils/RandomUtil"; +import { inject, injectable } from "tsyringe"; @injectable() -export class BotWeaponGeneratorHelper -{ +export class BotWeaponGeneratorHelper { constructor( @inject("PrimaryLogger") protected logger: ILogger, @inject("DatabaseServer") protected databaseServer: DatabaseServer, @@ -27,8 +26,7 @@ export class BotWeaponGeneratorHelper @inject("WeightedRandomHelper") protected weightedRandomHelper: WeightedRandomHelper, @inject("BotGeneratorHelper") protected botGeneratorHelper: BotGeneratorHelper, @inject("LocalisationService") protected localisationService: LocalisationService, - ) - {} + ) {} /** * Get a randomized number of bullets for a specific magazine @@ -36,27 +34,21 @@ export class BotWeaponGeneratorHelper * @param magTemplate magazine to generate bullet count for * @returns bullet count number */ - public getRandomizedBulletCount(magCounts: GenerationData, magTemplate: ITemplateItem): number - { + public getRandomizedBulletCount(magCounts: GenerationData, magTemplate: ITemplateItem): number { const randomizedMagazineCount = this.getRandomizedMagazineCount(magCounts); const parentItem = this.itemHelper.getItem(magTemplate._parent)[1]; let chamberBulletCount = 0; - if (this.magazineIsCylinderRelated(parentItem._name)) - { + if (this.magazineIsCylinderRelated(parentItem._name)) { const firstSlotAmmoTpl = magTemplate._props.Cartridges[0]._props.filters[0].Filter[0]; const ammoMaxStackSize = this.itemHelper.getItem(firstSlotAmmoTpl)[1]?._props?.StackMaxSize ?? 1; - chamberBulletCount - = ammoMaxStackSize === 1 + chamberBulletCount = + ammoMaxStackSize === 1 ? 1 // Rotating grenade launcher : magTemplate._props.Slots.length; // Shotguns/revolvers. We count the number of camoras as the _max_count of the magazine is 0 - } - else if (parentItem._id === BaseClasses.UBGL) - { + } else if (parentItem._id === BaseClasses.UBGL) { // Underbarrel launchers can only have 1 chambered grenade chamberBulletCount = 1; - } - else - { + } else { chamberBulletCount = magTemplate._props.Cartridges[0]._max_count; } @@ -70,8 +62,7 @@ export class BotWeaponGeneratorHelper * @param magCounts min and max value returned value can be between * @returns numerical value of magazine count */ - public getRandomizedMagazineCount(magCounts: GenerationData): number - { + public getRandomizedMagazineCount(magCounts: GenerationData): number { // const range = magCounts.max - magCounts.min; // return this.randomUtil.getBiasedRandomNumber(magCounts.min, magCounts.max, Math.round(range * 0.75), 4); @@ -83,8 +74,7 @@ export class BotWeaponGeneratorHelper * @param magazineParentName the name of the magazines parent * @returns true if it is cylinder related */ - public magazineIsCylinderRelated(magazineParentName: string): boolean - { + public magazineIsCylinderRelated(magazineParentName: string): boolean { return ["CylinderMagazine", "SpringDrivenCylinder"].includes(magazineParentName); } @@ -95,8 +85,7 @@ export class BotWeaponGeneratorHelper * @param magTemplate template object of magazine * @returns Item array */ - public createMagazineWithAmmo(magazineTpl: string, ammoTpl: string, magTemplate: ITemplateItem): Item[] - { + public createMagazineWithAmmo(magazineTpl: string, ammoTpl: string, magTemplate: ITemplateItem): Item[] { const magazine: Item[] = [{ _id: this.hashUtil.generate(), _tpl: magazineTpl }]; this.itemHelper.fillMagazineWithCartridge(magazine, magTemplate, ammoTpl, 1); @@ -116,16 +105,14 @@ export class BotWeaponGeneratorHelper cartridgeCount: number, inventory: Inventory, equipmentSlotsToAddTo: EquipmentSlots[] = [EquipmentSlots.TACTICAL_VEST, EquipmentSlots.POCKETS], - ): void - { + ): void { const ammoItems = this.itemHelper.splitStack({ _id: this.hashUtil.generate(), _tpl: ammoTpl, upd: { StackObjectsCount: cartridgeCount }, }); - for (const ammoItem of ammoItems) - { + for (const ammoItem of ammoItems) { const result = this.botGeneratorHelper.addItemWithChildrenToEquipmentSlot( equipmentSlotsToAddTo, ammoItem._id, @@ -134,12 +121,10 @@ export class BotWeaponGeneratorHelper inventory, ); - if (result !== ItemAddedResult.SUCCESS) - { + if (result !== ItemAddedResult.SUCCESS) { this.logger.debug(`Unable to add ammo: ${ammoItem._tpl} to bot inventory, ${ItemAddedResult[result]}`); - if (result === ItemAddedResult.NO_SPACE || result === ItemAddedResult.NO_CONTAINERS) - { + if (result === ItemAddedResult.NO_SPACE || result === ItemAddedResult.NO_CONTAINERS) { // If there's no space for 1 stack or no containers to hold item, there's no space for the others break; } @@ -152,8 +137,7 @@ export class BotWeaponGeneratorHelper * @param weaponTemplate weapon to get default magazine for * @returns tpl of magazine */ - public getWeaponsDefaultMagazineTpl(weaponTemplate: ITemplateItem): string - { + public getWeaponsDefaultMagazineTpl(weaponTemplate: ITemplateItem): string { return weaponTemplate._props.defMagType; } } diff --git a/project/src/helpers/ContainerHelper.ts b/project/src/helpers/ContainerHelper.ts index 9c3889c5..0f7d5967 100644 --- a/project/src/helpers/ContainerHelper.ts +++ b/project/src/helpers/ContainerHelper.ts @@ -1,14 +1,16 @@ import { injectable } from "tsyringe"; -export class FindSlotResult -{ - constructor(public success = false, public x?: number, public y?: number, public rotation = false) - {} +export class FindSlotResult { + constructor( + public success = false, + public x?: number, + public y?: number, + public rotation = false, + ) {} } @injectable() -export class ContainerHelper -{ +export class ContainerHelper { /** * Finds a slot for an item in a given 2D container map * @param container2D Array of container with slots filled/free @@ -16,8 +18,7 @@ export class ContainerHelper * @param itemHeight Height of item * @returns Location to place item in container */ - public findSlotForItem(container2D: number[][], itemWidth: number, itemHeight: number): FindSlotResult - { + public findSlotForItem(container2D: number[][], itemWidth: number, itemHeight: number): FindSlotResult { let rotation = false; const minVolume = (itemWidth < itemHeight ? itemWidth : itemHeight) - 1; const containerY = container2D.length; @@ -26,39 +27,32 @@ export class ContainerHelper const limitX = containerX - minVolume; // Every x+y slot taken up in container, exit - if (container2D.every((x) => x.every((y) => y === 1))) - { + if (container2D.every((x) => x.every((y) => y === 1))) { return new FindSlotResult(false); } // Down - for (let y = 0; y < limitY; y++) - { + for (let y = 0; y < limitY; y++) { // Across - if (container2D[y].every((x) => x === 1)) - { + if (container2D[y].every((x) => x === 1)) { // Every item in row is full, skip row continue; } - for (let x = 0; x < limitX; x++) - { + for (let x = 0; x < limitX; x++) { let foundSlot = this.locateSlot(container2D, containerX, containerY, x, y, itemWidth, itemHeight); // Failed to find slot, rotate item and try again - if (!foundSlot && itemWidth * itemHeight > 1) - { + if (!foundSlot && itemWidth * itemHeight > 1) { // Bigger than 1x1 foundSlot = this.locateSlot(container2D, containerX, containerY, x, y, itemHeight, itemWidth); // Height/Width swapped - if (foundSlot) - { + if (foundSlot) { // Found a slot for it when rotated rotation = true; } } - if (!foundSlot) - { + if (!foundSlot) { // Didn't fit this hole, try again continue; } @@ -90,36 +84,29 @@ export class ContainerHelper y: number, itemW: number, itemH: number, - ): boolean - { + ): boolean { let foundSlot = true; - for (let itemY = 0; itemY < itemH; itemY++) - { - if (foundSlot && y + itemH - 1 > containerY - 1) - { + for (let itemY = 0; itemY < itemH; itemY++) { + if (foundSlot && y + itemH - 1 > containerY - 1) { foundSlot = false; break; } // Does item fit x-ways across - for (let itemX = 0; itemX < itemW; itemX++) - { - if (foundSlot && x + itemW - 1 > containerX - 1) - { + for (let itemX = 0; itemX < itemW; itemX++) { + if (foundSlot && x + itemW - 1 > containerX - 1) { foundSlot = false; break; } - if (container2D[y + itemY][x + itemX] !== 0) - { + if (container2D[y + itemY][x + itemX] !== 0) { foundSlot = false; break; } } - if (!foundSlot) - { + if (!foundSlot) { break; } } @@ -143,23 +130,17 @@ export class ContainerHelper itemW: number, itemH: number, rotate: boolean, - ): void - { + ): void { // Swap height/width if we want to fit it in rotated const itemWidth = rotate ? itemH : itemW; const itemHeight = rotate ? itemW : itemH; - for (let tmpY = y; tmpY < y + itemHeight; tmpY++) - { - for (let tmpX = x; tmpX < x + itemWidth; tmpX++) - { - if (container2D[tmpY][tmpX] === 0) - { + for (let tmpY = y; tmpY < y + itemHeight; tmpY++) { + for (let tmpX = x; tmpX < x + itemWidth; tmpX++) { + if (container2D[tmpY][tmpX] === 0) { // Flag slot as used container2D[tmpY][tmpX] = 1; - } - else - { + } else { throw new Error(`Slot at (${x}, ${y}) is already filled. Cannot fit a ${itemW} by ${itemH}`); } } diff --git a/project/src/helpers/Dialogue/AbstractDialogueChatBot.ts b/project/src/helpers/Dialogue/AbstractDialogueChatBot.ts index dd26ba3b..2c147f7e 100644 --- a/project/src/helpers/Dialogue/AbstractDialogueChatBot.ts +++ b/project/src/helpers/Dialogue/AbstractDialogueChatBot.ts @@ -5,19 +5,15 @@ import { IUserDialogInfo } from "@spt/models/eft/profile/ISptProfile"; import { ILogger } from "@spt/models/spt/utils/ILogger"; import { MailSendService } from "@spt/services/MailSendService"; -export abstract class AbstractDialogueChatBot implements IDialogueChatBot -{ +export abstract class AbstractDialogueChatBot implements IDialogueChatBot { public constructor( protected logger: ILogger, protected mailSendService: MailSendService, protected chatCommands: IChatCommand[], - ) - {} + ) {} - public registerChatCommand(chatCommand: IChatCommand): void - { - if (this.chatCommands.some((cc) => cc.getCommandPrefix() === chatCommand.getCommandPrefix())) - { + public registerChatCommand(chatCommand: IChatCommand): void { + if (this.chatCommands.some((cc) => cc.getCommandPrefix() === chatCommand.getCommandPrefix())) { throw new Error( `The command "${chatCommand.getCommandPrefix()}" attempting to be registered already exists.`, ); @@ -29,10 +25,8 @@ export abstract class AbstractDialogueChatBot implements IDialogueChatBot protected abstract getUnrecognizedCommandMessage(): string; - public handleMessage(sessionId: string, request: ISendMessageRequest): string - { - if ((request.text ?? "").length === 0) - { + public handleMessage(sessionId: string, request: ISendMessageRequest): string { + if ((request.text ?? "").length === 0) { this.logger.error("Command came in as empty text! Invalid data!"); return request.dialogId; } @@ -40,32 +34,26 @@ export abstract class AbstractDialogueChatBot implements IDialogueChatBot const splitCommand = request.text.split(" "); const commandos = this.chatCommands.filter((c) => c.getCommandPrefix() === splitCommand[0]); - if (commandos[0]?.getCommands().has(splitCommand[1])) - { + if (commandos[0]?.getCommands().has(splitCommand[1])) { return commandos[0].handle(splitCommand[1], this.getChatBot(), sessionId, request); } - if (splitCommand[0].toLowerCase() === "help") - { + if (splitCommand[0].toLowerCase() === "help") { this.mailSendService.sendUserMessageToPlayer( sessionId, this.getChatBot(), "The available commands will be listed below:", ); // due to BSG being dumb with messages we need a mandatory timeout between messages so they get out on the right order - setTimeout(() => - { - for (const chatCommand of this.chatCommands) - { + setTimeout(() => { + for (const chatCommand of this.chatCommands) { this.mailSendService.sendUserMessageToPlayer( sessionId, this.getChatBot(), `Commands available for "${chatCommand.getCommandPrefix()}" prefix:`, ); - setTimeout(() => - { - for (const subCommand of chatCommand.getCommands()) - { + setTimeout(() => { + for (const subCommand of chatCommand.getCommands()) { this.mailSendService.sendUserMessageToPlayer( sessionId, this.getChatBot(), diff --git a/project/src/helpers/Dialogue/Commando/IChatCommand.ts b/project/src/helpers/Dialogue/Commando/IChatCommand.ts index 9f51b384..e1a9362e 100644 --- a/project/src/helpers/Dialogue/Commando/IChatCommand.ts +++ b/project/src/helpers/Dialogue/Commando/IChatCommand.ts @@ -1,10 +1,9 @@ import { ISendMessageRequest } from "@spt/models/eft/dialog/ISendMessageRequest"; import { IUserDialogInfo } from "@spt/models/eft/profile/ISptProfile"; -export interface IChatCommand -{ - getCommandPrefix(): string - getCommandHelp(command: string): string - getCommands(): Set - handle(command: string, commandHandler: IUserDialogInfo, sessionId: string, request: ISendMessageRequest): string +export interface IChatCommand { + getCommandPrefix(): string; + getCommandHelp(command: string): string; + getCommands(): Set; + handle(command: string, commandHandler: IUserDialogInfo, sessionId: string, request: ISendMessageRequest): string; } diff --git a/project/src/helpers/Dialogue/Commando/SptCommandoCommands.ts b/project/src/helpers/Dialogue/Commando/SptCommandoCommands.ts index 8a6e4d2f..5ce7ef6e 100644 --- a/project/src/helpers/Dialogue/Commando/SptCommandoCommands.ts +++ b/project/src/helpers/Dialogue/Commando/SptCommandoCommands.ts @@ -1,4 +1,3 @@ -import { inject, injectAll, injectable } from "tsyringe"; import { IChatCommand } from "@spt/helpers/Dialogue/Commando/IChatCommand"; import { ISptCommand } from "@spt/helpers/Dialogue/Commando/SptCommands/ISptCommand"; import { ISendMessageRequest } from "@spt/models/eft/dialog/ISendMessageRequest"; @@ -7,51 +6,49 @@ import { ConfigTypes } from "@spt/models/enums/ConfigTypes"; import { ICoreConfig } from "@spt/models/spt/config/ICoreConfig"; import { ConfigServer } from "@spt/servers/ConfigServer"; import { LocalisationService } from "@spt/services/LocalisationService"; +import { inject, injectAll, injectable } from "tsyringe"; @injectable() -export class SptCommandoCommands implements IChatCommand -{ +export class SptCommandoCommands implements IChatCommand { constructor( @inject("ConfigServer") protected configServer: ConfigServer, @inject("LocalisationService") protected localisationService: LocalisationService, @injectAll("SptCommand") protected sptCommands: ISptCommand[], - ) - { + ) { const coreConfigs = this.configServer.getConfig(ConfigTypes.CORE); // if give command is disabled or commando commands are disabled if ( !( - coreConfigs.features?.chatbotFeatures?.commandoFeatures?.giveCommandEnabled - && coreConfigs.features?.chatbotFeatures?.commandoEnabled + coreConfigs.features?.chatbotFeatures?.commandoFeatures?.giveCommandEnabled && + coreConfigs.features?.chatbotFeatures?.commandoEnabled ) - ) - { + ) { const giveCommand = this.sptCommands.find((c) => c.getCommand().toLocaleLowerCase() === "give"); this.sptCommands.splice(this.sptCommands.indexOf(giveCommand), 1); } } - public registerSptCommandoCommand(command: ISptCommand): void - { - if (this.sptCommands.some((c) => c.getCommand() === command.getCommand())) - { - throw new Error(this.localisationService.getText("chat-unable_to_register_command_already_registered", command.getCommand())); + public registerSptCommandoCommand(command: ISptCommand): void { + if (this.sptCommands.some((c) => c.getCommand() === command.getCommand())) { + throw new Error( + this.localisationService.getText( + "chat-unable_to_register_command_already_registered", + command.getCommand(), + ), + ); } this.sptCommands.push(command); } - public getCommandHelp(command: string): string - { + public getCommandHelp(command: string): string { return this.sptCommands.find((c) => c.getCommand() === command)?.getCommandHelp(); } - public getCommandPrefix(): string - { + public getCommandPrefix(): string { return "spt"; } - public getCommands(): Set - { + public getCommands(): Set { return new Set(this.sptCommands.map((c) => c.getCommand())); } @@ -60,8 +57,7 @@ export class SptCommandoCommands implements IChatCommand commandHandler: IUserDialogInfo, sessionId: string, request: ISendMessageRequest, - ): string - { + ): string { return this.sptCommands .find((c) => c.getCommand() === command) .performAction(commandHandler, sessionId, request); diff --git a/project/src/helpers/Dialogue/Commando/SptCommands/GiveCommand/GiveSptCommand.ts b/project/src/helpers/Dialogue/Commando/SptCommands/GiveCommand/GiveSptCommand.ts index ba03470d..9217fc97 100644 --- a/project/src/helpers/Dialogue/Commando/SptCommands/GiveCommand/GiveSptCommand.ts +++ b/project/src/helpers/Dialogue/Commando/SptCommands/GiveCommand/GiveSptCommand.ts @@ -1,5 +1,3 @@ -import { stringSimilarity } from "string-similarity-js"; -import { inject, injectable } from "tsyringe"; import { SavedCommand } from "@spt/helpers/Dialogue/Commando/SptCommands/GiveCommand/SavedCommand"; import { ISptCommand } from "@spt/helpers/Dialogue/Commando/SptCommands/ISptCommand"; import { ItemHelper } from "@spt/helpers/ItemHelper"; @@ -15,12 +13,13 @@ import { DatabaseService } from "@spt/services/DatabaseService"; import { ItemFilterService } from "@spt/services/ItemFilterService"; import { LocaleService } from "@spt/services/LocaleService"; import { MailSendService } from "@spt/services/MailSendService"; -import { ICloner } from "@spt/utils/cloners/ICloner"; import { HashUtil } from "@spt/utils/HashUtil"; +import { ICloner } from "@spt/utils/cloners/ICloner"; +import { stringSimilarity } from "string-similarity-js"; +import { inject, injectable } from "tsyringe"; @injectable() -export class GiveSptCommand implements ISptCommand -{ +export class GiveSptCommand implements ISptCommand { /** * Regex to account for all these cases: * spt give "item name" 5 @@ -50,23 +49,18 @@ export class GiveSptCommand implements ISptCommand @inject("DatabaseService") protected databaseService: DatabaseService, @inject("ItemFilterService") protected itemFilterService: ItemFilterService, @inject("PrimaryCloner") protected cloner: ICloner, - ) - {} + ) {} - public getCommand(): string - { + public getCommand(): string { return "give"; } - public getCommandHelp(): string - { + public getCommandHelp(): string { return 'spt give\n========\nSends items to the player through the message system.\n\n\tspt give [template ID] [quantity]\n\t\tEx: spt give 544fb25a4bdc2dfb738b4567 2\n\n\tspt give ["item name"] [quantity]\n\t\tEx: spt give "pack of sugar" 10\n\n\tspt give [locale] ["item name"] [quantity]\n\t\tEx: spt give fr "figurine de chat" 3'; } - public performAction(commandHandler: IUserDialogInfo, sessionId: string, request: ISendMessageRequest): string - { - if (!GiveSptCommand.commandRegex.test(request.text)) - { + public performAction(commandHandler: IUserDialogInfo, sessionId: string, request: ISendMessageRequest): string { + if (!GiveSptCommand.commandRegex.test(request.text)) { this.mailSendService.sendUserMessageToPlayer( sessionId, commandHandler, @@ -83,10 +77,8 @@ export class GiveSptCommand implements ISptCommand let locale: string; // This is a reply to a give request previously made pending a reply - if (result[1] === undefined) - { - if (!this.savedCommand.has(sessionId)) - { + if (result[1] === undefined) { + if (!this.savedCommand.has(sessionId)) { this.mailSendService.sendUserMessageToPlayer( sessionId, commandHandler, @@ -95,8 +87,7 @@ export class GiveSptCommand implements ISptCommand return request.dialogId; } const savedCommand = this.savedCommand.get(sessionId); - if (+result[6] > savedCommand.potentialItemNames.length) - { + if (+result[6] > savedCommand.potentialItemNames.length) { this.mailSendService.sendUserMessageToPlayer( sessionId, commandHandler, @@ -109,19 +100,15 @@ export class GiveSptCommand implements ISptCommand locale = savedCommand.locale; isItemName = true; this.savedCommand.delete(sessionId); - } - else - { + } else { // A new give request was entered, we need to ignore the old saved command - if (this.savedCommand.has(sessionId)) - { + if (this.savedCommand.has(sessionId)) { this.savedCommand.delete(sessionId); } isItemName = result[5] !== undefined; item = result[5] ? result[5] : result[2]; quantity = +result[6]; - if (quantity <= 0) - { + if (quantity <= 0) { this.mailSendService.sendUserMessageToPlayer( sessionId, commandHandler, @@ -130,14 +117,10 @@ export class GiveSptCommand implements ISptCommand return request.dialogId; } - if (isItemName) - { - try - { + if (isItemName) { + try { locale = result[4] ? result[4] : this.localeService.getDesiredGameLocale() ?? "en"; - } - catch (e) - { + } catch (e) { this.mailSendService.sendUserMessageToPlayer( sessionId, commandHandler, @@ -147,9 +130,8 @@ export class GiveSptCommand implements ISptCommand locale = "en"; } - const localizedGlobal - = this.databaseService.getLocales().global[locale] - ?? this.databaseService.getLocales().global.en; + const localizedGlobal = + this.databaseService.getLocales().global[locale] ?? this.databaseService.getLocales().global.en; const closestItemsMatchedByName = this.itemHelper .getItems() @@ -162,12 +144,9 @@ export class GiveSptCommand implements ISptCommand })) .sort((a1, a2) => a2.match - a1.match); - if (closestItemsMatchedByName[0].match >= GiveSptCommand.acceptableConfidence) - { + if (closestItemsMatchedByName[0].match >= GiveSptCommand.acceptableConfidence) { item = closestItemsMatchedByName[0].itemName; - } - else - { + } else { let i = 1; const slicedItems = closestItemsMatchedByName.slice(0, 10); // max 10 item names and map them @@ -192,20 +171,19 @@ export class GiveSptCommand implements ISptCommand } } - const localizedGlobal = this.databaseService.getLocales().global[locale] - ?? this.databaseService.getLocales().global.en; + const localizedGlobal = + this.databaseService.getLocales().global[locale] ?? this.databaseService.getLocales().global.en; // If item is an item name, we need to search using that item name and the locale which one we want otherwise // item is just the tplId. const tplId = isItemName ? this.itemHelper - .getItems() - .filter((i) => this.isItemAllowed(i)) - .find((i) => (localizedGlobal[`${i?._id} Name`]?.toLowerCase() ?? i._props.Name) === item)._id + .getItems() + .filter((i) => this.isItemAllowed(i)) + .find((i) => (localizedGlobal[`${i?._id} Name`]?.toLowerCase() ?? i._props.Name) === item)._id : item; const checkedItem = this.itemHelper.getItem(tplId); - if (!checkedItem[0]) - { + if (!checkedItem[0]) { this.mailSendService.sendUserMessageToPlayer( sessionId, commandHandler, @@ -216,53 +194,39 @@ export class GiveSptCommand implements ISptCommand const itemsToSend: Item[] = []; const preset = this.presetHelper.getDefaultPreset(checkedItem[1]._id); - if (preset && !GiveSptCommand.excludedPresetItems.has(checkedItem[1]._id)) - { - for (let i = 0; i < quantity; i++) - { + if (preset && !GiveSptCommand.excludedPresetItems.has(checkedItem[1]._id)) { + for (let i = 0; i < quantity; i++) { let items = this.cloner.clone(preset._items); items = this.itemHelper.replaceIDs(items); itemsToSend.push(...items); } - } - else if (this.itemHelper.isOfBaseclass(checkedItem[1]._id, BaseClasses.AMMO_BOX)) - { - for (let i = 0; i < quantity; i++) - { + } else if (this.itemHelper.isOfBaseclass(checkedItem[1]._id, BaseClasses.AMMO_BOX)) { + for (let i = 0; i < quantity; i++) { const ammoBoxArray: Item[] = []; ammoBoxArray.push({ _id: this.hashUtil.generate(), _tpl: checkedItem[1]._id }); // DO NOT generate the ammo box cartridges, the mail service does it for us! :) // this.itemHelper.addCartridgesToAmmoBox(ammoBoxArray, checkedItem[1]); itemsToSend.push(...ammoBoxArray); } - } - else - { - if (checkedItem[1]._props.StackMaxSize === 1) - { - for (let i = 0; i < quantity; i++) - { + } else { + if (checkedItem[1]._props.StackMaxSize === 1) { + for (let i = 0; i < quantity; i++) { itemsToSend.push({ _id: this.hashUtil.generate(), _tpl: checkedItem[1]._id, upd: this.itemHelper.generateUpdForItem(checkedItem[1]), }); } - } - else - { + } else { const item: Item = { _id: this.hashUtil.generate(), _tpl: checkedItem[1]._id, upd: this.itemHelper.generateUpdForItem(checkedItem[1]), }; item.upd.StackObjectsCount = quantity; - try - { + try { itemsToSend.push(...this.itemHelper.splitStack(item)); - } - catch - { + } catch { this.mailSendService.sendUserMessageToPlayer( sessionId, commandHandler, @@ -285,17 +249,16 @@ export class GiveSptCommand implements ISptCommand * @param templateItem the template item to check * @returns true if its obtainable, false if its not */ - protected isItemAllowed(templateItem: ITemplateItem): boolean - { + protected isItemAllowed(templateItem: ITemplateItem): boolean { return ( - templateItem._type !== "Node" - && !this.itemHelper.isQuestItem(templateItem._id) - && !this.itemFilterService.isItemBlacklisted(templateItem._id) - && (templateItem._props?.Prefab?.path ?? "") !== "" - && !this.itemHelper.isOfBaseclass(templateItem._id, BaseClasses.HIDEOUT_AREA_CONTAINER) - && !this.itemHelper.isOfBaseclass(templateItem._id, BaseClasses.LOOT_CONTAINER) - && !this.itemHelper.isOfBaseclass(templateItem._id, BaseClasses.RANDOM_LOOT_CONTAINER) - && !this.itemHelper.isOfBaseclass(templateItem._id, BaseClasses.MOB_CONTAINER) + templateItem._type !== "Node" && + !this.itemHelper.isQuestItem(templateItem._id) && + !this.itemFilterService.isItemBlacklisted(templateItem._id) && + (templateItem._props?.Prefab?.path ?? "") !== "" && + !this.itemHelper.isOfBaseclass(templateItem._id, BaseClasses.HIDEOUT_AREA_CONTAINER) && + !this.itemHelper.isOfBaseclass(templateItem._id, BaseClasses.LOOT_CONTAINER) && + !this.itemHelper.isOfBaseclass(templateItem._id, BaseClasses.RANDOM_LOOT_CONTAINER) && + !this.itemHelper.isOfBaseclass(templateItem._id, BaseClasses.MOB_CONTAINER) ); } } diff --git a/project/src/helpers/Dialogue/Commando/SptCommands/GiveCommand/SavedCommand.ts b/project/src/helpers/Dialogue/Commando/SptCommands/GiveCommand/SavedCommand.ts index 39515ace..1a2abb74 100644 --- a/project/src/helpers/Dialogue/Commando/SptCommands/GiveCommand/SavedCommand.ts +++ b/project/src/helpers/Dialogue/Commando/SptCommands/GiveCommand/SavedCommand.ts @@ -1,9 +1,7 @@ -export class SavedCommand -{ +export class SavedCommand { public constructor( public quantity: number, public potentialItemNames: string[], public locale: string, - ) - {} + ) {} } diff --git a/project/src/helpers/Dialogue/Commando/SptCommands/ISptCommand.ts b/project/src/helpers/Dialogue/Commando/SptCommands/ISptCommand.ts index 0c76ffb3..3c562a20 100644 --- a/project/src/helpers/Dialogue/Commando/SptCommands/ISptCommand.ts +++ b/project/src/helpers/Dialogue/Commando/SptCommands/ISptCommand.ts @@ -1,9 +1,8 @@ import { ISendMessageRequest } from "@spt/models/eft/dialog/ISendMessageRequest"; import { IUserDialogInfo } from "@spt/models/eft/profile/ISptProfile"; -export interface ISptCommand -{ - getCommand(): string - getCommandHelp(): string - performAction(commandHandler: IUserDialogInfo, sessionId: string, request: ISendMessageRequest): string +export interface ISptCommand { + getCommand(): string; + getCommandHelp(): string; + performAction(commandHandler: IUserDialogInfo, sessionId: string, request: ISendMessageRequest): string; } diff --git a/project/src/helpers/Dialogue/Commando/SptCommands/ProfileCommand/ProfileSptCommand.ts b/project/src/helpers/Dialogue/Commando/SptCommands/ProfileCommand/ProfileSptCommand.ts index 775c1716..99dbd05c 100644 --- a/project/src/helpers/Dialogue/Commando/SptCommands/ProfileCommand/ProfileSptCommand.ts +++ b/project/src/helpers/Dialogue/Commando/SptCommands/ProfileCommand/ProfileSptCommand.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { SavedCommand } from "@spt/helpers/Dialogue/Commando/SptCommands/GiveCommand/SavedCommand"; import { ISptCommand } from "@spt/helpers/Dialogue/Commando/SptCommands/ISptCommand"; import { ItemHelper } from "@spt/helpers/ItemHelper"; @@ -14,17 +13,17 @@ import { DatabaseServer } from "@spt/servers/DatabaseServer"; import { LocaleService } from "@spt/services/LocaleService"; import { MailSendService } from "@spt/services/MailSendService"; import { HashUtil } from "@spt/utils/HashUtil"; +import { inject, injectable } from "tsyringe"; @injectable() -export class ProfileSptCommand implements ISptCommand -{ +export class ProfileSptCommand implements ISptCommand { /** * Regex to account for all these cases: * spt profile level 20 * spt profile skill metabolism 10 */ - private static commandRegex - = /^spt profile (?level|skill)((?<=.*skill) (?[\w]+)){0,1} (?(?!0+)[0-9]+)$/; + private static commandRegex = + /^spt profile (?level|skill)((?<=.*skill) (?[\w]+)){0,1} (?(?!0+)[0-9]+)$/; protected savedCommand: SavedCommand; @@ -37,23 +36,18 @@ export class ProfileSptCommand implements ISptCommand @inject("LocaleService") protected localeService: LocaleService, @inject("DatabaseServer") protected databaseServer: DatabaseServer, @inject("ProfileHelper") protected profileHelper: ProfileHelper, - ) - {} + ) {} - public getCommand(): string - { + public getCommand(): string { return "profile"; } - public getCommandHelp(): string - { + public getCommandHelp(): string { return "spt profile\n========\nSets the profile level or skill to the desired level through the message system.\n\n\tspt profile level [desired level]\n\t\tEx: spt profile level 20\n\n\tspt profile skill [skill name] [quantity]\n\t\tEx: spt profile skill metabolism 51"; } - public performAction(commandHandler: IUserDialogInfo, sessionId: string, request: ISendMessageRequest): string - { - if (!ProfileSptCommand.commandRegex.test(request.text)) - { + public performAction(commandHandler: IUserDialogInfo, sessionId: string, request: ISendMessageRequest): string { + if (!ProfileSptCommand.commandRegex.test(request.text)) { this.mailSendService.sendUserMessageToPlayer( sessionId, commandHandler, @@ -69,11 +63,9 @@ export class ProfileSptCommand implements ISptCommand const quantity: number = +result.groups.quantity; let event: IProfileChangeEvent; - switch (command) - { + switch (command) { case "level": - if (quantity < 1 || quantity > this.profileHelper.getMaxLevel()) - { + if (quantity < 1 || quantity > this.profileHelper.getMaxLevel()) { this.mailSendService.sendUserMessageToPlayer( sessionId, commandHandler, @@ -83,14 +75,12 @@ export class ProfileSptCommand implements ISptCommand } event = this.handleLevelCommand(quantity); break; - case "skill": - { + case "skill": { const enumSkill = Object.values(SkillTypes).find( (t) => t.toLocaleLowerCase() === skill.toLocaleLowerCase(), ); - if (enumSkill === undefined) - { + if (enumSkill === undefined) { this.mailSendService.sendUserMessageToPlayer( sessionId, commandHandler, @@ -99,8 +89,7 @@ export class ProfileSptCommand implements ISptCommand return request.dialogId; } - if (quantity < 0 || quantity > 51) - { + if (quantity < 0 || quantity > 51) { this.mailSendService.sendUserMessageToPlayer( sessionId, commandHandler, @@ -138,8 +127,7 @@ export class ProfileSptCommand implements ISptCommand return request.dialogId; } - protected handleSkillCommand(skill: string, level: number): IProfileChangeEvent - { + protected handleSkillCommand(skill: string, level: number): IProfileChangeEvent { const event: IProfileChangeEvent = { _id: this.hashUtil.generate(), Type: ProfileChangeEventType.SKILL_POINTS, @@ -149,8 +137,7 @@ export class ProfileSptCommand implements ISptCommand return event; } - protected handleLevelCommand(level: number): IProfileChangeEvent - { + protected handleLevelCommand(level: number): IProfileChangeEvent { const exp = this.profileHelper.getExperience(level); const event: IProfileChangeEvent = { _id: this.hashUtil.generate(), diff --git a/project/src/helpers/Dialogue/Commando/SptCommands/TraderCommand/TraderSptCommand.ts b/project/src/helpers/Dialogue/Commando/SptCommands/TraderCommand/TraderSptCommand.ts index 7690306c..568246d3 100644 --- a/project/src/helpers/Dialogue/Commando/SptCommands/TraderCommand/TraderSptCommand.ts +++ b/project/src/helpers/Dialogue/Commando/SptCommands/TraderCommand/TraderSptCommand.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { SavedCommand } from "@spt/helpers/Dialogue/Commando/SptCommands/GiveCommand/SavedCommand"; import { ISptCommand } from "@spt/helpers/Dialogue/Commando/SptCommands/ISptCommand"; import { ItemHelper } from "@spt/helpers/ItemHelper"; @@ -12,10 +11,10 @@ import { DatabaseService } from "@spt/services/DatabaseService"; import { LocaleService } from "@spt/services/LocaleService"; import { MailSendService } from "@spt/services/MailSendService"; import { HashUtil } from "@spt/utils/HashUtil"; +import { inject, injectable } from "tsyringe"; @injectable() -export class TraderSptCommand implements ISptCommand -{ +export class TraderSptCommand implements ISptCommand { /** * Regex to account for all these cases: * spt trader prapor rep 100 @@ -33,23 +32,18 @@ export class TraderSptCommand implements ISptCommand @inject("MailSendService") protected mailSendService: MailSendService, @inject("LocaleService") protected localeService: LocaleService, @inject("DatabaseService") protected databaseService: DatabaseService, - ) - {} + ) {} - public getCommand(): string - { + public getCommand(): string { return "trader"; } - public getCommandHelp(): string - { + public getCommandHelp(): string { return "spt trader\n========\nSets the reputation or money spent to the input quantity through the message system.\n\n\tspt trader [trader] rep [quantity]\n\t\tEx: spt trader prapor rep 2\n\n\tspt trader [trader] spend [quantity]\n\t\tEx: spt trader therapist spend 1000000"; } - public performAction(commandHandler: IUserDialogInfo, sessionId: string, request: ISendMessageRequest): string - { - if (!TraderSptCommand.commandRegex.test(request.text)) - { + public performAction(commandHandler: IUserDialogInfo, sessionId: string, request: ISendMessageRequest): string { + if (!TraderSptCommand.commandRegex.test(request.text)) { this.mailSendService.sendUserMessageToPlayer( sessionId, commandHandler, @@ -67,8 +61,7 @@ export class TraderSptCommand implements ISptCommand const dbTrader = Object.values(this.databaseService.getTraders()).find( (t) => t.base.nickname.toLocaleLowerCase() === trader.toLocaleLowerCase(), ); - if (dbTrader === undefined) - { + if (dbTrader === undefined) { this.mailSendService.sendUserMessageToPlayer( sessionId, commandHandler, @@ -77,8 +70,7 @@ export class TraderSptCommand implements ISptCommand return request.dialogId; } let profileChangeEventType: ProfileChangeEventType; - switch (command) - { + switch (command) { case "rep": profileChangeEventType = ProfileChangeEventType.TRADER_STANDING; break; diff --git a/project/src/helpers/Dialogue/CommandoDialogueChatBot.ts b/project/src/helpers/Dialogue/CommandoDialogueChatBot.ts index 83b55a08..ecb68874 100644 --- a/project/src/helpers/Dialogue/CommandoDialogueChatBot.ts +++ b/project/src/helpers/Dialogue/CommandoDialogueChatBot.ts @@ -1,25 +1,22 @@ -import { inject, injectAll, injectable } from "tsyringe"; import { AbstractDialogueChatBot } from "@spt/helpers/Dialogue/AbstractDialogueChatBot"; import { IChatCommand } from "@spt/helpers/Dialogue/Commando/IChatCommand"; import { IUserDialogInfo } from "@spt/models/eft/profile/ISptProfile"; import { MemberCategory } from "@spt/models/enums/MemberCategory"; import { ILogger } from "@spt/models/spt/utils/ILogger"; import { MailSendService } from "@spt/services/MailSendService"; +import { inject, injectAll, injectable } from "tsyringe"; @injectable() -export class CommandoDialogueChatBot extends AbstractDialogueChatBot -{ +export class CommandoDialogueChatBot extends AbstractDialogueChatBot { public constructor( - @inject("PrimaryLogger") logger: ILogger, + @inject("PrimaryLogger") logger: ILogger, @inject("MailSendService") mailSendService: MailSendService, @injectAll("CommandoCommand") chatCommands: IChatCommand[], - ) - { + ) { super(logger, mailSendService, chatCommands); } - public getChatBot(): IUserDialogInfo - { + public getChatBot(): IUserDialogInfo { return { _id: "sptCommando", aid: 1234567, @@ -33,8 +30,7 @@ export class CommandoDialogueChatBot extends AbstractDialogueChatBot }; } - protected getUnrecognizedCommandMessage(): string - { + protected getUnrecognizedCommandMessage(): string { return "I'm sorry soldier, I don't recognize the command you are trying to use! Type \"help\" to see available commands."; } } diff --git a/project/src/helpers/Dialogue/IDialogueChatBot.ts b/project/src/helpers/Dialogue/IDialogueChatBot.ts index 677d1e63..38b3d21e 100644 --- a/project/src/helpers/Dialogue/IDialogueChatBot.ts +++ b/project/src/helpers/Dialogue/IDialogueChatBot.ts @@ -1,8 +1,7 @@ import { ISendMessageRequest } from "@spt/models/eft/dialog/ISendMessageRequest"; import { IUserDialogInfo } from "@spt/models/eft/profile/ISptProfile"; -export interface IDialogueChatBot -{ - getChatBot(): IUserDialogInfo - handleMessage(sessionId: string, request: ISendMessageRequest): string +export interface IDialogueChatBot { + getChatBot(): IUserDialogInfo; + handleMessage(sessionId: string, request: ISendMessageRequest): string; } diff --git a/project/src/helpers/Dialogue/SptDialogueChatBot.ts b/project/src/helpers/Dialogue/SptDialogueChatBot.ts index 1eeb348c..fcc4fe93 100644 --- a/project/src/helpers/Dialogue/SptDialogueChatBot.ts +++ b/project/src/helpers/Dialogue/SptDialogueChatBot.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { IDialogueChatBot } from "@spt/helpers/Dialogue/IDialogueChatBot"; import { ProfileHelper } from "@spt/helpers/ProfileHelper"; import { ISendMessageRequest } from "@spt/models/eft/dialog/ISendMessageRequest"; @@ -13,10 +12,10 @@ import { ConfigServer } from "@spt/servers/ConfigServer"; import { GiftService } from "@spt/services/GiftService"; import { MailSendService } from "@spt/services/MailSendService"; import { RandomUtil } from "@spt/utils/RandomUtil"; +import { inject, injectable } from "tsyringe"; @injectable() -export class SptDialogueChatBot implements IDialogueChatBot -{ +export class SptDialogueChatBot implements IDialogueChatBot { protected coreConfig: ICoreConfig; protected weatherConfig: IWeatherConfig; @@ -26,14 +25,12 @@ export class SptDialogueChatBot implements IDialogueChatBot @inject("MailSendService") protected mailSendService: MailSendService, @inject("GiftService") protected giftService: GiftService, @inject("ConfigServer") protected configServer: ConfigServer, - ) - { + ) { this.coreConfig = this.configServer.getConfig(ConfigTypes.CORE); this.weatherConfig = this.configServer.getConfig(ConfigTypes.WEATHER); } - public getChatBot(): IUserDialogInfo - { + public getChatBot(): IUserDialogInfo { return { _id: "sptFriend", aid: 1234566, @@ -52,8 +49,7 @@ export class SptDialogueChatBot implements IDialogueChatBot * @param sessionId Session Id * @param request send message request */ - public handleMessage(sessionId: string, request: ISendMessageRequest): string - { + public handleMessage(sessionId: string, request: ISendMessageRequest): string { const sender = this.profileHelper.getPmcProfile(sessionId); const sptFriendUser = this.getChatBot(); @@ -62,8 +58,7 @@ export class SptDialogueChatBot implements IDialogueChatBot const requestInput = request.text.toLowerCase(); - if (giftSent === GiftSentResult.SUCCESS) - { + if (giftSent === GiftSentResult.SUCCESS) { this.mailSendService.sendUserMessageToPlayer( sessionId, sptFriendUser, @@ -77,8 +72,7 @@ export class SptDialogueChatBot implements IDialogueChatBot return; } - if (giftSent === GiftSentResult.FAILED_GIFT_ALREADY_RECEIVED) - { + if (giftSent === GiftSentResult.FAILED_GIFT_ALREADY_RECEIVED) { this.mailSendService.sendUserMessageToPlayer( sessionId, sptFriendUser, @@ -88,8 +82,7 @@ export class SptDialogueChatBot implements IDialogueChatBot return; } - if (requestInput.includes("love you")) - { + if (requestInput.includes("love you")) { this.mailSendService.sendUserMessageToPlayer( sessionId, sptFriendUser, @@ -102,8 +95,7 @@ export class SptDialogueChatBot implements IDialogueChatBot ); } - if (requestInput === "spt") - { + if (requestInput === "spt") { this.mailSendService.sendUserMessageToPlayer( sessionId, sptFriendUser, @@ -111,8 +103,7 @@ export class SptDialogueChatBot implements IDialogueChatBot ); } - if (["hello", "hi", "sup", "yo", "hey"].includes(requestInput)) - { + if (["hello", "hi", "sup", "yo", "hey"].includes(requestInput)) { this.mailSendService.sendUserMessageToPlayer( sessionId, sptFriendUser, @@ -131,8 +122,7 @@ export class SptDialogueChatBot implements IDialogueChatBot ); } - if (requestInput === "nikita") - { + if (requestInput === "nikita") { this.mailSendService.sendUserMessageToPlayer( sessionId, sptFriendUser, @@ -145,8 +135,7 @@ export class SptDialogueChatBot implements IDialogueChatBot ); } - if (requestInput === "are you a bot") - { + if (requestInput === "are you a bot") { this.mailSendService.sendUserMessageToPlayer( sessionId, sptFriendUser, @@ -154,8 +143,7 @@ export class SptDialogueChatBot implements IDialogueChatBot ); } - if (requestInput === "itsonlysnowalan") - { + if (requestInput === "itsonlysnowalan") { this.weatherConfig.overrideSeason = Season.WINTER; this.mailSendService.sendUserMessageToPlayer( @@ -165,24 +153,16 @@ export class SptDialogueChatBot implements IDialogueChatBot ); } - if (requestInput === "givemespace") - { + if (requestInput === "givemespace") { const stashRowGiftId = "StashRows"; const maxGiftsToSendCount = this.coreConfig.features.chatbotFeatures.commandUseLimits[stashRowGiftId] ?? 5; - if ( - this.profileHelper.playerHasRecievedMaxNumberOfGift( - sessionId, - stashRowGiftId, - maxGiftsToSendCount)) - { + if (this.profileHelper.playerHasRecievedMaxNumberOfGift(sessionId, stashRowGiftId, maxGiftsToSendCount)) { this.mailSendService.sendUserMessageToPlayer( sessionId, sptFriendUser, "You cannot accept any more of this gift", ); - } - else - { + } else { this.profileHelper.addStashRowsBonusToProfile(sessionId, 2); this.mailSendService.sendUserMessageToPlayer( @@ -191,11 +171,7 @@ export class SptDialogueChatBot implements IDialogueChatBot this.randomUtil.getArrayValue(["Added 2 rows to stash, please restart your game to see them"]), ); - this.profileHelper.flagGiftReceivedInProfile( - sessionId, - stashRowGiftId, - maxGiftsToSendCount, - ); + this.profileHelper.flagGiftReceivedInProfile(sessionId, stashRowGiftId, maxGiftsToSendCount); } } diff --git a/project/src/helpers/DialogueHelper.ts b/project/src/helpers/DialogueHelper.ts index 38c19a0c..361896d6 100644 --- a/project/src/helpers/DialogueHelper.ts +++ b/project/src/helpers/DialogueHelper.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { ItemHelper } from "@spt/helpers/ItemHelper"; import { NotificationSendHelper } from "@spt/helpers/NotificationSendHelper"; import { NotifierHelper } from "@spt/helpers/NotifierHelper"; @@ -9,10 +8,10 @@ import { DatabaseServer } from "@spt/servers/DatabaseServer"; import { SaveServer } from "@spt/servers/SaveServer"; import { LocalisationService } from "@spt/services/LocalisationService"; import { HashUtil } from "@spt/utils/HashUtil"; +import { inject, injectable } from "tsyringe"; @injectable() -export class DialogueHelper -{ +export class DialogueHelper { constructor( @inject("PrimaryLogger") protected logger: ILogger, @inject("HashUtil") protected hashUtil: HashUtil, @@ -22,16 +21,14 @@ export class DialogueHelper @inject("NotificationSendHelper") protected notificationSendHelper: NotificationSendHelper, @inject("LocalisationService") protected localisationService: LocalisationService, @inject("ItemHelper") protected itemHelper: ItemHelper, - ) - {} + ) {} /** * Get the preview contents of the last message in a dialogue. * @param dialogue * @returns MessagePreview */ - public getMessagePreview(dialogue: Dialogue): MessagePreview - { + public getMessagePreview(dialogue: Dialogue): MessagePreview { // The last message of the dialogue should be shown on the preview. const message = dialogue.messages[dialogue.messages.length - 1]; const result: MessagePreview = { @@ -41,13 +38,11 @@ export class DialogueHelper uid: dialogue._id, }; - if (message?.text) - { + if (message?.text) { result.text = message.text; } - if (message?.systemData) - { + if (message?.systemData) { result.systemData = message.systemData; } @@ -61,35 +56,28 @@ export class DialogueHelper * @param itemId Item being moved to inventory * @returns */ - public getMessageItemContents(messageID: string, sessionID: string, itemId: string): Item[] - { + public getMessageItemContents(messageID: string, sessionID: string, itemId: string): Item[] { const dialogueData = this.saveServer.getProfile(sessionID).dialogues; - for (const dialogueId in dialogueData) - { + for (const dialogueId in dialogueData) { const message = dialogueData[dialogueId].messages.find((x) => x._id === messageID); - if (!message) - { + if (!message) { continue; } - if (message._id === messageID) - { + if (message._id === messageID) { const attachmentsNew = this.saveServer.getProfile(sessionID).dialogues[dialogueId].attachmentsNew; - if (attachmentsNew > 0) - { + if (attachmentsNew > 0) { this.saveServer.getProfile(sessionID).dialogues[dialogueId].attachmentsNew = attachmentsNew - 1; } // Check reward count when item being moved isn't in reward list // If count is 0, it means after this move occurs the reward array will be empty and all rewards collected - if (!message.items.data) - { + if (!message.items.data) { message.items.data = []; } const rewardItemCount = message.items.data?.filter((item) => item._id !== itemId); - if (rewardItemCount.length === 0) - { + if (rewardItemCount.length === 0) { message.rewardCollected = true; message.hasRewards = false; } @@ -106,11 +94,9 @@ export class DialogueHelper * @param sessionId Session/player id * @returns Dialog dictionary */ - public getDialogsForProfile(sessionId: string): Record - { + public getDialogsForProfile(sessionId: string): Record { const profile = this.saveServer.getProfile(sessionId); - if (!profile.dialogues) - { + if (!profile.dialogues) { profile.dialogues = {}; } diff --git a/project/src/helpers/DurabilityLimitsHelper.ts b/project/src/helpers/DurabilityLimitsHelper.ts index b7934228..8f3706bf 100644 --- a/project/src/helpers/DurabilityLimitsHelper.ts +++ b/project/src/helpers/DurabilityLimitsHelper.ts @@ -1,22 +1,20 @@ -import { inject, injectable } from "tsyringe"; import { BotHelper } from "@spt/helpers/BotHelper"; import { ITemplateItem } from "@spt/models/eft/common/tables/ITemplateItem"; import { ConfigTypes } from "@spt/models/enums/ConfigTypes"; import { IBotConfig } from "@spt/models/spt/config/IBotConfig"; import { ConfigServer } from "@spt/servers/ConfigServer"; import { RandomUtil } from "@spt/utils/RandomUtil"; +import { inject, injectable } from "tsyringe"; @injectable() -export class DurabilityLimitsHelper -{ +export class DurabilityLimitsHelper { protected botConfig: IBotConfig; constructor( @inject("RandomUtil") protected randomUtil: RandomUtil, @inject("BotHelper") protected botHelper: BotHelper, @inject("ConfigServer") protected configServer: ConfigServer, - ) - { + ) { this.botConfig = this.configServer.getConfig(ConfigTypes.BOT); } @@ -26,20 +24,16 @@ export class DurabilityLimitsHelper * @param botRole Role of bot to get max durability for * @returns Max durability of weapon */ - public getRandomizedMaxWeaponDurability(itemTemplate: ITemplateItem, botRole?: string): number - { - if (botRole && this.botHelper.isBotPmc(botRole)) - { + public getRandomizedMaxWeaponDurability(itemTemplate: ITemplateItem, botRole?: string): number { + if (botRole && this.botHelper.isBotPmc(botRole)) { return this.generateMaxWeaponDurability("pmc"); } - if (botRole && this.botHelper.isBotBoss(botRole)) - { + if (botRole && this.botHelper.isBotBoss(botRole)) { return this.generateMaxWeaponDurability("boss"); } - if (botRole && this.botHelper.isBotFollower(botRole)) - { + if (botRole && this.botHelper.isBotFollower(botRole)) { return this.generateMaxWeaponDurability("follower"); } @@ -52,22 +46,18 @@ export class DurabilityLimitsHelper * @param botRole Role of bot to get max durability for * @returns max durability */ - public getRandomizedMaxArmorDurability(itemTemplate: ITemplateItem, botRole?: string): number - { + public getRandomizedMaxArmorDurability(itemTemplate: ITemplateItem, botRole?: string): number { const itemMaxDurability = itemTemplate._props.MaxDurability!; - if (botRole && this.botHelper.isBotPmc(botRole)) - { + if (botRole && this.botHelper.isBotPmc(botRole)) { return this.generateMaxPmcArmorDurability(itemMaxDurability); } - if (botRole && this.botHelper.isBotBoss(botRole)) - { + if (botRole && this.botHelper.isBotBoss(botRole)) { return itemMaxDurability; } - if (botRole && this.botHelper.isBotFollower(botRole)) - { + if (botRole && this.botHelper.isBotFollower(botRole)) { return itemMaxDurability; } @@ -85,20 +75,16 @@ export class DurabilityLimitsHelper itemTemplate: ITemplateItem, botRole: string | undefined, maxDurability: number, - ): number - { - if (botRole && this.botHelper.isBotPmc(botRole)) - { + ): number { + if (botRole && this.botHelper.isBotPmc(botRole)) { return this.generateWeaponDurability("pmc", maxDurability); } - if (botRole && this.botHelper.isBotBoss(botRole)) - { + if (botRole && this.botHelper.isBotBoss(botRole)) { return this.generateWeaponDurability("boss", maxDurability); } - if (botRole && this.botHelper.isBotFollower(botRole)) - { + if (botRole && this.botHelper.isBotFollower(botRole)) { return this.generateWeaponDurability("follower", maxDurability); } @@ -116,36 +102,30 @@ export class DurabilityLimitsHelper itemTemplate: ITemplateItem, botRole: string | undefined, maxDurability: number, - ): number - { - if (botRole && this.botHelper.isBotPmc(botRole)) - { + ): number { + if (botRole && this.botHelper.isBotPmc(botRole)) { return this.generateArmorDurability("pmc", maxDurability); } - if (botRole && this.botHelper.isBotBoss(botRole)) - { + if (botRole && this.botHelper.isBotBoss(botRole)) { return this.generateArmorDurability("boss", maxDurability); } - if (botRole && this.botHelper.isBotFollower(botRole)) - { + if (botRole && this.botHelper.isBotFollower(botRole)) { return this.generateArmorDurability("follower", maxDurability); } return this.generateArmorDurability(botRole, maxDurability); } - protected generateMaxWeaponDurability(botRole?: string): number - { + protected generateMaxWeaponDurability(botRole?: string): number { const lowestMax = this.getLowestMaxWeaponFromConfig(botRole); const highestMax = this.getHighestMaxWeaponDurabilityFromConfig(botRole); return this.randomUtil.getInt(lowestMax, highestMax); } - protected generateMaxPmcArmorDurability(itemMaxDurability: number): number - { + protected generateMaxPmcArmorDurability(itemMaxDurability: number): number { const lowestMaxPercent = this.botConfig.durability.pmc.armor.lowestMaxPercent; const highestMaxPercent = this.botConfig.durability.pmc.armor.highestMaxPercent; const multiplier = this.randomUtil.getInt(lowestMaxPercent, highestMaxPercent); @@ -153,28 +133,23 @@ export class DurabilityLimitsHelper return itemMaxDurability * (multiplier / 100); } - protected getLowestMaxWeaponFromConfig(botRole?: string): number - { - if (this.botConfig.durability[botRole!]) - { + protected getLowestMaxWeaponFromConfig(botRole?: string): number { + if (this.botConfig.durability[botRole!]) { return this.botConfig.durability[botRole!].weapon.lowestMax; } return this.botConfig.durability.default.weapon.lowestMax; } - protected getHighestMaxWeaponDurabilityFromConfig(botRole?: string): number - { - if (this.botConfig.durability[botRole!]) - { + protected getHighestMaxWeaponDurabilityFromConfig(botRole?: string): number { + if (this.botConfig.durability[botRole!]) { return this.botConfig.durability[botRole!].weapon.highestMax; } return this.botConfig.durability.default.weapon.highestMax; } - protected generateWeaponDurability(botRole: string | undefined, maxDurability: number): number - { + protected generateWeaponDurability(botRole: string | undefined, maxDurability: number): number { const minDelta = this.getMinWeaponDeltaFromConfig(botRole); const maxDelta = this.getMaxWeaponDeltaFromConfig(botRole); const delta = this.randomUtil.getInt(minDelta, maxDelta); @@ -187,8 +162,7 @@ export class DurabilityLimitsHelper return result >= durabilityValueMinLimit ? result : durabilityValueMinLimit; } - protected generateArmorDurability(botRole: string | undefined, maxDurability: number): number - { + protected generateArmorDurability(botRole: string | undefined, maxDurability: number): number { const minDelta = this.getMinArmorDeltaFromConfig(botRole); const maxDelta = this.getMaxArmorDeltaFromConfig(botRole); const delta = this.randomUtil.getInt(minDelta, maxDelta); @@ -201,60 +175,48 @@ export class DurabilityLimitsHelper return result >= durabilityValueMinLimit ? result : durabilityValueMinLimit; } - protected getMinWeaponDeltaFromConfig(botRole?: string): number - { - if (this.botConfig.durability[botRole!]) - { + protected getMinWeaponDeltaFromConfig(botRole?: string): number { + if (this.botConfig.durability[botRole!]) { return this.botConfig.durability[botRole!].weapon.minDelta; } return this.botConfig.durability.default.weapon.minDelta; } - protected getMaxWeaponDeltaFromConfig(botRole?: string): number - { - if (this.botConfig.durability[botRole!]) - { + protected getMaxWeaponDeltaFromConfig(botRole?: string): number { + if (this.botConfig.durability[botRole!]) { return this.botConfig.durability[botRole!].weapon.maxDelta; } return this.botConfig.durability.default.weapon.maxDelta; } - protected getMinArmorDeltaFromConfig(botRole?: string): number - { - if (this.botConfig.durability[botRole!]) - { + protected getMinArmorDeltaFromConfig(botRole?: string): number { + if (this.botConfig.durability[botRole!]) { return this.botConfig.durability[botRole!].armor.minDelta; } return this.botConfig.durability.default.armor.minDelta; } - protected getMaxArmorDeltaFromConfig(botRole?: string): number - { - if (this.botConfig.durability[botRole!]) - { + protected getMaxArmorDeltaFromConfig(botRole?: string): number { + if (this.botConfig.durability[botRole!]) { return this.botConfig.durability[botRole!].armor.maxDelta; } return this.botConfig.durability.default.armor.maxDelta; } - protected getMinArmorLimitPercentFromConfig(botRole?: string): number - { - if (this.botConfig.durability[botRole!]) - { + protected getMinArmorLimitPercentFromConfig(botRole?: string): number { + if (this.botConfig.durability[botRole!]) { return this.botConfig.durability[botRole!].armor.minLimitPercent; } return this.botConfig.durability.default.armor.minLimitPercent; } - protected getMinWeaponLimitPercentFromConfig(botRole?: string): number - { - if (this.botConfig.durability[botRole!]) - { + protected getMinWeaponLimitPercentFromConfig(botRole?: string): number { + if (this.botConfig.durability[botRole!]) { return this.botConfig.durability[botRole!].weapon.minLimitPercent; } diff --git a/project/src/helpers/GameEventHelper.ts b/project/src/helpers/GameEventHelper.ts index 330a299e..bd8fe5fb 100644 --- a/project/src/helpers/GameEventHelper.ts +++ b/project/src/helpers/GameEventHelper.ts @@ -1,19 +1,17 @@ -import { inject, injectable } from "tsyringe"; import { ConfigTypes } from "@spt/models/enums/ConfigTypes"; import { ISeasonalEventConfig } from "@spt/models/spt/config/ISeasonalEventConfig"; import { ConfigServer } from "@spt/servers/ConfigServer"; import { DatabaseServer } from "@spt/servers/DatabaseServer"; +import { inject, injectable } from "tsyringe"; @injectable() -export class GameEventHelper -{ +export class GameEventHelper { protected seasonalEventConfig: ISeasonalEventConfig; constructor( @inject("DatabaseServer") protected databaseServer: DatabaseServer, @inject("ConfigServer") protected configServer: ConfigServer, - ) - { + ) { this.seasonalEventConfig = this.configServer.getConfig(ConfigTypes.SEASONAL_EVENT); } } diff --git a/project/src/helpers/HandbookHelper.ts b/project/src/helpers/HandbookHelper.ts index f9b64550..05dc6900 100644 --- a/project/src/helpers/HandbookHelper.ts +++ b/project/src/helpers/HandbookHelper.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { Category } from "@spt/models/eft/common/tables/IHandbookBase"; import { Item } from "@spt/models/eft/common/tables/IItem"; import { ConfigTypes } from "@spt/models/enums/ConfigTypes"; @@ -7,34 +6,30 @@ import { IItemConfig } from "@spt/models/spt/config/IItemConfig"; import { ConfigServer } from "@spt/servers/ConfigServer"; import { DatabaseService } from "@spt/services/DatabaseService"; import { ICloner } from "@spt/utils/cloners/ICloner"; +import { inject, injectable } from "tsyringe"; -class LookupItem -{ +class LookupItem { readonly byId: Map; readonly byParent: Map; - constructor() - { + constructor() { this.byId = new Map(); this.byParent = new Map(); } } -export class LookupCollection -{ +export class LookupCollection { readonly items: LookupItem; readonly categories: LookupItem; - constructor() - { + constructor() { this.items = new LookupItem(); this.categories = new LookupItem(); } } @injectable() -export class HandbookHelper -{ +export class HandbookHelper { protected itemConfig: IItemConfig; protected lookupCacheGenerated = false; protected handbookPriceCache = new LookupCollection(); @@ -43,53 +38,43 @@ export class HandbookHelper @inject("DatabaseService") protected databaseService: DatabaseService, @inject("ConfigServer") protected configServer: ConfigServer, @inject("PrimaryCloner") protected cloner: ICloner, - ) - { + ) { this.itemConfig = this.configServer.getConfig(ConfigTypes.ITEM); } /** * Create an in-memory cache of all items with associated handbook price in handbookPriceCache class */ - public hydrateLookup(): void - { + public hydrateLookup(): void { const handbook = this.databaseService.getHandbook(); // Add handbook overrides found in items.json config into db - for (const itemTpl in this.itemConfig.handbookPriceOverride) - { + for (const itemTpl in this.itemConfig.handbookPriceOverride) { let itemToUpdate = handbook.Items.find((item) => item.Id === itemTpl); - if (!itemToUpdate) - { + if (!itemToUpdate) { handbook.Items.push({ Id: itemTpl, ParentId: this.databaseService.getItems()[itemTpl]._parent, Price: this.itemConfig.handbookPriceOverride[itemTpl], }); - itemToUpdate = handbook - .Items.find((item) => item.Id === itemTpl); + itemToUpdate = handbook.Items.find((item) => item.Id === itemTpl); } itemToUpdate.Price = this.itemConfig.handbookPriceOverride[itemTpl]; } const handbookDbClone = this.cloner.clone(handbook); - for (const handbookItem of handbookDbClone.Items) - { + for (const handbookItem of handbookDbClone.Items) { this.handbookPriceCache.items.byId.set(handbookItem.Id, handbookItem.Price); - if (!this.handbookPriceCache.items.byParent.has(handbookItem.ParentId)) - { + if (!this.handbookPriceCache.items.byParent.has(handbookItem.ParentId)) { this.handbookPriceCache.items.byParent.set(handbookItem.ParentId, []); } this.handbookPriceCache.items.byParent.get(handbookItem.ParentId).push(handbookItem.Id); } - for (const handbookCategory of handbookDbClone.Categories) - { + for (const handbookCategory of handbookDbClone.Categories) { this.handbookPriceCache.categories.byId.set(handbookCategory.Id, handbookCategory.ParentId || undefined); - if (handbookCategory.ParentId) - { - if (!this.handbookPriceCache.categories.byParent.has(handbookCategory.ParentId)) - { + if (handbookCategory.ParentId) { + if (!this.handbookPriceCache.categories.byParent.has(handbookCategory.ParentId)) { this.handbookPriceCache.categories.byParent.set(handbookCategory.ParentId, []); } this.handbookPriceCache.categories.byParent.get(handbookCategory.ParentId).push(handbookCategory.Id); @@ -103,22 +88,18 @@ export class HandbookHelper * @param tpl Item tpl to look up price for * @returns price in roubles */ - public getTemplatePrice(tpl: string): number - { - if (!this.lookupCacheGenerated) - { + public getTemplatePrice(tpl: string): number { + if (!this.lookupCacheGenerated) { this.hydrateLookup(); this.lookupCacheGenerated = true; } - if (this.handbookPriceCache.items.byId.has(tpl)) - { + if (this.handbookPriceCache.items.byId.has(tpl)) { return this.handbookPriceCache.items.byId.get(tpl); } const handbookItem = this.databaseService.getHandbook().Items.find((item) => item.Id === tpl); - if (!handbookItem) - { + if (!handbookItem) { const newValue = 0; this.handbookPriceCache.items.byId.set(tpl, newValue); @@ -129,11 +110,9 @@ export class HandbookHelper return handbookItem.Price; } - public getTemplatePriceForItems(items: Item[]): number - { + public getTemplatePriceForItems(items: Item[]): number { let total = 0; - for (const item of items) - { + for (const item of items) { total += this.getTemplatePrice(item._tpl); } @@ -145,8 +124,7 @@ export class HandbookHelper * @param parentId * @returns string array */ - public templatesWithParent(parentId: string): string[] - { + public templatesWithParent(parentId: string): string[] { return this.handbookPriceCache.items.byParent.get(parentId) ?? []; } @@ -155,8 +133,7 @@ export class HandbookHelper * @param category * @returns true if exists in cache */ - public isCategory(category: string): boolean - { + public isCategory(category: string): boolean { return this.handbookPriceCache.categories.byId.has(category); } @@ -165,8 +142,7 @@ export class HandbookHelper * @param categoryParent * @returns string array */ - public childrenCategories(categoryParent: string): string[] - { + public childrenCategories(categoryParent: string): string[] { return this.handbookPriceCache.categories.byParent.get(categoryParent) ?? []; } @@ -176,10 +152,8 @@ export class HandbookHelper * @param currencyTypeFrom What current currency is * @returns Count in roubles */ - public inRUB(nonRoubleCurrencyCount: number, currencyTypeFrom: string): number - { - if (currencyTypeFrom === Money.ROUBLES) - { + public inRUB(nonRoubleCurrencyCount: number, currencyTypeFrom: string): number { + if (currencyTypeFrom === Money.ROUBLES) { return nonRoubleCurrencyCount; } @@ -192,10 +166,8 @@ export class HandbookHelper * @param currencyTypeTo Currency to convert roubles into * @returns currency count in desired type */ - public fromRUB(roubleCurrencyCount: number, currencyTypeTo: string): number - { - if (currencyTypeTo === Money.ROUBLES) - { + public fromRUB(roubleCurrencyCount: number, currencyTypeTo: string): number { + if (currencyTypeTo === Money.ROUBLES) { return roubleCurrencyCount; } @@ -204,8 +176,7 @@ export class HandbookHelper return price ? Math.max(1, Math.round(roubleCurrencyCount / price)) : 0; } - public getCategoryById(handbookId: string): Category - { + public getCategoryById(handbookId: string): Category { return this.databaseService.getHandbook().Categories.find((category) => category.Id === handbookId); } } diff --git a/project/src/helpers/HealthHelper.ts b/project/src/helpers/HealthHelper.ts index 6858271d..1a16dd48 100644 --- a/project/src/helpers/HealthHelper.ts +++ b/project/src/helpers/HealthHelper.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { IPmcData } from "@spt/models/eft/common/IPmcData"; import { BodyPartsHealth, Health } from "@spt/models/eft/common/tables/IBotBase"; import { ISyncHealthRequestData } from "@spt/models/eft/health/ISyncHealthRequestData"; @@ -8,12 +7,12 @@ import { IHealthConfig } from "@spt/models/spt/config/IHealthConfig"; import { ILogger } from "@spt/models/spt/utils/ILogger"; import { ConfigServer } from "@spt/servers/ConfigServer"; import { SaveServer } from "@spt/servers/SaveServer"; -import { ICloner } from "@spt/utils/cloners/ICloner"; import { TimeUtil } from "@spt/utils/TimeUtil"; +import { ICloner } from "@spt/utils/cloners/ICloner"; +import { inject, injectable } from "tsyringe"; @injectable() -export class HealthHelper -{ +export class HealthHelper { protected healthConfig: IHealthConfig; constructor( @@ -22,8 +21,7 @@ export class HealthHelper @inject("SaveServer") protected saveServer: SaveServer, @inject("ConfigServer") protected configServer: ConfigServer, @inject("PrimaryCloner") protected cloner: ICloner, - ) - { + ) { this.healthConfig = this.configServer.getConfig(ConfigTypes.HEALTH); } @@ -32,12 +30,10 @@ export class HealthHelper * @param sessionID Session Id * @returns updated profile */ - public resetVitality(sessionID: string): ISptProfile - { + public resetVitality(sessionID: string): ISptProfile { const profile = this.saveServer.getProfile(sessionID); - if (!profile.vitality) - { + if (!profile.vitality) { // Occurs on newly created profiles profile.vitality = { health: undefined!, effects: undefined! }; } @@ -81,35 +77,30 @@ export class HealthHelper postRaidHealth: Health, sessionID: string, isDead: boolean, - ): void - { + ): void { const fullProfile = this.saveServer.getProfile(sessionID); this.storeHydrationEnergyTempInProfile( fullProfile, postRaidHealth.Hydration.Current, postRaidHealth.Energy.Current, - postRaidHealth.Temperature.Current); + postRaidHealth.Temperature.Current, + ); // Store limb effects from post-raid in profile - for (const bodyPart in postRaidHealth.BodyParts) - { + for (const bodyPart in postRaidHealth.BodyParts) { // Effects - if (postRaidHealth.BodyParts[bodyPart].Effects) - { + if (postRaidHealth.BodyParts[bodyPart].Effects) { fullProfile.vitality.effects[bodyPart] = postRaidHealth.BodyParts[bodyPart].Effects; } // Limb hp - if (!isDead) - { + if (!isDead) { // Player alive, not is limb alive fullProfile.vitality.health[bodyPart] = postRaidHealth.BodyParts[bodyPart].Health.Current; - } - else - { - fullProfile.vitality.health[bodyPart] - = pmcData.Health.BodyParts[bodyPart].Health.Maximum * this.healthConfig.healthMultipliers.death; + } else { + fullProfile.vitality.health[bodyPart] = + pmcData.Health.BodyParts[bodyPart].Health.Maximum * this.healthConfig.healthMultipliers.death; } } @@ -129,8 +120,8 @@ export class HealthHelper fullProfile: ISptProfile, hydration: number, energy: number, - temprature: number): void - { + temprature: number, + ): void { fullProfile.vitality.health.Hydration = hydration; fullProfile.vitality.health.Energy = energy; fullProfile.vitality.health.Temperature = temprature; @@ -141,30 +132,22 @@ export class HealthHelper * @param postRaidBodyParts Post-raid body part data * @param profileData Player profile on server */ - protected transferPostRaidLimbEffectsToProfile( - postRaidBodyParts: BodyPartsHealth, - profileData: IPmcData, - ): void - { + protected transferPostRaidLimbEffectsToProfile(postRaidBodyParts: BodyPartsHealth, profileData: IPmcData): void { // Iterate over each body part - for (const bodyPartId in postRaidBodyParts) - { + for (const bodyPartId in postRaidBodyParts) { // Get effects on body part from profile const bodyPartEffects = postRaidBodyParts[bodyPartId].Effects; - for (const effect in bodyPartEffects) - { + for (const effect in bodyPartEffects) { const effectDetails = bodyPartEffects[effect]; // Null guard - if (!profileData.Health.BodyParts[bodyPartId].Effects) - { + if (!profileData.Health.BodyParts[bodyPartId].Effects) { profileData.Health.BodyParts[bodyPartId].Effects = {}; } // Already exists on server profile, skip const profileBodyPartEffects = profileData.Health.BodyParts[bodyPartId].Effects; - if (profileBodyPartEffects[effect]) - { + if (profileBodyPartEffects[effect]) { continue; } @@ -188,42 +171,31 @@ export class HealthHelper sessionID: string, addEffects = true, deleteExistingEffects = true, - ): void - { + ): void { const postRaidBodyParts = request.Health; // post raid health settings const fullProfile = this.saveServer.getProfile(sessionID); const profileEffects = fullProfile.vitality.effects; - this.storeHydrationEnergyTempInProfile( - fullProfile, - request.Hydration!, - request.Energy!, - request.Temperature!); + this.storeHydrationEnergyTempInProfile(fullProfile, request.Hydration!, request.Energy!, request.Temperature!); // Process request data into profile - for (const bodyPart in postRaidBodyParts) - { + for (const bodyPart in postRaidBodyParts) { // Transfer effects from request to profile - if (postRaidBodyParts[bodyPart].Effects) - { + if (postRaidBodyParts[bodyPart].Effects) { profileEffects[bodyPart] = postRaidBodyParts[bodyPart].Effects; } - if (request.IsAlive) - { + if (request.IsAlive) { // Player alive, not is limb alive fullProfile.vitality.health[bodyPart] = postRaidBodyParts[bodyPart].Current; - } - else - { - fullProfile.vitality.health[bodyPart] - = pmcData.Health.BodyParts[bodyPart].Health.Maximum * this.healthConfig.healthMultipliers.death; + } else { + fullProfile.vitality.health[bodyPart] = + pmcData.Health.BodyParts[bodyPart].Health.Maximum * this.healthConfig.healthMultipliers.death; } } // Add effects to body parts if enabled - if (addEffects) - { + if (addEffects) { this.saveEffects( pmcData, sessionID, @@ -246,43 +218,34 @@ export class HealthHelper * @param pmcData Profile to update * @param sessionId Session id */ - protected saveHealth(pmcData: IPmcData, sessionID: string): void - { - if (!this.healthConfig.save.health) - { + protected saveHealth(pmcData: IPmcData, sessionID: string): void { + if (!this.healthConfig.save.health) { return; } const profileHealth = this.saveServer.getProfile(sessionID).vitality.health; - for (const healthModifier in profileHealth) - { + for (const healthModifier in profileHealth) { let target = profileHealth[healthModifier]; - if (["Hydration", "Energy", "Temperature"].includes(healthModifier)) - { + if (["Hydration", "Energy", "Temperature"].includes(healthModifier)) { // Set resources - if (target > pmcData.Health[healthModifier].Maximum) - { + if (target > pmcData.Health[healthModifier].Maximum) { target = pmcData.Health[healthModifier].Maximum; } pmcData.Health[healthModifier].Current = Math.round(target); - } - else - { + } else { // Over max, limit - if (target > pmcData.Health.BodyParts[healthModifier].Health.Maximum) - { + if (target > pmcData.Health.BodyParts[healthModifier].Health.Maximum) { target = pmcData.Health.BodyParts[healthModifier].Health.Maximum; } // Part was zeroed out in raid - if (target === 0) - { + if (target === 0) { // Blacked body part target = Math.round( - pmcData.Health.BodyParts[healthModifier].Health.Maximum - * this.healthConfig.healthMultipliers.blacked, + pmcData.Health.BodyParts[healthModifier].Health.Maximum * + this.healthConfig.healthMultipliers.blacked, ); } @@ -305,25 +268,19 @@ export class HealthHelper sessionId: string, bodyPartsWithEffects: Effects, deleteExistingEffects = true, - ): void - { - if (!this.healthConfig.save.effects) - { + ): void { + if (!this.healthConfig.save.effects) { return; } - for (const bodyPart in bodyPartsWithEffects) - { + for (const bodyPart in bodyPartsWithEffects) { // clear effects from profile bodyPart - if (deleteExistingEffects) - { + if (deleteExistingEffects) { delete pmcData.Health.BodyParts[bodyPart].Effects; } - for (const effectType in bodyPartsWithEffects[bodyPart]) - { - if (typeof effectType !== "string") - { + for (const effectType in bodyPartsWithEffects[bodyPart]) { + if (typeof effectType !== "string") { this.logger.warning(`Effect ${effectType} on body part ${bodyPart} not a string, report this`); } @@ -332,20 +289,16 @@ export class HealthHelper // ? nodeEffects[bodyPart][effectValue] // : effectValue; let time = bodyPartsWithEffects[bodyPart][effectType]; - if (time) - { + if (time) { // Sometimes the value can be Infinity instead of -1, blame HealthListener.cs in modules - if (time === "Infinity") - { + if (time === "Infinity") { this.logger.warning( `Effect ${effectType} found with value of Infinity, changed to -1, this is an issue with HealthListener.cs`, ); time = -1; } this.addEffect(pmcData, bodyPart, effectType, time); - } - else - { + } else { this.addEffect(pmcData, bodyPart, effectType); } } @@ -359,29 +312,23 @@ export class HealthHelper * @param effectType Effect to add to body part * @param duration How long the effect has left in seconds (-1 by default, no duration). */ - protected addEffect(pmcData: IPmcData, effectBodyPart: string, effectType: string, duration = -1): void - { + protected addEffect(pmcData: IPmcData, effectBodyPart: string, effectType: string, duration = -1): void { const profileBodyPart = pmcData.Health.BodyParts[effectBodyPart]; - if (!profileBodyPart.Effects) - { + if (!profileBodyPart.Effects) { profileBodyPart.Effects = {}; } profileBodyPart.Effects[effectType] = { Time: duration }; // Delete empty property to prevent client bugs - if (this.isEmpty(profileBodyPart.Effects)) - { + if (this.isEmpty(profileBodyPart.Effects)) { delete profileBodyPart.Effects; } } - protected isEmpty(map: Record): boolean - { - for (const key in map) - { - if (key in map) - { + protected isEmpty(map: Record): boolean { + for (const key in map) { + if (key in map) { return false; } } diff --git a/project/src/helpers/HideoutHelper.ts b/project/src/helpers/HideoutHelper.ts index fb8e544f..4312fe27 100644 --- a/project/src/helpers/HideoutHelper.ts +++ b/project/src/helpers/HideoutHelper.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { InventoryHelper } from "@spt/helpers/InventoryHelper"; import { ItemHelper } from "@spt/helpers/ItemHelper"; import { ProfileHelper } from "@spt/helpers/ProfileHelper"; @@ -24,14 +23,14 @@ import { ConfigServer } from "@spt/servers/ConfigServer"; import { DatabaseService } from "@spt/services/DatabaseService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { PlayerService } from "@spt/services/PlayerService"; -import { ICloner } from "@spt/utils/cloners/ICloner"; import { HashUtil } from "@spt/utils/HashUtil"; import { HttpResponseUtil } from "@spt/utils/HttpResponseUtil"; import { TimeUtil } from "@spt/utils/TimeUtil"; +import { ICloner } from "@spt/utils/cloners/ICloner"; +import { inject, injectable } from "tsyringe"; @injectable() -export class HideoutHelper -{ +export class HideoutHelper { public static bitcoinFarm = "5d5c205bd582a50d042a3c0e"; public static bitcoinProductionId = "5d5c205bd582a50d042a3c0e"; public static waterCollector = "5d5589c1f934db045e6c5492"; @@ -53,8 +52,7 @@ export class HideoutHelper @inject("ItemHelper") protected itemHelper: ItemHelper, @inject("ConfigServer") protected configServer: ConfigServer, @inject("PrimaryCloner") protected cloner: ICloner, - ) - { + ) { this.hideoutConfig = this.configServer.getConfig(ConfigTypes.HIDEOUT); } @@ -69,12 +67,11 @@ export class HideoutHelper pmcData: IPmcData, body: IHideoutSingleProductionStartRequestData | IHideoutContinuousProductionStartRequestData, sessionID: string, - ): IItemEventRouterResponse - { - const recipe = this.databaseService.getHideout().production - .find((production) => production._id === body.recipeId); - if (!recipe) - { + ): IItemEventRouterResponse { + const recipe = this.databaseService + .getHideout() + .production.find((production) => production._id === body.recipeId); + if (!recipe) { this.logger.error(this.localisationService.getText("hideout-missing_recipe_in_db", body.recipeId)); return this.httpResponse.appendErrorToOutput(this.eventOutputHolder.getOutput(sessionID)); @@ -83,8 +80,7 @@ export class HideoutHelper // @Important: Here we need to be very exact: // - normal recipe: Production time value is stored in attribute "productionType" with small "p" // - scav case recipe: Production time value is stored in attribute "ProductionType" with capital "P" - if (!pmcData.Hideout.Production) - { + if (!pmcData.Hideout.Production) { pmcData.Hideout.Production = {}; } @@ -98,12 +94,10 @@ export class HideoutHelper // Store the tools used for this production, so we can return them later const bodyAsSingle = body as IHideoutSingleProductionStartRequestData; - if (bodyAsSingle && bodyAsSingle.tools?.length > 0) - { + if (bodyAsSingle && bodyAsSingle.tools?.length > 0) { production.sptRequiredTools = []; - for (const tool of bodyAsSingle.tools) - { + for (const tool of bodyAsSingle.tools) { const toolItem = this.cloner.clone(pmcData.Inventory.items.find((x) => x._id === tool.id)); // Make sure we only return as many as we took @@ -126,8 +120,7 @@ export class HideoutHelper * This convenience function initializes new Production Object * with all the constants. */ - public initProduction(recipeId: string, productionTime: number, needFuelForAllProductionTime: boolean): Production - { + public initProduction(recipeId: string, productionTime: number, needFuelForAllProductionTime: boolean): Production { return { Progress: 0, inProgress: true, @@ -148,8 +141,7 @@ export class HideoutHelper * @param productive * @returns */ - public isProductionType(productive: Productive): productive is Production - { + public isProductionType(productive: Productive): productive is Production { return (productive as Production).Progress !== undefined || (productive as Production).RecipeId !== undefined; } @@ -158,18 +150,19 @@ export class HideoutHelper * @param pmcData Profile to add bonus to * @param bonus Bonus to add to profile */ - public applyPlayerUpgradesBonuses(pmcData: IPmcData, bonus: StageBonus): void - { + public applyPlayerUpgradesBonuses(pmcData: IPmcData, bonus: StageBonus): void { // Handle additional changes some bonuses need before being added - switch (bonus.type) - { - case BonusType.STASH_SIZE: - { + switch (bonus.type) { + case BonusType.STASH_SIZE: { // Find stash item and adjust tpl to new tpl from bonus const stashItem = pmcData.Inventory.items.find((x) => x._id === pmcData.Inventory.stash); - if (!stashItem) - { - this.logger.warning(this.localisationService.getText("hideout-unable_to_apply_stashsize_bonus_no_stash_found", pmcData.Inventory.stash)); + if (!stashItem) { + this.logger.warning( + this.localisationService.getText( + "hideout-unable_to_apply_stashsize_bonus_no_stash_found", + pmcData.Inventory.stash, + ), + ); } stashItem._tpl = bonus.templateId; @@ -198,8 +191,7 @@ export class HideoutHelper * Process a players hideout, update areas that use resources + increment production timers * @param sessionID Session id */ - public updatePlayerHideout(sessionID: string): void - { + public updatePlayerHideout(sessionID: string): void { const pmcData = this.profileHelper.getPmcProfile(sessionID); const hideoutProperties = this.getHideoutProperties(pmcData); @@ -214,11 +206,10 @@ export class HideoutHelper * @returns Properties */ protected getHideoutProperties(pmcData: IPmcData): { - btcFarmCGs: number - isGeneratorOn: boolean - waterCollectorHasFilter: boolean - } - { + btcFarmCGs: number; + isGeneratorOn: boolean; + waterCollectorHasFilter: boolean; + } { const bitcoinFarm = pmcData.Hideout.Areas.find((area) => area.type === HideoutAreas.BITCOIN_FARM); const bitcoinCount = bitcoinFarm?.slots.filter((slot) => slot.item).length ?? 0; // Get slots with an item property @@ -233,11 +224,9 @@ export class HideoutHelper return hideoutProperties; } - protected doesWaterCollectorHaveFilter(waterCollector: HideoutArea): boolean - { + protected doesWaterCollectorHaveFilter(waterCollector: HideoutArea): boolean { // Can put filters in from L3 - if (waterCollector.level === 3) - { + if (waterCollector.level === 3) { // Has filter in at least one slot return waterCollector.slots.some((slot) => slot.item); } @@ -253,51 +242,45 @@ export class HideoutHelper */ protected updateProductionTimers( pmcData: IPmcData, - hideoutProperties: { btcFarmCGs: number, isGeneratorOn: boolean, waterCollectorHasFilter: boolean }, - ): void - { + hideoutProperties: { btcFarmCGs: number; isGeneratorOn: boolean; waterCollectorHasFilter: boolean }, + ): void { const recipes = this.databaseService.getHideout().production; // Check each production - for (const prodId in pmcData.Hideout.Production) - { + for (const prodId in pmcData.Hideout.Production) { const craft = pmcData.Hideout.Production[prodId]; - if (!craft) - { + if (!craft) { // Craft value is undefined, get rid of it (could be from cancelling craft that needs cleaning up) delete pmcData.Hideout.Production[prodId]; continue; } - if (craft.Progress === undefined) - { - this.logger.warning(this.localisationService.getText("hideout-craft_has_undefined_progress_value_defaulting", prodId)); + if (craft.Progress === undefined) { + this.logger.warning( + this.localisationService.getText("hideout-craft_has_undefined_progress_value_defaulting", prodId), + ); craft.Progress = 0; } // Craft complete, skip processing (Don't skip continious crafts like bitcoin farm) - if (craft.Progress >= craft.ProductionTime && prodId !== HideoutHelper.bitcoinFarm) - { + if (craft.Progress >= craft.ProductionTime && prodId !== HideoutHelper.bitcoinFarm) { continue; } - if (craft.sptIsScavCase) - { + if (craft.sptIsScavCase) { this.updateScavCaseProductionTimer(pmcData, prodId); continue; } - if (prodId === HideoutHelper.waterCollector) - { + if (prodId === HideoutHelper.waterCollector) { this.updateWaterCollectorProductionTimer(pmcData, prodId, hideoutProperties); continue; } - if (prodId === HideoutHelper.bitcoinFarm) - { + if (prodId === HideoutHelper.bitcoinFarm) { pmcData.Hideout.Production[prodId] = this.updateBitcoinFarm( pmcData, hideoutProperties.btcFarmCGs, @@ -308,8 +291,7 @@ export class HideoutHelper // Other recipes not covered by above const recipe = recipes.find((r) => r._id === prodId); - if (!recipe) - { + if (!recipe) { this.logger.error(this.localisationService.getText("hideout-missing_recipe_for_area", prodId)); continue; @@ -328,12 +310,10 @@ export class HideoutHelper protected updateWaterCollectorProductionTimer( pmcData: IPmcData, productionId: string, - hideoutProperties: { btcFarmCGs?: number, isGeneratorOn: boolean, waterCollectorHasFilter: boolean }, - ): void - { + hideoutProperties: { btcFarmCGs?: number; isGeneratorOn: boolean; waterCollectorHasFilter: boolean }, + ): void { const timeElapsed = this.getTimeElapsedSinceLastServerTick(pmcData, hideoutProperties.isGeneratorOn); - if (hideoutProperties.waterCollectorHasFilter) - { + if (hideoutProperties.waterCollectorHasFilter) { pmcData.Hideout.Production[productionId].Progress += timeElapsed; } } @@ -349,12 +329,10 @@ export class HideoutHelper pmcData: IPmcData, prodId: string, recipe: IHideoutProduction, - hideoutProperties: { btcFarmCGs?: number, isGeneratorOn: boolean, waterCollectorHasFilter?: boolean }, - ): void - { + hideoutProperties: { btcFarmCGs?: number; isGeneratorOn: boolean; waterCollectorHasFilter?: boolean }, + ): void { // Production is complete, no need to do any calculations - if (this.doesProgressMatchProductionTime(pmcData, prodId)) - { + if (this.doesProgressMatchProductionTime(pmcData, prodId)) { return; } @@ -363,12 +341,11 @@ export class HideoutHelper // Increment progress by time passed const production = pmcData.Hideout.Production[prodId]; - production.Progress - += production.needFuelForAllProductionTime && !hideoutProperties.isGeneratorOn ? 0 : timeElapsed; // Some items NEED power to craft (e.g. DSP) + production.Progress += + production.needFuelForAllProductionTime && !hideoutProperties.isGeneratorOn ? 0 : timeElapsed; // Some items NEED power to craft (e.g. DSP) // Limit progress to total production time if progress is over (dont run for continious crafts)) - if (!recipe.continuous) - { + if (!recipe.continuous) { // If progress is larger than prod time, return ProductionTime, hard cap the vaue production.Progress = Math.min(production.Progress, production.ProductionTime); } @@ -381,8 +358,7 @@ export class HideoutHelper * @param recipe Recipe being crafted * @returns progress matches productionTime from recipe */ - protected doesProgressMatchProductionTime(pmcData: IPmcData, prodId: string): boolean - { + protected doesProgressMatchProductionTime(pmcData: IPmcData, prodId: string): boolean { return pmcData.Hideout.Production[prodId].Progress === pmcData.Hideout.Production[prodId].ProductionTime; } @@ -391,12 +367,11 @@ export class HideoutHelper * @param pmcData Profile to update * @param productionId Id of scav case production to update */ - protected updateScavCaseProductionTimer(pmcData: IPmcData, productionId: string): void - { - const timeElapsed - = this.timeUtil.getTimestamp() - - pmcData.Hideout.Production[productionId].StartTimestamp - - pmcData.Hideout.Production[productionId].Progress; + protected updateScavCaseProductionTimer(pmcData: IPmcData, productionId: string): void { + const timeElapsed = + this.timeUtil.getTimestamp() - + pmcData.Hideout.Production[productionId].StartTimestamp - + pmcData.Hideout.Production[productionId].Progress; pmcData.Hideout.Production[productionId].Progress += timeElapsed; } @@ -409,16 +384,12 @@ export class HideoutHelper protected updateAreasWithResources( sessionID: string, pmcData: IPmcData, - hideoutProperties: { btcFarmCGs: number, isGeneratorOn: boolean, waterCollectorHasFilter: boolean }, - ): void - { - for (const area of pmcData.Hideout.Areas) - { - switch (area.type) - { + hideoutProperties: { btcFarmCGs: number; isGeneratorOn: boolean; waterCollectorHasFilter: boolean }, + ): void { + for (const area of pmcData.Hideout.Areas) { + switch (area.type) { case HideoutAreas.GENERATOR: - if (hideoutProperties.isGeneratorOn) - { + if (hideoutProperties.isGeneratorOn) { this.updateFuel(area, pmcData, hideoutProperties.isGeneratorOn); } break; @@ -427,8 +398,7 @@ export class HideoutHelper break; case HideoutAreas.AIR_FILTERING: - if (hideoutProperties.isGeneratorOn) - { + if (hideoutProperties.isGeneratorOn) { this.updateAirFilters(area, pmcData, hideoutProperties.isGeneratorOn); } break; @@ -442,19 +412,18 @@ export class HideoutHelper * @param pmcData Player profile * @param isGeneratorOn Is the generator turned on since last update */ - protected updateFuel(generatorArea: HideoutArea, pmcData: IPmcData, isGeneratorOn: boolean): void - { + protected updateFuel(generatorArea: HideoutArea, pmcData: IPmcData, isGeneratorOn: boolean): void { // 1 resource last 14 min 27 sec, 1/14.45/60 = 0.00115 // 10-10-2021 From wiki, 1 resource last 12 minutes 38 seconds, 1/12.63333/60 = 0.00131 - let fuelUsedSinceLastTick - = this.databaseService.getHideout().settings.generatorFuelFlowRate - * this.getTimeElapsedSinceLastServerTick(pmcData, isGeneratorOn); + let fuelUsedSinceLastTick = + this.databaseService.getHideout().settings.generatorFuelFlowRate * + this.getTimeElapsedSinceLastServerTick(pmcData, isGeneratorOn); const profileFuelConsumptionBonus = pmcData.Bonuses.find((bonus) => bonus.type === BonusType.FUEL_CONSUMPTION); // 0 to 1 - const fuelConsumptionBonusMultipler - = (profileFuelConsumptionBonus ? Math.abs(profileFuelConsumptionBonus.value) : 0) / 100; + const fuelConsumptionBonusMultipler = + (profileFuelConsumptionBonus ? Math.abs(profileFuelConsumptionBonus.value) : 0) / 100; // 0 to 1 const hideoutManagementConsumptionBonusMultipler = this.getHideoutManagementConsumptionBonus(pmcData); @@ -464,38 +433,31 @@ export class HideoutHelper let hasFuelRemaining = false; let pointsConsumed = 0; - for (let i = 0; i < generatorArea.slots.length; i++) - { + for (let i = 0; i < generatorArea.slots.length; i++) { const generatorSlot = generatorArea.slots[i]; - if (!generatorSlot?.item) - { + if (!generatorSlot?.item) { // No item in slot, skip continue; } const fuelItemInSlot = generatorSlot?.item[0]; - if (!fuelItemInSlot) - { + if (!fuelItemInSlot) { // No item in slot, skip continue; } let fuelRemaining = fuelItemInSlot.upd?.Resource?.Value; - if (fuelRemaining === 0) - { + if (fuelRemaining === 0) { // No fuel left, skip continue; } // Undefined fuel, fresh fuel item and needs its max fuel amount looked up - if (!fuelRemaining) - { + if (!fuelRemaining) { const fuelItemTemplate = this.itemHelper.getItem(fuelItemInSlot._tpl)[1]; pointsConsumed = fuelUsedSinceLastTick; fuelRemaining = fuelItemTemplate._props.MaxResource - fuelUsedSinceLastTick; - } - else - { + } else { // Fuel exists already, deduct fuel from item remaining value pointsConsumed = (fuelItemInSlot.upd.Resource.UnitsConsumed || 0) + fuelUsedSinceLastTick; fuelRemaining -= fuelUsedSinceLastTick; @@ -506,15 +468,13 @@ export class HideoutHelper pointsConsumed = Math.round(pointsConsumed * 10000) / 10000; // Fuel consumed / 10 is over 1, add hideout management skill point - if (pmcData && Math.floor(pointsConsumed / 10) >= 1) - { + if (pmcData && Math.floor(pointsConsumed / 10) >= 1) { this.profileHelper.addSkillPointsToPlayer(pmcData, SkillTypes.HIDEOUT_MANAGEMENT, 1); pointsConsumed -= 10; } const isFuelItemFoundInRaid = fuelItemInSlot.upd?.SpawnedInSession ?? false; - if (fuelRemaining > 0) - { + if (fuelRemaining > 0) { // Deducted all used fuel from this container, clean up and exit loop fuelItemInSlot.upd = this.getAreaUpdObject(1, fuelRemaining, pointsConsumed, isFuelItemFoundInRaid); @@ -535,8 +495,7 @@ export class HideoutHelper } // Out of fuel, flag generator as offline - if (!hasFuelRemaining) - { + if (!hasFuelRemaining) { generatorArea.active = false; } } @@ -545,24 +504,20 @@ export class HideoutHelper sessionId: string, pmcData: IPmcData, area: HideoutArea, - hideoutProperties: { btcFarmCGs: number, isGeneratorOn: boolean, waterCollectorHasFilter: boolean }, - ): void - { + hideoutProperties: { btcFarmCGs: number; isGeneratorOn: boolean; waterCollectorHasFilter: boolean }, + ): void { // Skip water collector when not level 3 (cant collect until 3) - if (area.level !== 3) - { + if (area.level !== 3) { return; } - if (!hideoutProperties.waterCollectorHasFilter) - { + if (!hideoutProperties.waterCollectorHasFilter) { return; } // Canister with purified water craft exists const purifiedWaterCraft = pmcData.Hideout.Production[HideoutHelper.waterCollector]; - if (purifiedWaterCraft && this.isProduction(purifiedWaterCraft)) - { + if (purifiedWaterCraft && this.isProduction(purifiedWaterCraft)) { // Update craft time to account for increases in players craft time skill purifiedWaterCraft.ProductionTime = this.getAdjustedCraftTimeWithSkills( pmcData, @@ -571,9 +526,7 @@ export class HideoutHelper ); this.updateWaterFilters(area, purifiedWaterCraft, hideoutProperties.isGeneratorOn, pmcData); - } - else - { + } else { // continuousProductionStart() // seem to not trigger consistently const recipe: IHideoutSingleProductionStartRequestData = { @@ -599,14 +552,11 @@ export class HideoutHelper pmcData: IPmcData, recipeId: string, applyHideoutManagementBonus = false, - ): number - { + ): number { const globalSkillsDb = this.databaseService.getGlobals().config.SkillsSettings; - const recipe = this.databaseService.getHideout().production - .find((production) => production._id === recipeId); - if (!recipe) - { + const recipe = this.databaseService.getHideout().production.find((production) => production._id === recipeId); + if (!recipe) { this.logger.error(this.localisationService.getText("hideout-missing_recipe_in_db", recipeId)); return undefined; @@ -615,8 +565,7 @@ export class HideoutHelper let timeReductionSeconds = 0; // Bitcoin farm is excluded from crafting skill cooldown reduction - if (recipeId !== HideoutHelper.bitcoinFarm) - { + if (recipeId !== HideoutHelper.bitcoinFarm) { // Seconds to deduct from crafts total time timeReductionSeconds += this.getSkillProductionTimeReduction( pmcData, @@ -627,8 +576,7 @@ export class HideoutHelper } // Some crafts take into account hideout management, e.g. fuel, water/air filters - if (applyHideoutManagementBonus) - { + if (applyHideoutManagementBonus) { timeReductionSeconds += this.getSkillProductionTimeReduction( pmcData, recipe.productionTime, @@ -638,14 +586,12 @@ export class HideoutHelper } let modifiedProductionTime = recipe.productionTime - timeReductionSeconds; - if (modifiedProductionTime > 0 && this.profileHelper.isDeveloperAccount(pmcData._id)) - { + if (modifiedProductionTime > 0 && this.profileHelper.isDeveloperAccount(pmcData._id)) { modifiedProductionTime = 40; } // Sanity check, don't let anything craft in less than 5 seconds - if (modifiedProductionTime < 5) - { + if (modifiedProductionTime < 5) { modifiedProductionTime = 5; } @@ -664,8 +610,7 @@ export class HideoutHelper production: Production, isGeneratorOn: boolean, pmcData: IPmcData, - ): void - { + ): void { let filterDrainRate = this.getWaterFilterDrainRate(pmcData); const productionTime = this.getTotalProductionTimeSeconds(HideoutHelper.waterCollector); const secondsSinceServerTick = this.getTimeElapsedSinceLastServerTick(pmcData, isGeneratorOn); @@ -679,14 +624,11 @@ export class HideoutHelper // Production hasn't completed let pointsConsumed = 0; - if (production.Progress < productionTime) - { + if (production.Progress < productionTime) { // Check all slots that take water filters until we find one with filter in it - for (let i = 0; i < waterFilterArea.slots.length; i++) - { + for (let i = 0; i < waterFilterArea.slots.length; i++) { // No water filter, skip - if (!waterFilterArea.slots[i].item) - { + if (!waterFilterArea.slots[i].item) { continue; } @@ -696,14 +638,11 @@ export class HideoutHelper let resourceValue = waterFilterItemInSlot.upd?.Resource ? waterFilterItemInSlot.upd.Resource.Value : undefined; - if (!resourceValue) - { + if (!resourceValue) { // Missing, is new filter, add default and subtract usage resourceValue = 100 - filterDrainRate; pointsConsumed = filterDrainRate; - } - else - { + } else { pointsConsumed = (waterFilterItemInSlot.upd.Resource.UnitsConsumed || 0) + filterDrainRate; resourceValue -= filterDrainRate; } @@ -713,15 +652,13 @@ export class HideoutHelper pointsConsumed = Math.round(pointsConsumed * 1000) / 1000; // Check units consumed for possible increment of hideout mgmt skill point - if (pmcData && Math.floor(pointsConsumed / 10) >= 1) - { + if (pmcData && Math.floor(pointsConsumed / 10) >= 1) { this.profileHelper.addSkillPointsToPlayer(pmcData, SkillTypes.HIDEOUT_MANAGEMENT, 1); pointsConsumed -= 10; } // Filter has some fuel left in it after our adjustment - if (resourceValue > 0) - { + if (resourceValue > 0) { const isWaterFilterFoundInRaid = waterFilterItemInSlot.upd.SpawnedInSession ?? false; // Set filters consumed amount @@ -758,10 +695,9 @@ export class HideoutHelper totalProductionTime: number, productionProgress: number, baseFilterDrainRate: number, - ): number - { - const drainTimeSeconds - = secondsSinceServerTick > totalProductionTime + ): number { + const drainTimeSeconds = + secondsSinceServerTick > totalProductionTime ? totalProductionTime - productionProgress // More time passed than prod time, get total minus the current progress : secondsSinceServerTick; @@ -774,8 +710,7 @@ export class HideoutHelper * @param pmcData Player profile * @returns Drain rate */ - protected getWaterFilterDrainRate(pmcData: IPmcData): number - { + protected getWaterFilterDrainRate(pmcData: IPmcData): number { const globalSkillsDb = this.databaseService.getGlobals().config.SkillsSettings; // 100 resources last 8 hrs 20 min, 100/8.33/60/60 = 0.00333 @@ -793,8 +728,8 @@ export class HideoutHelper ); // Never let bonus become 0 - const reductionBonus - = hideoutManagementConsumptionBonus + craftSkillTimeReductionMultipler === 0 + const reductionBonus = + hideoutManagementConsumptionBonus + craftSkillTimeReductionMultipler === 0 ? 1 : 1 - (hideoutManagementConsumptionBonus + craftSkillTimeReductionMultipler); @@ -806,8 +741,7 @@ export class HideoutHelper * @param prodId Id, e.g. Water collector id * @returns seconds to produce item */ - protected getTotalProductionTimeSeconds(prodId: string): number - { + protected getTotalProductionTimeSeconds(prodId: string): number { return this.databaseService.getHideout().production.find((prod) => prod._id === prodId)?.productionTime ?? 0; } @@ -823,8 +757,7 @@ export class HideoutHelper resourceValue: number, resourceUnitsConsumed: number, isFoundInRaid: boolean, - ): Upd - { + ): Upd { return { StackObjectsCount: stackCount, Resource: { Value: resourceValue, UnitsConsumed: resourceUnitsConsumed }, @@ -832,36 +765,30 @@ export class HideoutHelper }; } - protected updateAirFilters(airFilterArea: HideoutArea, pmcData: IPmcData, isGeneratorOn: boolean): void - { + protected updateAirFilters(airFilterArea: HideoutArea, pmcData: IPmcData, isGeneratorOn: boolean): void { // 300 resources last 20 hrs, 300/20/60/60 = 0.00416 /* 10-10-2021 from WIKI (https://escapefromtarkov.fandom.com/wiki/FP-100_filter_absorber) Lasts for 17 hours 38 minutes and 49 seconds (23 hours 31 minutes and 45 seconds with elite hideout management skill), 300/17.64694/60/60 = 0.004722 */ - let filterDrainRate - = this.databaseService.getHideout().settings.airFilterUnitFlowRate - * this.getTimeElapsedSinceLastServerTick(pmcData, isGeneratorOn); + let filterDrainRate = + this.databaseService.getHideout().settings.airFilterUnitFlowRate * + this.getTimeElapsedSinceLastServerTick(pmcData, isGeneratorOn); // Hideout management resource consumption bonus: const hideoutManagementConsumptionBonus = 1.0 - this.getHideoutManagementConsumptionBonus(pmcData); filterDrainRate *= hideoutManagementConsumptionBonus; let pointsConsumed = 0; - for (let i = 0; i < airFilterArea.slots.length; i++) - { - if (airFilterArea.slots[i].item) - { + for (let i = 0; i < airFilterArea.slots.length; i++) { + if (airFilterArea.slots[i].item) { let resourceValue = airFilterArea.slots[i].item[0].upd?.Resource ? airFilterArea.slots[i].item[0].upd.Resource.Value : undefined; - if (!resourceValue) - { + if (!resourceValue) { resourceValue = 300 - filterDrainRate; pointsConsumed = filterDrainRate; - } - else - { + } else { pointsConsumed = (airFilterArea.slots[i].item[0].upd.Resource.UnitsConsumed || 0) + filterDrainRate; resourceValue -= filterDrainRate; } @@ -869,14 +796,12 @@ export class HideoutHelper pointsConsumed = Math.round(pointsConsumed * 10000) / 10000; // check unit consumed for increment skill point - if (pmcData && Math.floor(pointsConsumed / 10) >= 1) - { + if (pmcData && Math.floor(pointsConsumed / 10) >= 1) { this.profileHelper.addSkillPointsToPlayer(pmcData, SkillTypes.HIDEOUT_MANAGEMENT, 1); pointsConsumed -= 10; } - if (resourceValue > 0) - { + if (resourceValue > 0) { airFilterArea.slots[i].item[0].upd = { StackObjectsCount: 1, Resource: { Value: resourceValue, UnitsConsumed: pointsConsumed }, @@ -892,24 +817,22 @@ export class HideoutHelper } } - protected updateBitcoinFarm(pmcData: IPmcData, btcFarmCGs: number, isGeneratorOn: boolean): Production | undefined - { + protected updateBitcoinFarm(pmcData: IPmcData, btcFarmCGs: number, isGeneratorOn: boolean): Production | undefined { const btcProd = pmcData.Hideout.Production[HideoutHelper.bitcoinFarm]; - const bitcoinProdData = this.databaseService.getHideout().production - .find((production) => production._id === HideoutHelper.bitcoinProductionId); + const bitcoinProdData = this.databaseService + .getHideout() + .production.find((production) => production._id === HideoutHelper.bitcoinProductionId); const coinSlotCount = this.getBTCSlots(pmcData); // Full on bitcoins, halt progress - if (this.isProduction(btcProd) && btcProd.Products.length >= coinSlotCount) - { + if (this.isProduction(btcProd) && btcProd.Products.length >= coinSlotCount) { // Set progress to 0 btcProd.Progress = 0; return btcProd; } - if (this.isProduction(btcProd)) - { + if (this.isProduction(btcProd)) { // The wiki has a wrong formula! // Do not change unless you validate it with the Client code files! // This formula was found on the client files: @@ -945,24 +868,20 @@ export class HideoutHelper } */ // BSG finally fixed their settings, they now get loaded from the settings and used in the client - const adjustedCraftTime - = (this.profileHelper.isDeveloperAccount(pmcData.sessionId) ? 40 : bitcoinProdData.productionTime) - / (1 + (btcFarmCGs - 1) * this.databaseService.getHideout().settings.gpuBoostRate); + const adjustedCraftTime = + (this.profileHelper.isDeveloperAccount(pmcData.sessionId) ? 40 : bitcoinProdData.productionTime) / + (1 + (btcFarmCGs - 1) * this.databaseService.getHideout().settings.gpuBoostRate); // The progress should be adjusted based on the GPU boost rate, but the target is still the base productionTime const timeMultiplier = bitcoinProdData.productionTime / adjustedCraftTime; const timeElapsedSeconds = this.getTimeElapsedSinceLastServerTick(pmcData, isGeneratorOn); btcProd.Progress += Math.floor(timeElapsedSeconds * timeMultiplier); - while (btcProd.Progress >= bitcoinProdData.productionTime) - { - if (btcProd.Products.length < coinSlotCount) - { + while (btcProd.Progress >= bitcoinProdData.productionTime) { + if (btcProd.Products.length < coinSlotCount) { // Has space to add a coin to production this.addBtcToProduction(btcProd, bitcoinProdData.productionTime); - } - else - { + } else { // Filled up bitcoin storage btcProd.Progress = 0; } @@ -981,8 +900,7 @@ export class HideoutHelper * @param btcProd Bitcoin production object * @param coinCraftTimeSeconds Time to craft a bitcoin */ - protected addBtcToProduction(btcProd: Production, coinCraftTimeSeconds: number): void - { + protected addBtcToProduction(btcProd: Production, coinCraftTimeSeconds: number): void { btcProd.Products.push({ _id: this.hashUtil.generate(), _tpl: ItemTpl.BARTER_PHYSICAL_BITCOIN, @@ -1004,23 +922,19 @@ export class HideoutHelper pmcData: IPmcData, isGeneratorOn: boolean, recipe?: IHideoutProduction, - ): number - { + ): number { // Reduce time elapsed (and progress) when generator is off let timeElapsed = this.timeUtil.getTimestamp() - pmcData.Hideout.sptUpdateLastRunTimestamp; - if (recipe) - { + if (recipe) { const hideoutArea = this.databaseService.getHideout().areas.find((area) => area.type === recipe.areaType); - if (!hideoutArea.needsFuel) - { + if (!hideoutArea.needsFuel) { // e.g. Lavatory works at 100% when power is on / off return timeElapsed; } } - if (!isGeneratorOn) - { + if (!isGeneratorOn) { timeElapsed *= this.databaseService.getHideout().settings.generatorSpeedWithoutFuel; } @@ -1032,10 +946,10 @@ export class HideoutHelper * @param pmcData Profile to look up * @returns Coin slot count */ - protected getBTCSlots(pmcData: IPmcData): number - { - const bitcoinProductions = this.databaseService.getHideout().production - .find((production) => production._id === HideoutHelper.bitcoinFarm); + protected getBTCSlots(pmcData: IPmcData): number { + const bitcoinProductions = this.databaseService + .getHideout() + .production.find((production) => production._id === HideoutHelper.bitcoinFarm); const productionSlots = bitcoinProductions?.productionLimitCount || 3; // Default to 3 if none found const hasManagementSkillSlots = this.profileHelper.hasEliteSkillLevel(SkillTypes.HIDEOUT_MANAGEMENT, pmcData); const managementSlotsCount = this.getEliteSkillAdditionalBitcoinSlotCount() || 2; @@ -1046,8 +960,7 @@ export class HideoutHelper /** * Get a count of how many additional bitcoins player hideout can hold with elite skill */ - protected getEliteSkillAdditionalBitcoinSlotCount(): number - { + protected getEliteSkillAdditionalBitcoinSlotCount(): number { return this.databaseService.getGlobals().config.SkillsSettings.HideoutManagement.EliteSlots.BitcoinFarm .Container; } @@ -1058,11 +971,9 @@ export class HideoutHelper * @param pmcData Profile to get hideout consumption level level from * @returns consumption bonus */ - protected getHideoutManagementConsumptionBonus(pmcData: IPmcData): number - { + protected getHideoutManagementConsumptionBonus(pmcData: IPmcData): number { const hideoutManagementSkill = this.profileHelper.getSkillFromProfile(pmcData, SkillTypes.HIDEOUT_MANAGEMENT); - if (!hideoutManagementSkill || hideoutManagementSkill.Progress === 0) - { + if (!hideoutManagementSkill || hideoutManagementSkill.Progress === 0) { return 0; } @@ -1073,10 +984,10 @@ export class HideoutHelper roundedLevel = roundedLevel === 51 ? roundedLevel - 1 : roundedLevel; return ( - (roundedLevel - * this.databaseService.getGlobals().config.SkillsSettings.HideoutManagement - .ConsumptionReductionPerLevel) - / 100 + (roundedLevel * + this.databaseService.getGlobals().config.SkillsSettings.HideoutManagement + .ConsumptionReductionPerLevel) / + 100 ); } @@ -1087,11 +998,9 @@ export class HideoutHelper * @param valuePerLevel Value from globals.config.SkillsSettings - `PerLevel` * @returns Multipler from 0 to 1 */ - protected getSkillBonusMultipliedBySkillLevel(pmcData: IPmcData, skill: SkillTypes, valuePerLevel: number): number - { + protected getSkillBonusMultipliedBySkillLevel(pmcData: IPmcData, skill: SkillTypes, valuePerLevel: number): number { const profileSkill = this.profileHelper.getSkillFromProfile(pmcData, skill); - if (!profileSkill || profileSkill.Progress === 0) - { + if (!profileSkill || profileSkill.Progress === 0) { return 0; } @@ -1116,15 +1025,13 @@ export class HideoutHelper productionTime: number, skill: SkillTypes, amountPerLevel: number, - ): number - { + ): number { const skillTimeReductionMultipler = this.getSkillBonusMultipliedBySkillLevel(pmcData, skill, amountPerLevel); return productionTime * skillTimeReductionMultipler; } - public isProduction(productive: Productive): productive is Production - { + public isProduction(productive: Productive): productive is Production { return (productive as Production).Progress !== undefined || (productive as Production).RecipeId !== undefined; } @@ -1141,12 +1048,10 @@ export class HideoutHelper request: IHideoutTakeProductionRequestData, sessionId: string, output: IItemEventRouterResponse, - ): void - { + ): void { // Get how many coins were crafted and ready to pick up const craftedCoinCount = pmcData.Hideout.Production[HideoutHelper.bitcoinFarm]?.Products?.length ?? 0; - if (!craftedCoinCount) - { + if (!craftedCoinCount) { const errorMsg = this.localisationService.getText("hideout-no_bitcoins_to_collect"); this.logger.error(errorMsg); @@ -1156,8 +1061,7 @@ export class HideoutHelper } const itemsToAdd: Item[][] = []; - for (let index = 0; index < craftedCoinCount; index++) - { + for (let index = 0; index < craftedCoinCount; index++) { itemsToAdd.push([ { _id: this.hashUtil.generate(), @@ -1177,15 +1081,13 @@ export class HideoutHelper // Add FiR coins to player inventory this.inventoryHelper.addItemsToStash(sessionId, addItemsRequest, pmcData, output); - if (output.warnings.length > 0) - { + if (output.warnings.length > 0) { return; } // Is at max capacity + we collected all coins - reset production start time const coinSlotCount = this.getBTCSlots(pmcData); - if (pmcData.Hideout.Production[HideoutHelper.bitcoinFarm].Products.length >= coinSlotCount) - { + if (pmcData.Hideout.Production[HideoutHelper.bitcoinFarm].Products.length >= coinSlotCount) { // Set start to now pmcData.Hideout.Production[HideoutHelper.bitcoinFarm].StartTimestamp = this.timeUtil.getTimestamp(); } @@ -1199,21 +1101,18 @@ export class HideoutHelper * Upgrade hideout wall from starting level to interactable level if necessary stations have been upgraded * @param pmcProfile Profile to upgrade wall in */ - public unlockHideoutWallInProfile(pmcProfile: IPmcData): void - { + public unlockHideoutWallInProfile(pmcProfile: IPmcData): void { const waterCollector = pmcProfile.Hideout.Areas.find((x) => x.type === HideoutAreas.WATER_COLLECTOR); const medStation = pmcProfile.Hideout.Areas.find((x) => x.type === HideoutAreas.MEDSTATION); const wall = pmcProfile.Hideout.Areas.find((x) => x.type === HideoutAreas.EMERGENCY_WALL); // No collector or med station, skip - if (!(waterCollector && medStation)) - { + if (!(waterCollector && medStation)) { return; } // If medstation > level 1 AND water collector > level 1 AND wall is level 0 - if (waterCollector?.level >= 1 && medStation?.level >= 1 && wall?.level <= 0) - { + if (waterCollector?.level >= 1 && medStation?.level >= 1 && wall?.level <= 0) { wall.level = 3; } } @@ -1223,8 +1122,7 @@ export class HideoutHelper * @param improvement hideout improvement object * @returns true if complete */ - protected hideoutImprovementIsComplete(improvement: IHideoutImprovement): boolean - { + protected hideoutImprovementIsComplete(improvement: IHideoutImprovement): boolean { return improvement?.completed ? true : false; } @@ -1232,16 +1130,13 @@ export class HideoutHelper * Iterate over hideout improvements not completed and check if they need to be adjusted * @param pmcProfile Profile to adjust */ - public setHideoutImprovementsToCompleted(pmcProfile: IPmcData): void - { - for (const improvementId in pmcProfile.Hideout.Improvement) - { + public setHideoutImprovementsToCompleted(pmcProfile: IPmcData): void { + for (const improvementId in pmcProfile.Hideout.Improvement) { const improvementDetails = pmcProfile.Hideout.Improvement[improvementId]; if ( - improvementDetails.completed === false - && improvementDetails.improveCompleteTimestamp < this.timeUtil.getTimestamp() - ) - { + improvementDetails.completed === false && + improvementDetails.improveCompleteTimestamp < this.timeUtil.getTimestamp() + ) { improvementDetails.completed = true; } } @@ -1251,13 +1146,13 @@ export class HideoutHelper * Add/remove bonus combat skill based on number of dogtags in place of fame hideout area * @param pmcData Player profile */ - public applyPlaceOfFameDogtagBonus(pmcData: IPmcData): void - { + public applyPlaceOfFameDogtagBonus(pmcData: IPmcData): void { const fameAreaProfile = pmcData.Hideout.Areas.find((area) => area.type === HideoutAreas.PLACE_OF_FAME); // Get hideout area 16 bonus array - const fameAreaDb = this.databaseService.getHideout().areas - .find((area) => area.type === HideoutAreas.PLACE_OF_FAME); + const fameAreaDb = this.databaseService + .getHideout() + .areas.find((area) => area.type === HideoutAreas.PLACE_OF_FAME); // Get SkillGroupLevelingBoost object const combatBoostBonusDb = fameAreaDb.stages[fameAreaProfile.level].bonuses.find( @@ -1273,8 +1168,8 @@ export class HideoutHelper // Calculate bonus percent (apply hideoutManagement bonus) const hideoutManagementSkill = this.profileHelper.getSkillFromProfile(pmcData, SkillTypes.HIDEOUT_MANAGEMENT); const hideoutManagementSkillBonusPercent = 1 + hideoutManagementSkill.Progress / 10000; // 5100 becomes 0.51, add 1 to it, 1.51 - const bonus - = this.getDogtagCombatSkillBonusPercent(pmcData, activeDogtags) * hideoutManagementSkillBonusPercent; + const bonus = + this.getDogtagCombatSkillBonusPercent(pmcData, activeDogtags) * hideoutManagementSkillBonusPercent; // Update bonus value to above calcualted value combatBonusProfile.value = Number.parseFloat(bonus.toFixed(2)); @@ -1287,20 +1182,16 @@ export class HideoutHelper * @param activeDogtags Active dogtags in place of fame dogtag slots * @returns combat bonus */ - protected getDogtagCombatSkillBonusPercent(pmcData: IPmcData, activeDogtags: Item[]): number - { + protected getDogtagCombatSkillBonusPercent(pmcData: IPmcData, activeDogtags: Item[]): number { // Not own dogtag // Side = opposite of player let result = 0; - for (const dogtag of activeDogtags) - { - if (!dogtag.upd.Dogtag) - { + for (const dogtag of activeDogtags) { + if (!dogtag.upd.Dogtag) { continue; } - if (Number.parseInt(dogtag.upd.Dogtag?.AccountId) === pmcData.aid) - { + if (Number.parseInt(dogtag.upd.Dogtag?.AccountId) === pmcData.aid) { continue; } diff --git a/project/src/helpers/HttpServerHelper.ts b/project/src/helpers/HttpServerHelper.ts index 880c5348..587b73f7 100644 --- a/project/src/helpers/HttpServerHelper.ts +++ b/project/src/helpers/HttpServerHelper.ts @@ -1,11 +1,10 @@ -import { inject, injectable } from "tsyringe"; import { ConfigTypes } from "@spt/models/enums/ConfigTypes"; import { IHttpConfig } from "@spt/models/spt/config/IHttpConfig"; import { ConfigServer } from "@spt/servers/ConfigServer"; +import { inject, injectable } from "tsyringe"; @injectable() -export class HttpServerHelper -{ +export class HttpServerHelper { protected httpConfig: IHttpConfig; protected mime = { @@ -20,13 +19,11 @@ export class HttpServerHelper txt: "text/plain", }; - constructor(@inject("ConfigServer") protected configServer: ConfigServer) - { + constructor(@inject("ConfigServer") protected configServer: ConfigServer) { this.httpConfig = this.configServer.getConfig(ConfigTypes.HTTP); } - public getMimeText(key: string): string - { + public getMimeText(key: string): string { return this.mime[key]; } @@ -34,8 +31,7 @@ export class HttpServerHelper * Combine ip and port into address * @returns url */ - public buildUrl(): string - { + public buildUrl(): string { return `${this.httpConfig.backendIp}:${this.httpConfig.backendPort}`; } @@ -43,19 +39,16 @@ export class HttpServerHelper * Prepend http to the url:port * @returns URI */ - public getBackendUrl(): string - { + public getBackendUrl(): string { return `http://${this.buildUrl()}`; } /** Get websocket url + port */ - public getWebsocketUrl(): string - { + public getWebsocketUrl(): string { return `ws://${this.buildUrl()}`; } - public sendTextJson(resp: any, output: any): void - { + public sendTextJson(resp: any, output: any): void { resp.writeHead(200, "OK", { "Content-Type": this.mime.json }); resp.end(output); } diff --git a/project/src/helpers/InRaidHelper.ts b/project/src/helpers/InRaidHelper.ts index d807b532..e1b9f70c 100644 --- a/project/src/helpers/InRaidHelper.ts +++ b/project/src/helpers/InRaidHelper.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { InventoryHelper } from "@spt/helpers/InventoryHelper"; import { IPmcData } from "@spt/models/eft/common/IPmcData"; import { Item } from "@spt/models/eft/common/tables/IItem"; @@ -7,10 +6,10 @@ import { ILostOnDeathConfig } from "@spt/models/spt/config/ILostOnDeathConfig"; import { ILogger } from "@spt/models/spt/utils/ILogger"; import { ConfigServer } from "@spt/servers/ConfigServer"; import { ICloner } from "@spt/utils/cloners/ICloner"; +import { inject, injectable } from "tsyringe"; @injectable() -export class InRaidHelper -{ +export class InRaidHelper { protected lostOnDeathConfig: ILostOnDeathConfig; constructor( @@ -18,8 +17,7 @@ export class InRaidHelper @inject("InventoryHelper") protected inventoryHelper: InventoryHelper, @inject("ConfigServer") protected configServer: ConfigServer, @inject("PrimaryCloner") protected cloner: ICloner, - ) - { + ) { this.lostOnDeathConfig = this.configServer.getConfig(ConfigTypes.LOST_ON_DEATH); } @@ -28,10 +26,8 @@ export class InRaidHelper * Reset the skill points earned in a raid to 0, ready for next raid * @param profile Profile to update */ - protected resetSkillPointsEarnedDuringRaid(profile: IPmcData): void - { - for (const skill of profile.Skills.Common) - { + protected resetSkillPointsEarnedDuringRaid(profile: IPmcData): void { + for (const skill of profile.Skills.Common) { skill.PointsEarnedDuringSession = 0.0; } } @@ -45,8 +41,7 @@ export class InRaidHelper * @param serverProfile Profile to update * @param postRaidProfile Profile returned by client after a raid */ - public setInventory(sessionID: string, serverProfile: IPmcData, postRaidProfile: IPmcData): void - { + public setInventory(sessionID: string, serverProfile: IPmcData, postRaidProfile: IPmcData): void { // Store insurance (as removeItem() removes insurance also) const insured = this.cloner.clone(serverProfile.InsuredItems); @@ -67,12 +62,10 @@ export class InRaidHelper * @param pmcData Player profile * @param sessionId Session id */ - public deleteInventory(pmcData: IPmcData, sessionId: string): void - { + public deleteInventory(pmcData: IPmcData, sessionId: string): void { // Get inventory item ids to remove from players profile const itemIdsToDeleteFromProfile = this.getInventoryItemsLostOnDeath(pmcData).map((item) => item._id); - for (const itemIdToDelete of itemIdsToDeleteFromProfile) - { + for (const itemIdToDelete of itemIdsToDeleteFromProfile) { // Items inside containers are handled as part of function this.inventoryHelper.removeItem(pmcData, itemIdToDelete, sessionId); } @@ -86,29 +79,24 @@ export class InRaidHelper * @param pmcProfile Profile to get items from * @returns Array of items lost on death */ - protected getInventoryItemsLostOnDeath(pmcProfile: IPmcData): Item[] - { + protected getInventoryItemsLostOnDeath(pmcProfile: IPmcData): Item[] { const inventoryItems = pmcProfile.Inventory.items ?? []; const equipmentRootId = pmcProfile?.Inventory?.equipment; const questRaidItemContainerId = pmcProfile?.Inventory?.questRaidItems; - return inventoryItems.filter((item) => - { + return inventoryItems.filter((item) => { // Keep items flagged as kept after death - if (this.isItemKeptAfterDeath(pmcProfile, item)) - { + if (this.isItemKeptAfterDeath(pmcProfile, item)) { return false; } // Remove normal items or quest raid items - if (item.parentId === equipmentRootId || item.parentId === questRaidItemContainerId) - { + if (item.parentId === equipmentRootId || item.parentId === questRaidItemContainerId) { return true; } // Pocket items are lost on death - if (item.slotId.startsWith("pocket")) - { + if (item.slotId.startsWith("pocket")) { return true; } @@ -122,24 +110,20 @@ export class InRaidHelper * @itemToCheck Item to check should be kept * @returns true if item is kept after death */ - protected isItemKeptAfterDeath(pmcData: IPmcData, itemToCheck: Item): boolean - { + protected isItemKeptAfterDeath(pmcData: IPmcData, itemToCheck: Item): boolean { // Use pocket slotId's otherwise it deletes the root pocket item. const pocketSlots = ["pocket1", "pocket2", "pocket3", "pocket4"]; // Base inventory items are always kept - if (!itemToCheck.parentId) - { + if (!itemToCheck.parentId) { return true; } // Is item equipped on player - if (itemToCheck.parentId === pmcData.Inventory.equipment) - { + if (itemToCheck.parentId === pmcData.Inventory.equipment) { // Check slot id against config, true = delete, false = keep, undefined = delete const discard: boolean = this.lostOnDeathConfig.equipment[itemToCheck.slotId]; - if (typeof discard === "boolean" && discard === true) - { + if (typeof discard === "boolean" && discard === true) { // Lost on death return false; } @@ -148,20 +132,17 @@ export class InRaidHelper } // Should we keep items in pockets on death - if (!this.lostOnDeathConfig.equipment.PocketItems && pocketSlots.includes(itemToCheck.slotId)) - { + if (!this.lostOnDeathConfig.equipment.PocketItems && pocketSlots.includes(itemToCheck.slotId)) { return true; } // Is quest item + quest item not lost on death - if (itemToCheck.parentId === pmcData.Inventory.questRaidItems && !this.lostOnDeathConfig.questItems) - { + if (itemToCheck.parentId === pmcData.Inventory.questRaidItems && !this.lostOnDeathConfig.questItems) { return true; } // special slots are always kept after death - if (itemToCheck.slotId?.includes("SpecialSlot") && this.lostOnDeathConfig.specialSlotItems) - { + if (itemToCheck.slotId?.includes("SpecialSlot") && this.lostOnDeathConfig.specialSlotItems) { return true; } diff --git a/project/src/helpers/InventoryHelper.ts b/project/src/helpers/InventoryHelper.ts index 9339e2e8..0de532b4 100644 --- a/project/src/helpers/InventoryHelper.ts +++ b/project/src/helpers/InventoryHelper.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { ContainerHelper } from "@spt/helpers/ContainerHelper"; import { DialogueHelper } from "@spt/helpers/DialogueHelper"; import { ItemHelper } from "@spt/helpers/ItemHelper"; @@ -28,13 +27,13 @@ import { ConfigServer } from "@spt/servers/ConfigServer"; import { DatabaseServer } from "@spt/servers/DatabaseServer"; import { FenceService } from "@spt/services/FenceService"; import { LocalisationService } from "@spt/services/LocalisationService"; -import { ICloner } from "@spt/utils/cloners/ICloner"; import { HashUtil } from "@spt/utils/HashUtil"; import { HttpResponseUtil } from "@spt/utils/HttpResponseUtil"; +import { ICloner } from "@spt/utils/cloners/ICloner"; +import { inject, injectable } from "tsyringe"; @injectable() -export class InventoryHelper -{ +export class InventoryHelper { protected inventoryConfig: IInventoryConfig; constructor( @@ -53,8 +52,7 @@ export class InventoryHelper @inject("LocalisationService") protected localisationService: LocalisationService, @inject("ConfigServer") protected configServer: ConfigServer, @inject("PrimaryCloner") protected cloner: ICloner, - ) - { + ) { this.inventoryConfig = this.configServer.getConfig(ConfigTypes.INVENTORY); } @@ -70,11 +68,9 @@ export class InventoryHelper request: IAddItemsDirectRequest, pmcData: IPmcData, output: IItemEventRouterResponse, - ): void - { + ): void { // Check all items fit into inventory before adding - if (!this.canPlaceItemsInInventory(sessionId, request.itemsWithModsToAdd)) - { + if (!this.canPlaceItemsInInventory(sessionId, request.itemsWithModsToAdd)) { // No space, exit this.httpResponse.appendErrorToOutput( output, @@ -85,8 +81,7 @@ export class InventoryHelper return; } - for (const itemToAdd of request.itemsWithModsToAdd) - { + for (const itemToAdd of request.itemsWithModsToAdd) { const addItemRequest: IAddItemDirectRequest = { itemWithModsToAdd: itemToAdd, foundInRaid: request.foundInRaid, @@ -96,8 +91,7 @@ export class InventoryHelper // Add to player inventory this.addItemToStash(sessionId, addItemRequest, pmcData, output); - if (output.warnings.length > 0) - { + if (output.warnings.length > 0) { return; } } @@ -115,8 +109,7 @@ export class InventoryHelper request: IAddItemDirectRequest, pmcData: IPmcData, output: IItemEventRouterResponse, - ): void - { + ): void { const itemWithModsToAddClone = this.cloner.clone(request.itemWithModsToAdd); // Get stash layouts ready for use @@ -132,8 +125,7 @@ export class InventoryHelper request.useSortingTable, output, ); - if (output.warnings.length > 0) - { + if (output.warnings.length > 0) { // Failed to place, error out return; } @@ -145,18 +137,14 @@ export class InventoryHelper this.removeTraderRagfairRelatedUpdProperties(itemWithModsToAddClone[0].upd); // Run callback - try - { - if (typeof request.callback === "function") - { + try { + if (typeof request.callback === "function") { request.callback(itemWithModsToAddClone[0].upd.StackObjectsCount); } - } - catch (err) - { + } catch (err) { // Callback failed - const message - = typeof err?.message === "string" ? err.message : this.localisationService.getText("http-unknown_error"); + const message = + typeof err?.message === "string" ? err.message : this.localisationService.getText("http-unknown_error"); this.httpResponse.appendErrorToOutput(output, message); @@ -179,19 +167,14 @@ export class InventoryHelper * @param itemWithChildren An item * @param foundInRaid Item was found in raid */ - protected setFindInRaidStatusForItem(itemWithChildren: Item[], foundInRaid: boolean): void - { - for (const item of itemWithChildren) - { + protected setFindInRaidStatusForItem(itemWithChildren: Item[], foundInRaid: boolean): void { + for (const item of itemWithChildren) { // Ensure item has upd object this.itemHelper.addUpdObjectToItem(item); - if (foundInRaid) - { + if (foundInRaid) { item.upd.SpawnedInSession = foundInRaid; - } - else - { + } else { delete item.upd.SpawnedInSession; } } @@ -201,20 +184,16 @@ export class InventoryHelper * Remove properties from a Upd object used by a trader/ragfair that are unnecessary to a player * @param upd Object to update */ - protected removeTraderRagfairRelatedUpdProperties(upd: Upd): void - { - if (upd.UnlimitedCount !== undefined) - { + protected removeTraderRagfairRelatedUpdProperties(upd: Upd): void { + if (upd.UnlimitedCount !== undefined) { delete upd.UnlimitedCount; } - if (upd.BuyRestrictionCurrent !== undefined) - { + if (upd.BuyRestrictionCurrent !== undefined) { delete upd.BuyRestrictionCurrent; } - if (upd.BuyRestrictionMax !== undefined) - { + if (upd.BuyRestrictionMax !== undefined) { delete upd.BuyRestrictionMax; } } @@ -225,15 +204,12 @@ export class InventoryHelper * @param itemsWithChildren array of items with children to try and fit * @returns True all items fit */ - public canPlaceItemsInInventory(sessionId: string, itemsWithChildren: Item[][]): boolean - { + public canPlaceItemsInInventory(sessionId: string, itemsWithChildren: Item[][]): boolean { const pmcData = this.profileHelper.getPmcProfile(sessionId); const stashFS2D = this.cloner.clone(this.getStashSlotMap(pmcData, sessionId)); - for (const itemWithChildren of itemsWithChildren) - { - if (!this.canPlaceItemInContainer(stashFS2D, itemWithChildren)) - { + for (const itemWithChildren of itemsWithChildren) { + if (!this.canPlaceItemInContainer(stashFS2D, itemWithChildren)) { return false; } } @@ -247,12 +223,9 @@ export class InventoryHelper * @param itemsWithChildren items to try and fit into grid * @returns True all fit */ - public canPlaceItemsInContainer(containerFS2D: number[][], itemsWithChildren: Item[][]): boolean - { - for (const itemWithChildren of itemsWithChildren) - { - if (!this.canPlaceItemInContainer(containerFS2D, itemWithChildren)) - { + public canPlaceItemsInContainer(containerFS2D: number[][], itemsWithChildren: Item[][]): boolean { + for (const itemWithChildren of itemsWithChildren) { + if (!this.canPlaceItemInContainer(containerFS2D, itemWithChildren)) { return false; } } @@ -266,18 +239,15 @@ export class InventoryHelper * @param itemWithChildren item to check fits * @returns True it fits */ - public canPlaceItemInContainer(containerFS2D: number[][], itemWithChildren: Item[]): boolean - { + public canPlaceItemInContainer(containerFS2D: number[][], itemWithChildren: Item[]): boolean { // Get x/y size of item const rootItem = itemWithChildren[0]; const itemSize = this.getItemSize(rootItem._tpl, rootItem._id, itemWithChildren); // Look for a place to slot item into const findSlotResult = this.containerHelper.findSlotForItem(containerFS2D, itemSize[0], itemSize[1]); - if (findSlotResult.success) - { - try - { + if (findSlotResult.success) { + try { this.containerHelper.fillContainerMapWithItem( containerFS2D, findSlotResult.x, @@ -286,11 +256,11 @@ export class InventoryHelper itemSize[1], findSlotResult.rotation, ); - } - catch (err) - { + } catch (err) { const errorText = typeof err === "string" ? ` -> ${err}` : err.message; - this.logger.error(this.localisationService.getText("inventory-unable_to_fit_item_into_inventory", errorText)); + this.logger.error( + this.localisationService.getText("inventory-unable_to_fit_item_into_inventory", errorText), + ); return false; } @@ -314,18 +284,15 @@ export class InventoryHelper itemWithChildren: Item[], containerId: string, desiredSlotId = "hideout", - ): void - { + ): void { // Get x/y size of item const rootItemAdded = itemWithChildren[0]; const itemSize = this.getItemSize(rootItemAdded._tpl, rootItemAdded._id, itemWithChildren); // Look for a place to slot item into const findSlotResult = this.containerHelper.findSlotForItem(containerFS2D, itemSize[0], itemSize[1]); - if (findSlotResult.success) - { - try - { + if (findSlotResult.success) { + try { this.containerHelper.fillContainerMapWithItem( containerFS2D, findSlotResult.x, @@ -334,9 +301,7 @@ export class InventoryHelper itemSize[1], findSlotResult.rotation, ); - } - catch (err) - { + } catch (err) { const errorText = typeof err === "string" ? ` -> ${err}` : err.message; this.logger.error(this.localisationService.getText("inventory-fill_container_failed", errorText)); @@ -373,18 +338,15 @@ export class InventoryHelper playerInventory: Inventory, useSortingTable: boolean, output: IItemEventRouterResponse, - ): void - { + ): void { // Get x/y size of item const rootItem = itemWithChildren[0]; const itemSize = this.getItemSize(rootItem._tpl, rootItem._id, itemWithChildren); // Look for a place to slot item into const findSlotResult = this.containerHelper.findSlotForItem(stashFS2D, itemSize[0], itemSize[1]); - if (findSlotResult.success) - { - try - { + if (findSlotResult.success) { + try { this.containerHelper.fillContainerMapWithItem( stashFS2D, findSlotResult.x, @@ -393,9 +355,7 @@ export class InventoryHelper itemSize[1], findSlotResult.rotation, ); - } - catch (err) - { + } catch (err) { handleContainerPlacementError(err, output); return; @@ -415,16 +375,14 @@ export class InventoryHelper } // Space not found in main stash, use sorting table - if (useSortingTable) - { + if (useSortingTable) { const findSortingSlotResult = this.containerHelper.findSlotForItem( sortingTableFS2D, itemSize[0], itemSize[1], ); - try - { + try { this.containerHelper.fillContainerMapWithItem( sortingTableFS2D, findSortingSlotResult.x, @@ -433,9 +391,7 @@ export class InventoryHelper itemSize[1], findSortingSlotResult.rotation, ); - } - catch (err) - { + } catch (err) { handleContainerPlacementError(err, output); return; @@ -449,9 +405,7 @@ export class InventoryHelper r: findSortingSlotResult.rotation ? 1 : 0, rotation: findSortingSlotResult.rotation, }; - } - else - { + } else { this.httpResponse.appendErrorToOutput( output, this.localisationService.getText("inventory-no_stash_space"), @@ -461,15 +415,11 @@ export class InventoryHelper return; } - function handleContainerPlacementError(err: any, output: IItemEventRouterResponse): void - { + function handleContainerPlacementError(err: any, output: IItemEventRouterResponse): void { const errorText = typeof err === "string" ? ` -> ${err}` : err.message; this.logger.error(this.localisationService.getText("inventory-fill_container_failed", errorText)); - this.httpResponse.appendErrorToOutput( - output, - this.localisationService.getText("inventory-no_stash_space"), - ); + this.httpResponse.appendErrorToOutput(output, this.localisationService.getText("inventory-no_stash_space")); } } @@ -482,15 +432,8 @@ export class InventoryHelper * @param sessionID Session id * @param output OPTIONAL - IItemEventRouterResponse */ - public removeItem( - profile: IPmcData, - itemId: string, - sessionID: string, - output?: IItemEventRouterResponse, - ): void - { - if (!itemId) - { + public removeItem(profile: IPmcData, itemId: string, sessionID: string, output?: IItemEventRouterResponse): void { + if (!itemId) { this.logger.warning(this.localisationService.getText("inventory-unable_to_remove_item_no_id_given")); return; @@ -502,32 +445,27 @@ export class InventoryHelper const insuredItems = profile.InsuredItems; // We have output object, inform client of item deletion - if (output) - { + if (output) { output.profileChanges[sessionID].items.del.push({ _id: itemId }); } - for (const childId of itemToRemoveWithChildren) - { + for (const childId of itemToRemoveWithChildren) { // We expect that each inventory item and each insured item has unique "_id", respective "itemId". // Therefore we want to use a NON-Greedy function and escape the iteration as soon as we find requested item. const inventoryIndex = inventoryItems.findIndex((item) => item._id === childId); - if (inventoryIndex !== -1) - { + if (inventoryIndex !== -1) { inventoryItems.splice(inventoryIndex, 1); - } - else - { - this.logger.warning(this.localisationService.getText("inventory-unable_to_remove_item_id_not_found", - { + } else { + this.logger.warning( + this.localisationService.getText("inventory-unable_to_remove_item_id_not_found", { childId: childId, profileId: profile._id, - })); + }), + ); } const insuredIndex = insuredItems.findIndex((item) => item.itemId === childId); - if (insuredIndex !== -1) - { + if (insuredIndex !== -1) { insuredItems.splice(insuredIndex, 1); } } @@ -543,31 +481,28 @@ export class InventoryHelper sessionId: string, removeRequest: IInventoryRemoveRequestData, output?: IItemEventRouterResponse, - ): void - { + ): void { const fullProfile = this.profileHelper.getFullProfile(sessionId); // Iterate over all dialogs and look for mesasage with key from request, that has item (and maybe its children) we want to remove const dialogs = Object.values(fullProfile.dialogues); - for (const dialog of dialogs) - { + for (const dialog of dialogs) { const messageWithReward = dialog.messages.find((message) => message._id === removeRequest.fromOwner.id); - if (messageWithReward) - { + if (messageWithReward) { // Find item + any possible children and remove them from mails items array const itemWithChildern = this.itemHelper.findAndReturnChildrenAsItems( messageWithReward.items.data, removeRequest.item, ); - for (const itemToDelete of itemWithChildern) - { + for (const itemToDelete of itemWithChildern) { // Get index of item to remove from reward array + remove it const indexOfItemToRemove = messageWithReward.items.data.indexOf(itemToDelete); - if (indexOfItemToRemove === -1) - { + if (indexOfItemToRemove === -1) { this.logger.error( - this.localisationService.getText("inventory-unable_to_remove_item_restart_immediately", - { item: removeRequest.item, mailId: removeRequest.fromOwner.id }), + this.localisationService.getText("inventory-unable_to_remove_item_restart_immediately", { + item: removeRequest.item, + mailId: removeRequest.fromOwner.id, + }), ); continue; @@ -598,38 +533,30 @@ export class InventoryHelper countToRemove: number, sessionID: string, output?: IItemEventRouterResponse, - ): IItemEventRouterResponse - { - if (!itemId) - { + ): IItemEventRouterResponse { + if (!itemId) { return output; } // Goal is to keep removing items until we can remove part of an items stack const itemsToReduce = this.itemHelper.findAndReturnChildrenAsItems(pmcData.Inventory.items, itemId); let remainingCount = countToRemove; - for (const itemToReduce of itemsToReduce) - { + for (const itemToReduce of itemsToReduce) { const itemStackSize = this.itemHelper.getItemStackSize(itemToReduce); // Remove whole stack - if (remainingCount >= itemStackSize) - { + if (remainingCount >= itemStackSize) { remainingCount -= itemStackSize; this.removeItem(pmcData, itemToReduce._id, sessionID, output); - } - else - { + } else { itemToReduce.upd.StackObjectsCount -= remainingCount; remainingCount = 0; - if (output) - { + if (output) { output.profileChanges[sessionID].items.change.push(itemToReduce); } } - if (remainingCount === 0) - { + if (remainingCount === 0) { // Desired count of item has been removed / we ran out of items to remove break; } @@ -645,8 +572,7 @@ export class InventoryHelper * @param inventoryItems * @returns [width, height] */ - public getItemSize(itemTpl: string, itemID: string, inventoryItems: Item[]): number[] - { + public getItemSize(itemTpl: string, itemID: string, inventoryItems: Item[]): number[] { // -> Prepares item Width and height returns [sizeX, sizeY] return this.getSizeByInventoryItemHash(itemTpl, itemID, this.getInventoryItemHash(inventoryItems)); } @@ -663,21 +589,18 @@ export class InventoryHelper itemTpl: string, itemID: string, inventoryItemHash: InventoryHelper.InventoryItemHash, - ): number[] - { + ): number[] { const toDo = [itemID]; const result = this.itemHelper.getItem(itemTpl); const tmpItem = result[1]; // Invalid item or no object - if (!(result[0] && result[1])) - { + if (!(result[0] && result[1])) { this.logger.error(this.localisationService.getText("inventory-invalid_item_missing_from_db", itemTpl)); } // Item found but no _props property - if (tmpItem && !tmpItem._props) - { + if (tmpItem && !tmpItem._props) { this.localisationService.getText("inventory-item_missing_props_property", { itemTpl: itemTpl, itemName: tmpItem?._name, @@ -685,8 +608,7 @@ export class InventoryHelper } // No item object or getItem() returned false - if (!(tmpItem && result[0])) - { + if (!(tmpItem && result[0])) { // return default size of 1x1 this.logger.error(this.localisationService.getText("inventory-return_default_size", itemTpl)); @@ -718,23 +640,17 @@ export class InventoryHelper const rootFolded = rootItem.upd?.Foldable && rootItem.upd.Foldable.Folded === true; // The item itself is collapsible - if (foldableWeapon && (foldedSlot === undefined || foldedSlot === "") && rootFolded) - { + if (foldableWeapon && (foldedSlot === undefined || foldedSlot === "") && rootFolded) { outX -= tmpItem._props.SizeReduceRight; } // Calculate size contribution from child items/attachments - if (!skipThisItems.includes(tmpItem._parent)) - { - while (toDo.length > 0) - { - if (toDo[0] in inventoryItemHash.byParentId) - { - for (const item of inventoryItemHash.byParentId[toDo[0]]) - { + if (!skipThisItems.includes(tmpItem._parent)) { + while (toDo.length > 0) { + if (toDo[0] in inventoryItemHash.byParentId) { + for (const item of inventoryItemHash.byParentId[toDo[0]]) { // Filtering child items outside of mod slots, such as those inside containers, without counting their ExtraSize attribute - if (item.slotId.indexOf("mod_") < 0) - { + if (item.slotId.indexOf("mod_") < 0) { continue; } @@ -742,8 +658,7 @@ export class InventoryHelper // If the barrel is folded the space in the barrel is not counted const itemResult = this.itemHelper.getItem(item._tpl); - if (!itemResult[0]) - { + if (!itemResult[0]) { this.logger.error( this.localisationService.getText( "inventory-get_item_size_item_not_found_by_tpl", @@ -756,26 +671,21 @@ export class InventoryHelper const childFoldable = itm._props.Foldable; const childFolded = item.upd?.Foldable && item.upd.Foldable.Folded === true; - if (foldableWeapon && foldedSlot === item.slotId && (rootFolded || childFolded)) - { + if (foldableWeapon && foldedSlot === item.slotId && (rootFolded || childFolded)) { continue; } - if (childFoldable && rootFolded && childFolded) - { + if (childFoldable && rootFolded && childFolded) { continue; } // Calculating child ExtraSize - if (itm._props.ExtraSizeForceAdd === true) - { + if (itm._props.ExtraSizeForceAdd === true) { forcedUp += itm._props.ExtraSizeUp; forcedDown += itm._props.ExtraSizeDown; forcedLeft += itm._props.ExtraSizeLeft; forcedRight += itm._props.ExtraSizeRight; - } - else - { + } else { sizeUp = sizeUp < itm._props.ExtraSizeUp ? itm._props.ExtraSizeUp : sizeUp; sizeDown = sizeDown < itm._props.ExtraSizeDown ? itm._props.ExtraSizeDown : sizeDown; sizeLeft = sizeLeft < itm._props.ExtraSizeLeft ? itm._props.ExtraSizeLeft : sizeLeft; @@ -800,8 +710,7 @@ export class InventoryHelper * @param containerY Vertical size of container * @returns Two-dimensional representation of container */ - protected getBlankContainerMap(containerH: number, containerY: number): number[][] - { + protected getBlankContainerMap(containerH: number, containerY: number): number[][] { return Array(containerY) .fill(0) .map(() => Array(containerH).fill(0)); @@ -814,50 +723,42 @@ export class InventoryHelper * @param containerId Id of the container * @returns Two-dimensional representation of container */ - public getContainerMap(containerH: number, containerV: number, itemList: Item[], containerId: string): number[][] - { + public getContainerMap(containerH: number, containerV: number, itemList: Item[], containerId: string): number[][] { const container2D: number[][] = this.getBlankContainerMap(containerH, containerV); const inventoryItemHash = this.getInventoryItemHash(itemList); const containerItemHash = inventoryItemHash.byParentId[containerId]; - if (!containerItemHash) - { + if (!containerItemHash) { // No items in the container return container2D; } - for (const item of containerItemHash) - { - if (!("location" in item)) - { + for (const item of containerItemHash) { + if (!("location" in item)) { continue; } const tmpSize = this.getSizeByInventoryItemHash(item._tpl, item._id, inventoryItemHash); const iW = tmpSize[0]; // x const iH = tmpSize[1]; // y - const fH - = (item.location as Location).r === 1 - || (item.location as Location).r === "Vertical" - || (item.location as Location).rotation === "Vertical" + const fH = + (item.location as Location).r === 1 || + (item.location as Location).r === "Vertical" || + (item.location as Location).rotation === "Vertical" ? iW : iH; - const fW - = (item.location as Location).r === 1 - || (item.location as Location).r === "Vertical" - || (item.location as Location).rotation === "Vertical" + const fW = + (item.location as Location).r === 1 || + (item.location as Location).r === "Vertical" || + (item.location as Location).rotation === "Vertical" ? iH : iW; const fillTo = (item.location as Location).x + fW; - for (let y = 0; y < fH; y++) - { - try - { + for (let y = 0; y < fH; y++) { + try { container2D[(item.location as Location).y + y].fill(1, (item.location as Location).x, fillTo); - } - catch (e) - { + } catch (e) { this.logger.error( this.localisationService.getText("inventory-unable_to_fill_container", { id: item._id, @@ -871,20 +772,16 @@ export class InventoryHelper return container2D; } - protected getInventoryItemHash(inventoryItem: Item[]): InventoryHelper.InventoryItemHash - { + protected getInventoryItemHash(inventoryItem: Item[]): InventoryHelper.InventoryItemHash { const inventoryItemHash: InventoryHelper.InventoryItemHash = { byItemId: {}, byParentId: {} }; - for (const item of inventoryItem) - { + for (const item of inventoryItem) { inventoryItemHash.byItemId[item._id] = item; - if (!("parentId" in item)) - { + if (!("parentId" in item)) { continue; } - if (!(item.parentId in inventoryItemHash.byParentId)) - { + if (!(item.parentId in inventoryItemHash.byParentId)) { inventoryItemHash.byParentId[item.parentId] = []; } inventoryItemHash.byParentId[item.parentId].push(item); @@ -902,27 +799,22 @@ export class InventoryHelper */ public getOwnerInventoryItems( request: - | IInventoryMoveRequestData - | IInventorySplitRequestData - | IInventoryMergeRequestData - | IInventoryTransferRequestData, + | IInventoryMoveRequestData + | IInventorySplitRequestData + | IInventoryMergeRequestData + | IInventoryTransferRequestData, sessionId: string, - ): IOwnerInventoryItems - { + ): IOwnerInventoryItems { const pmcItems = this.profileHelper.getPmcProfile(sessionId).Inventory.items; const scavProfile = this.profileHelper.getScavProfile(sessionId); let fromInventoryItems = pmcItems; let fromType = "pmc"; - if (request.fromOwner) - { - if (request.fromOwner.id === scavProfile._id) - { + if (request.fromOwner) { + if (request.fromOwner.id === scavProfile._id) { fromInventoryItems = scavProfile.Inventory.items; fromType = "scav"; - } - else if (request.fromOwner.type.toLocaleLowerCase() === "mail") - { + } else if (request.fromOwner.type.toLocaleLowerCase() === "mail") { // Split requests dont use 'use' but 'splitItem' property const item = "splitItem" in request ? request.splitItem : request.item; fromInventoryItems = this.dialogueHelper.getMessageItemContents(request.fromOwner.id, sessionId, item); @@ -936,8 +828,7 @@ export class InventoryHelper let toType = "pmc"; // Destination is scav inventory, update values - if (request.toOwner?.id === scavProfile._id) - { + if (request.toOwner?.id === scavProfile._id) { toInventoryItems = scavProfile.Inventory.items; toType = "scav"; } @@ -960,8 +851,7 @@ export class InventoryHelper * @param sessionID session id * @returns 2-dimensional array */ - protected getStashSlotMap(pmcData: IPmcData, sessionID: string): number[][] - { + protected getStashSlotMap(pmcData: IPmcData, sessionID: string): number[][] { const playerStashSize = this.getPlayerStashSize(sessionID); return this.getContainerMap( playerStashSize[0], @@ -976,8 +866,7 @@ export class InventoryHelper * @param containerTpl Container to get data for * @returns blank two-dimensional array */ - public getContainerSlotMap(containerTpl: string): number[][] - { + public getContainerSlotMap(containerTpl: string): number[][] { const containerTemplate = this.itemHelper.getItem(containerTpl)[1]; const containerH = containerTemplate._props.Grids[0]._props.cellsH; @@ -991,8 +880,7 @@ export class InventoryHelper * @param pmcData Player profile * @returns two-dimensional array */ - protected getSortingTableSlotMap(pmcData: IPmcData): number[][] - { + protected getSortingTableSlotMap(pmcData: IPmcData): number[][] { return this.getContainerMap(10, 45, pmcData.Inventory.items, pmcData.Inventory.sortingTable); } @@ -1001,21 +889,18 @@ export class InventoryHelper * @param sessionID Players id * @returns Array of 2 values, horizontal and vertical stash size */ - protected getPlayerStashSize(sessionID: string): Record - { + protected getPlayerStashSize(sessionID: string): Record { const profile = this.profileHelper.getPmcProfile(sessionID); const stashRowBonus = profile.Bonuses.find((bonus) => bonus.type === BonusType.STASH_ROWS); // this sets automatically a stash size from items.json (its not added anywhere yet cause we still use base stash) const stashTPL = this.getStashType(sessionID); - if (!stashTPL) - { + if (!stashTPL) { this.logger.error(this.localisationService.getText("inventory-missing_stash_size")); } const stashItemResult = this.itemHelper.getItem(stashTPL); - if (!stashItemResult[0]) - { + if (!stashItemResult[0]) { this.logger.error(this.localisationService.getText("inventory-stash_not_found", stashTPL)); return; @@ -1028,8 +913,7 @@ export class InventoryHelper let stashV = firstStashItemGrid._props.cellsV !== 0 ? firstStashItemGrid._props.cellsV : 66; // Player has a bonus, apply to vertical size - if (stashRowBonus) - { + if (stashRowBonus) { stashV += stashRowBonus.value; } @@ -1041,12 +925,10 @@ export class InventoryHelper * @param sessionID Player id * @returns Stash tpl */ - protected getStashType(sessionID: string): string - { + protected getStashType(sessionID: string): string { const pmcData = this.profileHelper.getPmcProfile(sessionID); const stashObj = pmcData.Inventory.items.find((item) => item._id === pmcData.Inventory.stash); - if (!stashObj) - { + if (!stashObj) { this.logger.error(this.localisationService.getText("inventory-unable_to_find_stash")); } @@ -1059,37 +941,29 @@ export class InventoryHelper * @param toItems Inventory of the destination * @param request Move request */ - public moveItemToProfile(sourceItems: Item[], toItems: Item[], request: IInventoryMoveRequestData): void - { + public moveItemToProfile(sourceItems: Item[], toItems: Item[], request: IInventoryMoveRequestData): void { this.handleCartridges(sourceItems, request); // Get all children item has, they need to move with item const idsToMove = this.itemHelper.findAndReturnChildrenByItems(sourceItems, request.item); - for (const itemId of idsToMove) - { + for (const itemId of idsToMove) { const itemToMove = sourceItems.find((item) => item._id === itemId); - if (!itemToMove) - { + if (!itemToMove) { this.logger.error(this.localisationService.getText("inventory-unable_to_find_item_to_move", itemId)); continue; } // Only adjust the values for parent item, not children (their values are already correctly tied to parent) - if (itemId === request.item) - { + if (itemId === request.item) { itemToMove.parentId = request.to.id; itemToMove.slotId = request.to.container; - if (request.to.location) - { + if (request.to.location) { // Update location object itemToMove.location = request.to.location; - } - else - { + } else { // No location in request, delete it - if (itemToMove.location) - { + if (itemToMove.location) { delete itemToMove.location; } } @@ -1111,14 +985,12 @@ export class InventoryHelper pmcData: IPmcData, inventoryItems: Item[], moveRequest: IInventoryMoveRequestData, - ): { success: boolean, errorMessage?: string } - { + ): { success: boolean; errorMessage?: string } { this.handleCartridges(inventoryItems, moveRequest); // Find item we want to 'move' const matchingInventoryItem = inventoryItems.find((item) => item._id === moveRequest.item); - if (!matchingInventoryItem) - { + if (!matchingInventoryItem) { const errorMesage = `Unable to move item: ${moveRequest.item}, cannot find in inventory`; this.logger.error(errorMesage); @@ -1130,8 +1002,7 @@ export class InventoryHelper ); // Don't move shells from camora to cartridges (happens when loading shells into mts-255 revolver shotgun) - if (matchingInventoryItem.slotId?.includes("camora_") && moveRequest.to.container === "cartridges") - { + if (matchingInventoryItem.slotId?.includes("camora_") && moveRequest.to.container === "cartridges") { this.logger.warning( this.localisationService.getText("inventory-invalid_move_to_container", { slotId: matchingInventoryItem.slotId, @@ -1150,15 +1021,11 @@ export class InventoryHelper this.updateFastPanelBinding(pmcData, matchingInventoryItem); // Item has location propery, ensure its value is handled - if ("location" in moveRequest.to) - { + if ("location" in moveRequest.to) { matchingInventoryItem.location = moveRequest.to.location; - } - else - { + } else { // Moved from slot with location to one without, clean up - if (matchingInventoryItem.location) - { + if (matchingInventoryItem.location) { delete matchingInventoryItem.location; } } @@ -1171,27 +1038,26 @@ export class InventoryHelper * @param pmcData Player profile * @param itemBeingMoved item being moved */ - protected updateFastPanelBinding(pmcData: IPmcData, itemBeingMoved: Item): void - { + protected updateFastPanelBinding(pmcData: IPmcData, itemBeingMoved: Item): void { // Find matching _id in fast panel - const fastPanelSlot = Object.entries(pmcData.Inventory.fastPanel) - .find(([itemId]) => itemId === itemBeingMoved._id); - if (!fastPanelSlot) - { + const fastPanelSlot = Object.entries(pmcData.Inventory.fastPanel).find( + ([itemId]) => itemId === itemBeingMoved._id, + ); + if (!fastPanelSlot) { return; } // Get moved items parent (should be container item was put into) const itemParent = pmcData.Inventory.items.find((item) => item._id === itemBeingMoved.parentId); - if (!itemParent) - { + if (!itemParent) { return; } // Reset fast panel value if item was moved to a container other than pocket/rig (cant be used from fastpanel) - const wasMovedToFastPanelAccessibleContainer = ["pockets", "tacticalvest"].includes(itemParent?.slotId?.toLowerCase() ?? ""); - if (!wasMovedToFastPanelAccessibleContainer) - { + const wasMovedToFastPanelAccessibleContainer = ["pockets", "tacticalvest"].includes( + itemParent?.slotId?.toLowerCase() ?? "", + ); + if (!wasMovedToFastPanelAccessibleContainer) { pmcData.Inventory.fastPanel[fastPanelSlot[0]] = ""; } } @@ -1199,11 +1065,9 @@ export class InventoryHelper /** * Internal helper function to handle cartridges in inventory if any of them exist. */ - protected handleCartridges(items: Item[], request: IInventoryMoveRequestData): void - { + protected handleCartridges(items: Item[], request: IInventoryMoveRequestData): void { // Not moving item into a cartridge slot, skip - if (request.to.container !== "cartridges") - { + if (request.to.container !== "cartridges") { return; } @@ -1218,13 +1082,11 @@ export class InventoryHelper * @param itemTpl Container being opened * @returns Reward details */ - public getRandomLootContainerRewardDetails(itemTpl: string): RewardDetails - { + public getRandomLootContainerRewardDetails(itemTpl: string): RewardDetails { return this.inventoryConfig.randomLootContainers[itemTpl]; } - public getInventoryConfig(): IInventoryConfig - { + public getInventoryConfig(): IInventoryConfig { return this.inventoryConfig; } @@ -1236,21 +1098,17 @@ export class InventoryHelper * @param itemToCheck Item to look for * @returns True if item exists inside stash */ - public isItemInStash(pmcData: IPmcData, itemToCheck: Item): boolean - { + public isItemInStash(pmcData: IPmcData, itemToCheck: Item): boolean { // Create recursive helper function - const isParentInStash = (itemId: string): boolean => - { + const isParentInStash = (itemId: string): boolean => { // Item not found / has no parent const item = pmcData.Inventory.items.find((item) => item._id === itemId); - if (!item || !item.parentId) - { + if (!item || !item.parentId) { return false; } // Root level. Items parent is the stash with slotId "hideout" - if (item.parentId === pmcData.Inventory.stash && item.slotId === "hideout") - { + if (item.parentId === pmcData.Inventory.stash && item.slotId === "hideout") { return true; } @@ -1263,11 +1121,9 @@ export class InventoryHelper } } -namespace InventoryHelper -{ - export interface InventoryItemHash - { - byItemId: Record - byParentId: Record +namespace InventoryHelper { + export interface InventoryItemHash { + byItemId: Record; + byParentId: Record; } } diff --git a/project/src/helpers/ItemHelper.ts b/project/src/helpers/ItemHelper.ts index 73c1a8ef..f0ae1841 100644 --- a/project/src/helpers/ItemHelper.ts +++ b/project/src/helpers/ItemHelper.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { HandbookHelper } from "@spt/helpers/HandbookHelper"; import { IStaticAmmoDetails } from "@spt/models/eft/common/ILocation"; import { IPmcData } from "@spt/models/eft/common/IPmcData"; @@ -15,17 +14,17 @@ import { ItemBaseClassService } from "@spt/services/ItemBaseClassService"; import { ItemFilterService } from "@spt/services/ItemFilterService"; import { LocaleService } from "@spt/services/LocaleService"; import { LocalisationService } from "@spt/services/LocalisationService"; -import { ICloner } from "@spt/utils/cloners/ICloner"; import { CompareUtil } from "@spt/utils/CompareUtil"; import { HashUtil } from "@spt/utils/HashUtil"; import { JsonUtil } from "@spt/utils/JsonUtil"; import { MathUtil } from "@spt/utils/MathUtil"; import { ObjectId } from "@spt/utils/ObjectId"; import { ProbabilityObject, ProbabilityObjectArray, RandomUtil } from "@spt/utils/RandomUtil"; +import { ICloner } from "@spt/utils/cloners/ICloner"; +import { inject, injectable } from "tsyringe"; @injectable() -export class ItemHelper -{ +export class ItemHelper { protected readonly defaultInvalidBaseTypes: string[] = [ BaseClasses.LOOT_CONTAINER, BaseClasses.MOB_CONTAINER, @@ -51,8 +50,7 @@ export class ItemHelper @inject("LocaleService") protected localeService: LocaleService, @inject("CompareUtil") protected compareUtil: CompareUtil, @inject("PrimaryCloner") protected cloner: ICloner, - ) - {} + ) {} /** * Does the provided pool of items contain the desired item @@ -61,12 +59,9 @@ export class ItemHelper * @param slotId OPTIONAL - slotid of desired item * @returns True if pool contains item */ - public hasItemWithTpl(itemPool: Item[], item: ItemTpl, slotId?: string): boolean - { + public hasItemWithTpl(itemPool: Item[], item: ItemTpl, slotId?: string): boolean { // Filter the pool by slotId if provided - const filteredPool = (slotId) - ? itemPool.filter((item) => item.slotId?.startsWith(slotId)) - : itemPool; + const filteredPool = slotId ? itemPool.filter((item) => item.slotId?.startsWith(slotId)) : itemPool; // Check if any item in the filtered pool matches the provided item return filteredPool.some((poolItem) => poolItem._tpl === item); @@ -79,12 +74,9 @@ export class ItemHelper * @param slotId OPTIONAL - slotid of desired item * @returns Item or undefined */ - public getItemFromPoolByTpl(itemPool: Item[], item: ItemTpl, slotId?: string): Item | undefined - { - // Filter the pool by slotId if provided - const filteredPool = (slotId) - ? itemPool.filter((item) => item.slotId?.startsWith(slotId)) - : itemPool; + public getItemFromPoolByTpl(itemPool: Item[], item: ItemTpl, slotId?: string): Item | undefined { + // Filter the pool by slotId if provided + const filteredPool = slotId ? itemPool.filter((item) => item.slotId?.startsWith(slotId)) : itemPool; // Check if any item in the filtered pool matches the provided item return filteredPool.find((poolItem) => poolItem._tpl === item); @@ -98,21 +90,16 @@ export class ItemHelper * @param compareUpdProperties Upd properties to compare between the items * @returns true if they are the same, false if they arent */ - public isSameItems(item1: Item[], item2: Item[], compareUpdProperties?: Set): boolean - { - if (item1.length !== item2.length) - { + public isSameItems(item1: Item[], item2: Item[], compareUpdProperties?: Set): boolean { + if (item1.length !== item2.length) { return false; } - for (const itemOf1 of item1) - { + for (const itemOf1 of item1) { const itemOf2 = item2.find((i2) => i2._tpl === itemOf1._tpl); - if (itemOf2 === undefined) - { + if (itemOf2 === undefined) { return false; } - if (!this.isSameItem(itemOf1, itemOf2, compareUpdProperties)) - { + if (!this.isSameItem(itemOf1, itemOf2, compareUpdProperties)) { return false; } } @@ -127,15 +114,12 @@ export class ItemHelper * @param compareUpdProperties Upd properties to compare between the items * @returns true if they are the same, false if they arent */ - public isSameItem(item1: Item, item2: Item, compareUpdProperties?: Set): boolean - { - if (item1._tpl !== item2._tpl) - { + public isSameItem(item1: Item, item2: Item, compareUpdProperties?: Set): boolean { + if (item1._tpl !== item2._tpl) { return false; } - if (compareUpdProperties) - { + if (compareUpdProperties) { return Array.from(compareUpdProperties.values()).every((p) => this.compareUtil.recursiveCompare(item1.upd?.[p], item2.upd?.[p]), ); @@ -149,68 +133,53 @@ export class ItemHelper * @param itemTemplate the item template to generate a Upd for * @returns A Upd with all the default properties set */ - public generateUpdForItem(itemTemplate: ITemplateItem): Upd - { + public generateUpdForItem(itemTemplate: ITemplateItem): Upd { const itemProperties: Upd = {}; // armors, etc - if (itemTemplate._props.MaxDurability) - { + if (itemTemplate._props.MaxDurability) { itemProperties.Repairable = { Durability: itemTemplate._props.MaxDurability, MaxDurability: itemTemplate._props.MaxDurability, }; } - if (itemTemplate._props.HasHinge) - { + if (itemTemplate._props.HasHinge) { itemProperties.Togglable = { On: true }; } - if (itemTemplate._props.Foldable) - { + if (itemTemplate._props.Foldable) { itemProperties.Foldable = { Folded: false }; } - if (itemTemplate._props.weapFireType?.length) - { - if (itemTemplate._props.weapFireType.includes("fullauto")) - { + if (itemTemplate._props.weapFireType?.length) { + if (itemTemplate._props.weapFireType.includes("fullauto")) { itemProperties.FireMode = { FireMode: "fullauto" }; - } - else - { + } else { itemProperties.FireMode = { FireMode: this.randomUtil.getArrayValue(itemTemplate._props.weapFireType) }; } } - if (itemTemplate._props.MaxHpResource) - { + if (itemTemplate._props.MaxHpResource) { itemProperties.MedKit = { HpResource: itemTemplate._props.MaxHpResource }; } - if (itemTemplate._props.MaxResource && itemTemplate._props.foodUseTime) - { + if (itemTemplate._props.MaxResource && itemTemplate._props.foodUseTime) { itemProperties.FoodDrink = { HpPercent: itemTemplate._props.MaxResource }; } - if (itemTemplate._parent === BaseClasses.FLASHLIGHT) - { + if (itemTemplate._parent === BaseClasses.FLASHLIGHT) { itemProperties.Light = { IsActive: false, SelectedMode: 0 }; - } - else if (itemTemplate._parent === BaseClasses.TACTICAL_COMBO) - { + } else if (itemTemplate._parent === BaseClasses.TACTICAL_COMBO) { itemProperties.Light = { IsActive: false, SelectedMode: 0 }; } - if (itemTemplate._parent === BaseClasses.NIGHTVISION) - { + if (itemTemplate._parent === BaseClasses.NIGHTVISION) { itemProperties.Togglable = { On: false }; } // Togglable face shield - if (itemTemplate._props.HasHinge && itemTemplate._props.FaceShieldComponent) - { + if (itemTemplate._props.HasHinge && itemTemplate._props.FaceShieldComponent) { itemProperties.Togglable = { On: false }; } @@ -222,22 +191,20 @@ export class ItemHelper * @param {string} tpl the template id / tpl * @returns boolean; true for items that may be in player possession and not quest items */ - public isValidItem(tpl: string, invalidBaseTypes?: string[]): boolean - { + public isValidItem(tpl: string, invalidBaseTypes?: string[]): boolean { const baseTypes = invalidBaseTypes || this.defaultInvalidBaseTypes; const itemDetails = this.getItem(tpl); - if (!itemDetails[0]) - { + if (!itemDetails[0]) { return false; } return ( - !itemDetails[1]._props.QuestItem - && itemDetails[1]._type === "Item" - && baseTypes.every((x) => !this.isOfBaseclass(tpl, x)) - && this.getItemPrice(tpl) > 0 - && !this.itemFilterService.isItemBlacklisted(tpl) + !itemDetails[1]._props.QuestItem && + itemDetails[1]._type === "Item" && + baseTypes.every((x) => !this.isOfBaseclass(tpl, x)) && + this.getItemPrice(tpl) > 0 && + !this.itemFilterService.isItemBlacklisted(tpl) ); } @@ -248,8 +215,7 @@ export class ItemHelper * @param {string} baseClassTpl the baseclass to check for * @return {boolean} is the tpl a descendent? */ - public isOfBaseclass(tpl: string, baseClassTpl: string): boolean - { + public isOfBaseclass(tpl: string, baseClassTpl: string): boolean { return this.itemBaseClassService.itemHasBaseClass(tpl, [baseClassTpl]); } @@ -259,8 +225,7 @@ export class ItemHelper * @param baseClassTpls base classes to check for * @returns true if any supplied base classes match */ - public isOfBaseclasses(tpl: string, baseClassTpls: string[]): boolean - { + public isOfBaseclasses(tpl: string, baseClassTpls: string[]): boolean { return this.itemBaseClassService.itemHasBaseClass(tpl, baseClassTpls); } @@ -271,8 +236,7 @@ export class ItemHelper * @param itemTpl item to check * @returns Does item have the possibility ot need soft inserts */ - public armorItemCanHoldMods(itemTpl: string): boolean - { + public armorItemCanHoldMods(itemTpl: string): boolean { return this.isOfBaseclasses(itemTpl, [BaseClasses.HEADWEAR, BaseClasses.VEST, BaseClasses.ARMOR]); } @@ -281,10 +245,8 @@ export class ItemHelper * @param itemTpl Armor item * @returns True if item needs some kind of insert */ - public armorItemHasRemovableOrSoftInsertSlots(itemTpl: string): boolean - { - if (!this.armorItemCanHoldMods(itemTpl)) - { + public armorItemHasRemovableOrSoftInsertSlots(itemTpl: string): boolean { + if (!this.armorItemCanHoldMods(itemTpl)) { return false; } @@ -296,8 +258,7 @@ export class ItemHelper * @param itemTpl item tpl to check for plate support * @returns True when armor can hold plates */ - public armorItemHasRemovablePlateSlots(itemTpl: string): boolean - { + public armorItemHasRemovablePlateSlots(itemTpl: string): boolean { const itemTemplate = this.getItem(itemTpl); const plateSlotIds = this.getRemovablePlateSlotIds(); @@ -309,31 +270,26 @@ export class ItemHelper * @param itemTpl Item tpl to check * @returns True if it needs armor inserts */ - public itemRequiresSoftInserts(itemTpl: string): boolean - { + public itemRequiresSoftInserts(itemTpl: string): boolean { // not a slot that takes soft-inserts - if (!this.armorItemCanHoldMods(itemTpl)) - { + if (!this.armorItemCanHoldMods(itemTpl)) { return false; } // Check is an item const itemDbDetails = this.getItem(itemTpl); - if (!itemDbDetails[0]) - { + if (!itemDbDetails[0]) { return false; } // Has no slots - if (!(itemDbDetails[1]._props.Slots ?? []).length) - { + if (!(itemDbDetails[1]._props.Slots ?? []).length) { return false; } // Check if item has slots that match soft insert name ids const softInsertIds = this.getSoftInsertSlotIds(); - if (itemDbDetails[1]._props.Slots.some((slot) => softInsertIds.includes(slot._name.toLowerCase()))) - { + if (itemDbDetails[1]._props.Slots.some((slot) => softInsertIds.includes(slot._name.toLowerCase()))) { return true; } @@ -344,8 +300,7 @@ export class ItemHelper * Get all soft insert slot ids * @returns An array of soft insert ids (e.g. soft_armor_back, helmet_top) */ - public getSoftInsertSlotIds(): string[] - { + public getSoftInsertSlotIds(): string[] { return [ "groin", "groin_back", @@ -370,8 +325,7 @@ export class ItemHelper * @param tpls item tpls to look up the price of * @returns Total price in roubles */ - public getItemAndChildrenPrice(tpls: string[]): number - { + public getItemAndChildrenPrice(tpls: string[]): number { // Run getItemPrice for each tpl in tpls array, return sum return tpls.reduce((total, tpl) => total + this.getItemPrice(tpl), 0); } @@ -382,17 +336,14 @@ export class ItemHelper * @param tpl Item to look price up of * @returns Price in roubles */ - public getItemPrice(tpl: string): number - { + public getItemPrice(tpl: string): number { const handbookPrice = this.getStaticItemPrice(tpl); - if (handbookPrice >= 1) - { + if (handbookPrice >= 1) { return handbookPrice; } const dynamicPrice = this.getDynamicItemPrice(tpl); - if (dynamicPrice) - { + if (dynamicPrice) { return dynamicPrice; } @@ -405,8 +356,7 @@ export class ItemHelper * @param tpl Item to look price up of * @returns Price in roubles */ - public getItemMaxPrice(tpl: string): number - { + public getItemMaxPrice(tpl: string): number { const staticPrice = this.getStaticItemPrice(tpl); const dynamicPrice = this.getDynamicItemPrice(tpl); @@ -418,11 +368,9 @@ export class ItemHelper * @param tpl Items tpl id to look up price * @returns Price in roubles (0 if not found) */ - public getStaticItemPrice(tpl: string): number - { + public getStaticItemPrice(tpl: string): number { const handbookPrice = this.handbookHelper.getTemplatePrice(tpl); - if (handbookPrice >= 1) - { + if (handbookPrice >= 1) { return handbookPrice; } @@ -434,11 +382,9 @@ export class ItemHelper * @param tpl Items tpl id to look up price * @returns Price in roubles (undefined if not found) */ - public getDynamicItemPrice(tpl: string): number - { + public getDynamicItemPrice(tpl: string): number { const dynamicPrice = this.databaseService.getPrices()[tpl]; - if (dynamicPrice) - { + if (dynamicPrice) { return dynamicPrice; } @@ -450,15 +396,12 @@ export class ItemHelper * @param item Item to update * @returns Fixed item */ - public fixItemStackCount(item: Item): Item - { - if (item.upd === undefined) - { + public fixItemStackCount(item: Item): Item { + if (item.upd === undefined) { item.upd = { StackObjectsCount: 1 }; } - if (item.upd.StackObjectsCount === undefined) - { + if (item.upd.StackObjectsCount === undefined) { item.upd.StackObjectsCount = 1; } return item; @@ -468,8 +411,7 @@ export class ItemHelper * Get cloned copy of all item data from items.json * @returns array of ITemplateItem objects */ - public getItems(): ITemplateItem[] - { + public getItems(): ITemplateItem[] { return this.cloner.clone(Object.values(this.databaseService.getItems())); } @@ -478,24 +420,20 @@ export class ItemHelper * @param tpl items template id to look up * @returns bool - is valid + template item object as array */ - public getItem(tpl: string): [boolean, ITemplateItem] - { + public getItem(tpl: string): [boolean, ITemplateItem] { // -> Gets item from - if (tpl in this.databaseService.getItems()) - { + if (tpl in this.databaseService.getItems()) { return [true, this.databaseService.getItems()[tpl]]; } return [false, undefined]; } - public itemHasSlots(itemTpl: string): boolean - { + public itemHasSlots(itemTpl: string): boolean { return this.getItem(itemTpl)[1]._props.Slots?.length > 0; } - public isItemInDb(tpl: string): boolean - { + public isItemInDb(tpl: string): boolean { const itemDetails = this.getItem(tpl); return itemDetails[0]; @@ -507,20 +445,16 @@ export class ItemHelper * @param skipArmorItemsWithoutDurability Skip over armor items without durability * @returns % quality modifer between 0 and 1 */ - public getItemQualityModifierForItems(items: Item[], skipArmorItemsWithoutDurability?: boolean): number - { - if (this.isOfBaseclass(items[0]._tpl, BaseClasses.WEAPON)) - { + public getItemQualityModifierForItems(items: Item[], skipArmorItemsWithoutDurability?: boolean): number { + if (this.isOfBaseclass(items[0]._tpl, BaseClasses.WEAPON)) { return this.getItemQualityModifier(items[0]); } let qualityModifier = 0; let itemsWithQualityCount = 0; - for (const item of items) - { + for (const item of items) { const result = this.getItemQualityModifier(item, skipArmorItemsWithoutDurability); - if (result === -1) - { + if (result === -1) { continue; } @@ -528,8 +462,7 @@ export class ItemHelper itemsWithQualityCount++; } - if (itemsWithQualityCount === 0) - { + if (itemsWithQualityCount === 0) { // Can happen when rigs without soft inserts or plates are listed return 1; } @@ -544,22 +477,21 @@ export class ItemHelper * @param skipArmorItemsWithoutDurability return -1 for armor items that have maxdurability of 0 * @returns Number between 0 and 1 */ - public getItemQualityModifier(item: Item, skipArmorItemsWithoutDurability?: boolean): number - { + public getItemQualityModifier(item: Item, skipArmorItemsWithoutDurability?: boolean): number { // Default to 100% let result = 1; // Is armor and has 0 max durability const itemDetails = this.getItem(item._tpl)[1]; - if (skipArmorItemsWithoutDurability - && this.isOfBaseclass(item._tpl, BaseClasses.ARMOR) - && itemDetails._props.MaxDurability === 0) - { + if ( + skipArmorItemsWithoutDurability && + this.isOfBaseclass(item._tpl, BaseClasses.ARMOR) && + itemDetails._props.MaxDurability === 0 + ) { return -1; } - if (item.upd) - { + if (item.upd) { const medkit = item.upd.MedKit ? item.upd.MedKit : undefined; const repairable = item.upd.Repairable ? item.upd.Repairable : undefined; const foodDrink = item.upd.FoodDrink ? item.upd.FoodDrink : undefined; @@ -567,39 +499,27 @@ export class ItemHelper const resource = item.upd.Resource ? item.upd.Resource : undefined; const repairKit = item.upd.RepairKit ? item.upd.RepairKit : undefined; - if (medkit) - { + if (medkit) { // Meds result = medkit.HpResource / itemDetails._props.MaxHpResource; - } - else if (repairable) - { + } else if (repairable) { result = this.getRepairableItemQualityValue(itemDetails, repairable, item); - } - else if (foodDrink) - { + } else if (foodDrink) { // food & drink result = foodDrink.HpPercent / itemDetails._props.MaxResource; - } - else if (key && key.NumberOfUsages > 0 && itemDetails._props.MaximumNumberOfUsage > 0) - { + } else if (key && key.NumberOfUsages > 0 && itemDetails._props.MaximumNumberOfUsage > 0) { // keys - keys count upwards, not down like everything else const maxNumOfUsages = itemDetails._props.MaximumNumberOfUsage; result = (maxNumOfUsages - key.NumberOfUsages) / maxNumOfUsages; - } - else if (resource && resource.UnitsConsumed > 0) - { + } else if (resource && resource.UnitsConsumed > 0) { // Things like fuel tank result = resource.Value / itemDetails._props.MaxResource; - } - else if (repairKit) - { + } else if (repairKit) { // Repair kits result = repairKit.Resource / itemDetails._props.MaxRepairResource; } - if (result === 0) - { + if (result === 0) { // make item non-zero but still very low result = 0.01; } @@ -617,11 +537,9 @@ export class ItemHelper * @param item Item quality value is for * @returns A number between 0 and 1 */ - protected getRepairableItemQualityValue(itemDetails: ITemplateItem, repairable: Repairable, item: Item): number - { + protected getRepairableItemQualityValue(itemDetails: ITemplateItem, repairable: Repairable, item: Item): number { // Edge case, max durability is below durability - if (repairable.Durability > repairable.MaxDurability) - { + if (repairable.Durability > repairable.MaxDurability) { this.logger.warning( `Max durability: ${repairable.MaxDurability} for item id: ${item._id} was below durability: ${repairable.Durability}, adjusting values to match`, ); @@ -634,8 +552,7 @@ export class ItemHelper : repairable.MaxDurability; const durability = repairable.Durability / maxDurability; - if (!durability) - { + if (!durability) { this.logger.error(this.localisationService.getText("item-durability_value_invalid_use_default", item._tpl)); return 1; @@ -650,14 +567,11 @@ export class ItemHelper * @param baseItemId Parent items id * @returns an array of strings */ - public findAndReturnChildrenByItems(items: Item[], baseItemId: string): string[] - { + public findAndReturnChildrenByItems(items: Item[], baseItemId: string): string[] { const list: string[] = []; - for (const childitem of items) - { - if (childitem.parentId === baseItemId) - { + for (const childitem of items) { + if (childitem.parentId === baseItemId) { list.push(...this.findAndReturnChildrenByItems(items, childitem._id)); } } @@ -674,27 +588,22 @@ export class ItemHelper * @param modsOnly Include only mod items, exclude items stored inside root item * @returns An array of Item objects */ - public findAndReturnChildrenAsItems(items: Item[], baseItemId: string, modsOnly = false): Item[] - { + public findAndReturnChildrenAsItems(items: Item[], baseItemId: string, modsOnly = false): Item[] { const list: Item[] = []; - for (const childItem of items) - { + for (const childItem of items) { // Include itself - if (childItem._id === baseItemId) - { + if (childItem._id === baseItemId) { list.unshift(childItem); continue; } // Is stored in parent and disallowed - if (modsOnly && childItem.location) - { + if (modsOnly && childItem.location) { continue; } // Items parentid matches root item AND returned items doesnt contain current child - if (childItem.parentId === baseItemId && !list.some((item) => childItem._id === item._id)) - { + if (childItem.parentId === baseItemId && !list.some((item) => childItem._id === item._id)) { list.push(...this.findAndReturnChildrenAsItems(items, childItem._id)); } } @@ -708,14 +617,11 @@ export class ItemHelper * @param assort Array of items to check in * @returns Array of children of requested item */ - public findAndReturnChildrenByAssort(itemIdToFind: string, assort: Item[]): Item[] - { + public findAndReturnChildrenByAssort(itemIdToFind: string, assort: Item[]): Item[] { let list: Item[] = []; - for (const itemFromAssort of assort) - { - if (itemFromAssort.parentId === itemIdToFind && !list.some((item) => itemFromAssort._id === item._id)) - { + for (const itemFromAssort of assort) { + if (itemFromAssort.parentId === itemIdToFind && !list.some((item) => itemFromAssort._id === item._id)) { list.push(itemFromAssort); list = list.concat(this.findAndReturnChildrenByAssort(itemFromAssort._id, assort)); } @@ -729,10 +635,8 @@ export class ItemHelper * @param itemToCheck Item to check * @returns true if it has buy restrictions */ - public hasBuyRestrictions(itemToCheck: Item): boolean - { - if (itemToCheck.upd?.BuyRestrictionCurrent !== undefined && itemToCheck.upd?.BuyRestrictionMax !== undefined) - { + public hasBuyRestrictions(itemToCheck: Item): boolean { + if (itemToCheck.upd?.BuyRestrictionCurrent !== undefined && itemToCheck.upd?.BuyRestrictionMax !== undefined) { return true; } @@ -744,8 +648,7 @@ export class ItemHelper * @param tpl Template id to check * @returns true if it is a dogtag */ - public isDogtag(tpl: string): boolean - { + public isDogtag(tpl: string): boolean { const dogTagTpls = [ ItemTpl.BARTER_DOGTAG_BEAR, ItemTpl.BARTER_DOGTAG_BEAR_EOD, @@ -763,10 +666,8 @@ export class ItemHelper * @param item * @returns "slotId OR slotid,locationX,locationY" */ - public getChildId(item: Item): string - { - if (!("location" in item)) - { + public getChildId(item: Item): string { + if (!("location" in item)) { return item.slotId; } @@ -778,11 +679,9 @@ export class ItemHelper * @param tpl item to check * @returns true if it can be stacked */ - public isItemTplStackable(tpl: string): boolean - { + public isItemTplStackable(tpl: string): boolean { const item = this.databaseService.getItems()[tpl]; - if (!item) - { + if (!item) { return undefined; } @@ -794,10 +693,8 @@ export class ItemHelper * @param itemToSplit Item to split into smaller stacks * @returns Array of root item + children */ - public splitStack(itemToSplit: Item): Item[] - { - if (itemToSplit?.upd?.StackObjectsCount === undefined) - { + public splitStack(itemToSplit: Item): Item[] { + if (itemToSplit?.upd?.StackObjectsCount === undefined) { return [itemToSplit]; } @@ -807,15 +704,13 @@ export class ItemHelper // If the current count is already equal or less than the max // return the item as is. - if (remainingCount <= maxStackSize) - { + if (remainingCount <= maxStackSize) { rootAndChildren.push(this.cloner.clone(itemToSplit)); return rootAndChildren; } - while (remainingCount) - { + while (remainingCount) { const amount = Math.min(remainingCount, maxStackSize); const newStackClone = this.cloner.clone(itemToSplit); @@ -833,22 +728,19 @@ export class ItemHelper * @param itemToSplit Item to split into smaller stacks * @returns */ - public splitStackIntoSeparateItems(itemToSplit: Item): Item[][] - { + public splitStackIntoSeparateItems(itemToSplit: Item): Item[][] { const itemTemplate = this.getItem(itemToSplit._tpl)[1]; const itemMaxStackSize = itemTemplate._props.StackMaxSize ?? 1; // item already within bounds of stack size, return it - if (itemToSplit.upd?.StackObjectsCount <= itemMaxStackSize) - { + if (itemToSplit.upd?.StackObjectsCount <= itemMaxStackSize) { return [[itemToSplit]]; } // Split items stack into chunks const result: Item[][] = []; let remainingCount = itemToSplit.upd.StackObjectsCount; - while (remainingCount) - { + while (remainingCount) { const amount = Math.min(remainingCount, itemMaxStackSize); const newItemClone = this.cloner.clone(itemToSplit); @@ -868,25 +760,21 @@ export class ItemHelper * @param {string} desiredBarterItemIds * @returns Array of Item objects */ - public findBarterItems(by: "tpl" | "id", itemsToSearch: Item[], desiredBarterItemIds: string | string[]): Item[] - { + public findBarterItems(by: "tpl" | "id", itemsToSearch: Item[], desiredBarterItemIds: string | string[]): Item[] { // Find required items to take after buying (handles multiple items) - const desiredBarterIds - = typeof desiredBarterItemIds === "string" ? [desiredBarterItemIds] : desiredBarterItemIds; + const desiredBarterIds = + typeof desiredBarterItemIds === "string" ? [desiredBarterItemIds] : desiredBarterItemIds; const matchingItems: Item[] = []; - for (const barterId of desiredBarterIds) - { - const filterResult = itemsToSearch.filter((item) => - { + for (const barterId of desiredBarterIds) { + const filterResult = itemsToSearch.filter((item) => { return by === "tpl" ? item._tpl === barterId : item._id === barterId; }); matchingItems.push(...filterResult); } - if (matchingItems.length === 0) - { + if (matchingItems.length === 0) { this.logger.warning(`No items found for barter Id: ${desiredBarterIds}`); } @@ -908,30 +796,25 @@ export class ItemHelper pmcData?: IPmcData, insuredItems?: IInsuredItem[], fastPanel?: any, - ): Item[] - { + ): Item[] { let items = this.cloner.clone(originalItems); // Deep-clone the items to avoid mutation. let serialisedInventory = this.jsonUtil.serialize(items); - for (const item of items) - { - if (pmcData) - { + for (const item of items) { + if (pmcData) { // Insured items should not be renamed. Only works for PMCs. - if (insuredItems?.find((insuredItem) => insuredItem.itemId === item._id)) - { + if (insuredItems?.find((insuredItem) => insuredItem.itemId === item._id)) { continue; } // Do not replace the IDs of specific types of items. if ( - item._id === pmcData.Inventory.equipment - || item._id === pmcData.Inventory.questRaidItems - || item._id === pmcData.Inventory.questStashItems - || item._id === pmcData.Inventory.sortingTable - || item._id === pmcData.Inventory.stash - ) - { + item._id === pmcData.Inventory.equipment || + item._id === pmcData.Inventory.questRaidItems || + item._id === pmcData.Inventory.questStashItems || + item._id === pmcData.Inventory.sortingTable || + item._id === pmcData.Inventory.stash + ) { continue; } } @@ -942,12 +825,9 @@ export class ItemHelper serialisedInventory = serialisedInventory.replace(new RegExp(oldId, "g"), newId); // Also replace in quick slot if the old ID exists. - if (fastPanel) - { - for (const itemSlot in fastPanel) - { - if (fastPanel[itemSlot] === oldId) - { + if (fastPanel) { + for (const itemSlot in fastPanel) { + if (fastPanel[itemSlot] === oldId) { fastPanel[itemSlot] = fastPanel[itemSlot].replace(new RegExp(oldId, "g"), newId); } } @@ -966,16 +846,13 @@ export class ItemHelper // First scan - Check which ids are duplicated. // Second scan - Map parents to items. // Third scan - Resolve IDs. - for (const item of items) - { + for (const item of items) { dupes[item._id] = (dupes[item._id] || 0) + 1; } - for (const item of items) - { + for (const item of items) { // register the parents - if (dupes[item._id] > 1) - { + if (dupes[item._id] > 1) { const newId = this.hashUtil.generate(); newParents[item.parentId] = newParents[item.parentId] || []; @@ -985,26 +862,21 @@ export class ItemHelper } } - for (const item of items) - { - if (dupes[item._id] > 1) - { + for (const item of items) { + if (dupes[item._id] > 1) { const oldId = item._id; const newId = oldToNewIds[oldId].splice(0, 1)[0]; item._id = newId; // Extract one of the children that's also duplicated. - if (oldId in newParents && newParents[oldId].length > 0) - { + if (oldId in newParents && newParents[oldId].length > 0) { childrenMapping[newId] = {}; - for (const childIndex in newParents[oldId]) - { + for (const childIndex in newParents[oldId]) { // Make sure we haven't already assigned another duplicate child of // same slot and location to this parent. const childId = this.getChildId(newParents[oldId][childIndex]); - if (!(childId in childrenMapping[newId])) - { + if (!(childId in childrenMapping[newId])) { childrenMapping[newId][childId] = 1; newParents[oldId][childIndex].parentId = newId; // Some very fucking sketchy stuff on this childIndex @@ -1024,12 +896,9 @@ export class ItemHelper * Modifies passed in items * @param items The list of items to mark as FiR */ - public setFoundInRaid(items: Item[]): void - { - for (const item of items) - { - if (!item.upd) - { + public setFoundInRaid(items: Item[]): void { + for (const item of items) { + if (!item.upd) { item.upd = {}; } @@ -1043,33 +912,28 @@ export class ItemHelper * @param {Array} tplsToCheck Tpl values to check if parents of item match * @returns boolean Match found */ - public doesItemOrParentsIdMatch(tpl: string, tplsToCheck: string[]): boolean - { + public doesItemOrParentsIdMatch(tpl: string, tplsToCheck: string[]): boolean { const itemDetails = this.getItem(tpl); const itemExists = itemDetails[0]; const item = itemDetails[1]; // not an item, drop out - if (!itemExists) - { + if (!itemExists) { return false; } // no parent to check - if (!item._parent) - { + if (!item._parent) { return false; } // Does templateId match any values in tplsToCheck array - if (tplsToCheck.includes(item._id)) - { + if (tplsToCheck.includes(item._id)) { return true; } // Does the items parent type exist in tplsToCheck array - if (tplsToCheck.includes(item._parent)) - { + if (tplsToCheck.includes(item._parent)) { return true; } @@ -1082,11 +946,9 @@ export class ItemHelper * @param tpl Items tpl to check quest status of * @returns true if item is flagged as quest item */ - public isQuestItem(tpl: string): boolean - { + public isQuestItem(tpl: string): boolean { const itemDetails = this.getItem(tpl); - if (itemDetails[0] && itemDetails[1]._props.QuestItem) - { + if (itemDetails[0] && itemDetails[1]._props.QuestItem) { return true; } @@ -1104,11 +966,9 @@ export class ItemHelper * @param parent The parent of the item to be checked * @returns True if the item is actually moddable, false if it is not, and undefined if the check cannot be performed. */ - public isRaidModdable(item: Item, parent: Item): boolean | undefined - { + public isRaidModdable(item: Item, parent: Item): boolean | undefined { // This check requires the item to have the slotId property populated. - if (!item.slotId) - { + if (!item.slotId) { return undefined; } @@ -1117,15 +977,13 @@ export class ItemHelper // Check for RaidModdable property on the item template. let isNotRaidModdable = false; - if (itemTemplate[0]) - { + if (itemTemplate[0]) { isNotRaidModdable = itemTemplate[1]?._props?.RaidModdable === false; } // Check to see if the slot that the item is attached to is marked as required in the parent item's template. let isRequiredSlot = false; - if (parentTemplate[0] && parentTemplate[1]?._props?.Slots) - { + if (parentTemplate[0] && parentTemplate[1]?._props?.Slots) { isRequiredSlot = parentTemplate[1]._props.Slots.some( (slot) => slot._name === item.slotId && slot._required, ); @@ -1150,14 +1008,11 @@ export class ItemHelper * @param itemsMap - A Map containing item IDs mapped to their corresponding Item objects for quick lookup. * @returns The Item object representing the top-most parent of the given item, or `undefined` if no such parent exists. */ - public getAttachmentMainParent(itemId: string, itemsMap: Map): Item | undefined - { + public getAttachmentMainParent(itemId: string, itemsMap: Map): Item | undefined { let currentItem = itemsMap.get(itemId); - while (currentItem && this.isAttachmentAttached(currentItem)) - { + while (currentItem && this.isAttachmentAttached(currentItem)) { currentItem = itemsMap.get(currentItem.parentId); - if (!currentItem) - { + if (!currentItem) { return undefined; } } @@ -1170,14 +1025,13 @@ export class ItemHelper * @param item The item to check. * @returns true if the item is attached attachment, otherwise false. */ - public isAttachmentAttached(item: Item): boolean - { + public isAttachmentAttached(item: Item): boolean { const equipmentSlots = Object.values(EquipmentSlots).map((value) => value as string); return !( - ["hideout", "main"].includes(item.slotId) - || equipmentSlots.includes(item.slotId) - || !Number.isNaN(Number(item.slotId)) + ["hideout", "main"].includes(item.slotId) || + equipmentSlots.includes(item.slotId) || + !Number.isNaN(Number(item.slotId)) ); } @@ -1196,16 +1050,13 @@ export class ItemHelper * @param itemsMap - A Map containing item IDs mapped to their corresponding Item objects for quick lookup. * @returns The Item object representing the equipment parent of the given item, or `undefined` if no such parent exists. */ - public getEquipmentParent(itemId: string, itemsMap: Map): Item | undefined - { + public getEquipmentParent(itemId: string, itemsMap: Map): Item | undefined { let currentItem = itemsMap.get(itemId); const equipmentSlots = Object.values(EquipmentSlots).map((value) => value as string); - while (currentItem && !equipmentSlots.includes(currentItem.slotId)) - { + while (currentItem && !equipmentSlots.includes(currentItem.slotId)) { currentItem = itemsMap.get(currentItem.parentId); - if (!currentItem) - { + if (!currentItem) { return undefined; } } @@ -1218,8 +1069,7 @@ export class ItemHelper * @param rootItemId * @returns ItemSize object (width and height) */ - public getItemSize(items: Item[], rootItemId: string): ItemHelper.ItemSize - { + public getItemSize(items: Item[], rootItemId: string): ItemHelper.ItemSize { const rootTemplate = this.getItem(items.filter((x) => x._id === rootItemId)[0]._tpl)[1]; const width = rootTemplate._props.Width; const height = rootTemplate._props.Height; @@ -1235,25 +1085,21 @@ export class ItemHelper let forcedRight = 0; const children = this.findAndReturnChildrenAsItems(items, rootItemId); - for (const ci of children) - { + for (const ci of children) { const itemTemplate = this.getItem(ci._tpl)[1]; // Calculating child ExtraSize - if (itemTemplate._props.ExtraSizeForceAdd === true) - { + if (itemTemplate._props.ExtraSizeForceAdd === true) { forcedUp += itemTemplate._props.ExtraSizeUp; forcedDown += itemTemplate._props.ExtraSizeDown; forcedLeft += itemTemplate._props.ExtraSizeLeft; forcedRight += itemTemplate._props.ExtraSizeRight; - } - else - { + } else { sizeUp = sizeUp < itemTemplate._props.ExtraSizeUp ? itemTemplate._props.ExtraSizeUp : sizeUp; sizeDown = sizeDown < itemTemplate._props.ExtraSizeDown ? itemTemplate._props.ExtraSizeDown : sizeDown; sizeLeft = sizeLeft < itemTemplate._props.ExtraSizeLeft ? itemTemplate._props.ExtraSizeLeft : sizeLeft; - sizeRight - = sizeRight < itemTemplate._props.ExtraSizeRight ? itemTemplate._props.ExtraSizeRight : sizeRight; + sizeRight = + sizeRight < itemTemplate._props.ExtraSizeRight ? itemTemplate._props.ExtraSizeRight : sizeRight; } } @@ -1268,12 +1114,10 @@ export class ItemHelper * @param item Db item template to look up Cartridge filter values from * @returns Caliber of cartridge */ - public getRandomCompatibleCaliberTemplateId(item: ITemplateItem): string | undefined - { + public getRandomCompatibleCaliberTemplateId(item: ITemplateItem): string | undefined { const cartridges = item?._props?.Cartridges[0]?._props?.filters[0]?.Filter; - if (!cartridges) - { + if (!cartridges) { this.logger.warning(`Failed to find cartridge for item: ${item?._id} ${item?._name}`); return undefined; } @@ -1286,16 +1130,14 @@ export class ItemHelper * @param ammoBox Box to add cartridges to * @param ammoBoxDetails Item template from items db */ - public addCartridgesToAmmoBox(ammoBox: Item[], ammoBoxDetails: ITemplateItem): void - { + public addCartridgesToAmmoBox(ammoBox: Item[], ammoBoxDetails: ITemplateItem): void { const ammoBoxMaxCartridgeCount = ammoBoxDetails._props.StackSlots[0]._max_count; const cartridgeTpl = ammoBoxDetails._props.StackSlots[0]._props.filters[0].Filter[0]; const cartridgeDetails = this.getItem(cartridgeTpl); const cartridgeMaxStackSize = cartridgeDetails[1]._props.StackMaxSize; // Exit if ammo already exists in box - if (ammoBox.some((item) => item._tpl === cartridgeTpl)) - { + if (ammoBox.some((item) => item._tpl === cartridgeTpl)) { return; } @@ -1305,8 +1147,7 @@ export class ItemHelper // Find location based on Max ammo box size let location = Math.ceil(ammoBoxMaxCartridgeCount / maxPerStack) - 1; - while (currentStoredCartridgeCount < ammoBoxMaxCartridgeCount) - { + while (currentStoredCartridgeCount < ammoBoxMaxCartridgeCount) { const remainingSpace = ammoBoxMaxCartridgeCount - currentStoredCartridgeCount; const cartridgeCountToAdd = remainingSpace < maxPerStack ? remainingSpace : maxPerStack; @@ -1320,8 +1161,7 @@ export class ItemHelper ); // In live no ammo box has the first cartridge item with a location - if (location === 0) - { + if (location === 0) { delete cartridgeItemToAdd.location; } @@ -1337,8 +1177,7 @@ export class ItemHelper * @param ammoBox Box to add cartridges to * @param ammoBoxDetails Item template from items db */ - public addSingleStackCartridgesToAmmoBox(ammoBox: Item[], ammoBoxDetails: ITemplateItem): void - { + public addSingleStackCartridgesToAmmoBox(ammoBox: Item[], ammoBoxDetails: ITemplateItem): void { const ammoBoxMaxCartridgeCount = ammoBoxDetails._props.StackSlots[0]._max_count; const cartridgeTpl = ammoBoxDetails._props.StackSlots[0]._props.filters[0].Filter[0]; ammoBox.push( @@ -1359,18 +1198,15 @@ export class ItemHelper * @param items Inventory with child parent items to check * @returns True when item is in container */ - public itemIsInsideContainer(item: Item, desiredContainerSlotId: string, items: Item[]): boolean - { + public itemIsInsideContainer(item: Item, desiredContainerSlotId: string, items: Item[]): boolean { // Get items parent const parent = items.find((x) => x._id === item.parentId); - if (!parent) - { + if (!parent) { // No parent, end of line, not inside container return false; } - if (parent.slotId === desiredContainerSlotId) - { + if (parent.slotId === desiredContainerSlotId) { return true; } @@ -1395,13 +1231,11 @@ export class ItemHelper minSizePercent = 0.25, defaultCartridgeTpl?: string, weapon?: ITemplateItem, - ): void - { + ): void { let chosenCaliber = caliber || this.getRandomValidCaliber(magTemplate); // Edge case for the Klin pp-9, it has a typo in its ammo caliber - if (chosenCaliber === "Caliber9x18PMM") - { + if (chosenCaliber === "Caliber9x18PMM") { chosenCaliber = "Caliber9x18PM"; } @@ -1412,9 +1246,10 @@ export class ItemHelper defaultCartridgeTpl, weapon?._props?.Chambers[0]?._props?.filters[0]?.Filter, ); - if (!cartridgeTpl) - { - this.logger.debug(`Unable to fill item: ${magazine[0]._id} ${magTemplate._name} with cartrides as none were found.`); + if (!cartridgeTpl) { + this.logger.debug( + `Unable to fill item: ${magazine[0]._id} ${magTemplate._name} with cartrides as none were found.`, + ); return; } @@ -1434,18 +1269,15 @@ export class ItemHelper magTemplate: ITemplateItem, cartridgeTpl: string, minSizePercent = 0.25, - ): void - { + ): void { // Get cartridge properties and max allowed stack size const cartridgeDetails = this.getItem(cartridgeTpl); - if (!cartridgeDetails[0]) - { + if (!cartridgeDetails[0]) { this.logger.error(this.localisationService.getText("item-invalid_tpl_item", cartridgeTpl)); } const cartridgeMaxStackSize = cartridgeDetails[1]._props?.StackMaxSize; - if (!cartridgeMaxStackSize) - { + if (!cartridgeMaxStackSize) { this.logger.error(`Item with tpl: ${cartridgeTpl} lacks a _props or StackMaxSize property`); } @@ -1454,8 +1286,7 @@ export class ItemHelper ? magTemplate._props.Slots.length // Edge case for rotating grenade launcher magazine : magTemplate._props.Cartridges[0]?._max_count; - if (!magazineCartridgeMaxCount) - { + if (!magazineCartridgeMaxCount) { this.logger.warning( `Magazine: ${magTemplate._id} ${magTemplate._name} lacks a Cartridges array, unable to fill magazine with ammo`, ); @@ -1468,24 +1299,21 @@ export class ItemHelper magazineCartridgeMaxCount, ); - if (magazineWithChildCartridges.length > 1) - { + if (magazineWithChildCartridges.length > 1) { this.logger.warning(`Magazine ${magTemplate._name} already has cartridges defined, this may cause issues`); } // Loop over cartridge count and add stacks to magazine let currentStoredCartridgeCount = 0; let location = 0; - while (currentStoredCartridgeCount < desiredStackCount) - { + while (currentStoredCartridgeCount < desiredStackCount) { // Get stack size of cartridges - let cartridgeCountToAdd - = desiredStackCount <= cartridgeMaxStackSize ? desiredStackCount : cartridgeMaxStackSize; + let cartridgeCountToAdd = + desiredStackCount <= cartridgeMaxStackSize ? desiredStackCount : cartridgeMaxStackSize; // Ensure we don't go over the max stackcount size const remainingSpace = desiredStackCount - currentStoredCartridgeCount; - if (cartridgeCountToAdd > remainingSpace) - { + if (cartridgeCountToAdd > remainingSpace) { cartridgeCountToAdd = remainingSpace; } @@ -1505,8 +1333,7 @@ export class ItemHelper } // Only one cartridge stack added, remove location property as its only used for 2 or more stacks - if (location === 1) - { + if (location === 1) { delete magazineWithChildCartridges[1].location; } } @@ -1516,8 +1343,7 @@ export class ItemHelper * @param magTemplate Magazine template from Db * @returns Tpl of cartridge */ - protected getRandomValidCaliber(magTemplate: ITemplateItem): string - { + protected getRandomValidCaliber(magTemplate: ITemplateItem): string { const ammoTpls = magTemplate._props.Cartridges[0]._props.filters[0].Filter; const calibers = [ ...new Set( @@ -1542,11 +1368,9 @@ export class ItemHelper staticAmmoDist: Record, fallbackCartridgeTpl: string, cartridgeWhitelist?: string[], - ): string | undefined - { + ): string | undefined { const ammos = staticAmmoDist[caliber]; - if (!ammos && fallbackCartridgeTpl) - { + if (!ammos && fallbackCartridgeTpl) { this.logger.error( `Unable to pick a cartridge for caliber: ${caliber} as staticAmmoDist has no data. using fallback value of ${fallbackCartridgeTpl}`, ); @@ -1554,8 +1378,7 @@ export class ItemHelper return fallbackCartridgeTpl; } - if (!Array.isArray(ammos) && fallbackCartridgeTpl) - { + if (!Array.isArray(ammos) && fallbackCartridgeTpl) { this.logger.error( `Unable to pick a cartridge for caliber: ${caliber}, the chosen staticAmmoDist data is not an array. Using fallback value of ${fallbackCartridgeTpl}`, ); @@ -1563,8 +1386,7 @@ export class ItemHelper return fallbackCartridgeTpl; } - if (!ammos && !fallbackCartridgeTpl) - { + if (!ammos && !fallbackCartridgeTpl) { this.logger.debug( `Unable to pick a cartridge for caliber: ${caliber} as staticAmmoDist has no data. No fallback value provided`, ); @@ -1572,12 +1394,10 @@ export class ItemHelper return; } const ammoArray = new ProbabilityObjectArray(this.mathUtil, this.cloner); - for (const icd of ammos) - { + for (const icd of ammos) { // Whitelist exists and tpl not inside it, skip // Fixes 9x18mm kedr issues - if (cartridgeWhitelist && !cartridgeWhitelist.includes(icd.tpl)) - { + if (cartridgeWhitelist && !cartridgeWhitelist.includes(icd.tpl)) { continue; } @@ -1601,8 +1421,7 @@ export class ItemHelper stackCount: number, location: number, foundInRaid = false, - ): Item - { + ): Item { return { _id: this.objectId.generate(), _tpl: ammoTpl, @@ -1618,10 +1437,8 @@ export class ItemHelper * @param item Item to get stack size of * @returns size of stack */ - public getItemStackSize(item: Item): number - { - if (item.upd?.StackObjectsCount) - { + public getItemStackSize(item: Item): number { + if (item.upd?.StackObjectsCount) { return item.upd.StackObjectsCount; } @@ -1633,12 +1450,10 @@ export class ItemHelper * @param itemTpl Tpl of item to get name of * @returns Full name, short name if not found */ - public getItemName(itemTpl: string): string - { + public getItemName(itemTpl: string): string { const localeDb = this.localeService.getLocaleDb(); const result = localeDb[`${itemTpl} Name`]; - if (result?.length > 0) - { + if (result?.length > 0) { return result; } @@ -1650,8 +1465,7 @@ export class ItemHelper * @param desiredBaseType Item base type wanted * @returns Array of tpls */ - public getItemTplsOfBaseType(desiredBaseType: string): string[] - { + public getItemTplsOfBaseType(desiredBaseType: string): string[] { return Object.values(this.databaseService.getItems()) .filter((item) => item._parent === desiredBaseType) .map((item) => item._id); @@ -1670,27 +1484,21 @@ export class ItemHelper itemToAddTemplate: ITemplateItem, modSpawnChanceDict?: Record, requiredOnly = false, - ): Item[] - { + ): Item[] { const result = itemToAdd; const incompatibleModTpls: Set = new Set(); - for (const slot of itemToAddTemplate._props.Slots) - { + for (const slot of itemToAddTemplate._props.Slots) { // If only required mods is requested, skip non-essential - if (requiredOnly && !slot._required) - { + if (requiredOnly && !slot._required) { continue; } // Roll chance for non-required slot mods - if (modSpawnChanceDict && !slot._required) - { + if (modSpawnChanceDict && !slot._required) { // only roll chance to not include mod if dict exists and has value for this mod type (e.g. front_plate) const modSpawnChance = modSpawnChanceDict[slot._name.toLowerCase()]; - if (modSpawnChance) - { - if (!this.randomUtil.getChance100(modSpawnChance)) - { + if (modSpawnChance) { + if (!this.randomUtil.getChance100(modSpawnChance)) { continue; } } @@ -1698,8 +1506,7 @@ export class ItemHelper const itemPool = slot._props.filters[0].Filter ?? []; const chosenTpl = this.getCompatibleTplFromArray(itemPool, incompatibleModTpls); - if (!chosenTpl) - { + if (!chosenTpl) { this.logger.debug( `Unable to add mod to item: ${itemToAddTemplate._id} ${itemToAddTemplate._name} slot: ${slot._name} as no compatible tpl could be found in pool of ${itemPool.length}, skipping`, ); @@ -1730,25 +1537,20 @@ export class ItemHelper * @param incompatibleModTpls Incompatible tpls to not allow * @returns Chosen tpl or undefined */ - public getCompatibleTplFromArray(possibleTpls: string[], incompatibleModTpls: Set): string | undefined - { - if (possibleTpls.length === 0) - { + public getCompatibleTplFromArray(possibleTpls: string[], incompatibleModTpls: Set): string | undefined { + if (possibleTpls.length === 0) { return undefined; } let chosenTpl: string | undefined = undefined; let count = 0; - while (!chosenTpl) - { + while (!chosenTpl) { // Loop over choosing a random tpl until one is found or count varaible reaches the same size as the possible tpls array const tpl = this.randomUtil.getArrayValue(possibleTpls); - if (incompatibleModTpls.has(tpl)) - { + if (incompatibleModTpls.has(tpl)) { // Incompatible tpl was chosen, try again count++; - if (count >= possibleTpls.length) - { + if (count >= possibleTpls.length) { return undefined; } continue; @@ -1765,8 +1567,7 @@ export class ItemHelper * @param slotName Name of slot (_name) of Items Slot array * @returns True if its a slot that holds a removable palte */ - public isRemovablePlateSlot(slotName: string): boolean - { + public isRemovablePlateSlot(slotName: string): boolean { return this.getRemovablePlateSlotIds().includes(slotName.toLowerCase()); } @@ -1774,8 +1575,7 @@ export class ItemHelper * Get a list of slot names that hold removable plates * @returns Array of slot ids (e.g. front_plate) */ - public getRemovablePlateSlotIds(): string[] - { + public getRemovablePlateSlotIds(): string[] { return ["front_plate", "back_plate", "left_side_plate", "right_side_plate"]; } @@ -1785,37 +1585,31 @@ export class ItemHelper * @param itemWithChildren Primary item + children of primary item * @returns Item array with updated IDs */ - public reparentItemAndChildren(rootItem: Item, itemWithChildren: Item[]): Item[] - { + public reparentItemAndChildren(rootItem: Item, itemWithChildren: Item[]): Item[] { const oldRootId = itemWithChildren[0]._id; const idMappings = {}; idMappings[oldRootId] = rootItem._id; - for (const mod of itemWithChildren) - { - if (idMappings[mod._id] === undefined) - { + for (const mod of itemWithChildren) { + if (idMappings[mod._id] === undefined) { idMappings[mod._id] = this.hashUtil.generate(); } // Has parentId + no remapping exists for its parent - if (mod.parentId !== undefined && idMappings[mod.parentId] === undefined) - { + if (mod.parentId !== undefined && idMappings[mod.parentId] === undefined) { // Make remapping for items parentId idMappings[mod.parentId] = this.hashUtil.generate(); } mod._id = idMappings[mod._id]; - if (mod.parentId !== undefined) - { + if (mod.parentId !== undefined) { mod.parentId = idMappings[mod.parentId]; } } // Force item's details into first location of presetItems - if (itemWithChildren[0]._tpl !== rootItem._tpl) - { + if (itemWithChildren[0]._tpl !== rootItem._tpl) { this.logger.warning(`Reassigning root item from ${itemWithChildren[0]._tpl} to ${rootItem._tpl}`); } @@ -1830,23 +1624,19 @@ export class ItemHelper * @param newId Optional: new id to use * @returns New root id */ - public remapRootItemId(itemWithChildren: Item[], newId = this.hashUtil.generate()): string - { + public remapRootItemId(itemWithChildren: Item[], newId = this.hashUtil.generate()): string { const rootItemExistingId = itemWithChildren[0]._id; - for (const item of itemWithChildren) - { + for (const item of itemWithChildren) { // Root, update id - if (item._id === rootItemExistingId) - { + if (item._id === rootItemExistingId) { item._id = newId; continue; } // Child with parent of root, update - if (item.parentId === rootItemExistingId) - { + if (item.parentId === rootItemExistingId) { item.parentId = newId; } } @@ -1863,17 +1653,14 @@ export class ItemHelper * @param items Array of Items that should be adjusted. * @returns Array of Items that have been adopted. */ - public adoptOrphanedItems(rootId: string, items: Item[]): Item[] - { - for (const item of items) - { + public adoptOrphanedItems(rootId: string, items: Item[]): Item[] { + for (const item of items) { // Check if the item's parent exists. const parentExists = items.some((parentItem) => parentItem._id === item.parentId); // If the parent does not exist and the item is not already a 'hideout' item, adopt the orphaned item by // setting the parent ID to the PMCs inventory equipment ID, the slot ID to 'hideout', and remove the location. - if (!parentExists && item.parentId !== rootId && item.slotId !== "hideout") - { + if (!parentExists && item.parentId !== rootId && item.slotId !== "hideout") { item.parentId = rootId; item.slotId = "hideout"; delete item.location; @@ -1889,11 +1676,9 @@ export class ItemHelper * @param items An array of Items that should be added to a Map. * @returns A Map where the keys are the item IDs and the values are the corresponding Item objects. */ - public generateItemsMap(items: Item[]): Map - { + public generateItemsMap(items: Item[]): Map { const itemsMap = new Map(); - for (const item of items) - { + for (const item of items) { itemsMap.set(item._id, item); } return itemsMap; @@ -1905,14 +1690,11 @@ export class ItemHelper * @param warningMessageWhenMissing text to write to log when upd object was not found * @returns True when upd object was added */ - public addUpdObjectToItem(item: Item, warningMessageWhenMissing?: string): boolean - { - if (!item.upd) - { + public addUpdObjectToItem(item: Item, warningMessageWhenMissing?: string): boolean { + if (!item.upd) { item.upd = {}; - if (warningMessageWhenMissing) - { + if (warningMessageWhenMissing) { this.logger.debug(warningMessageWhenMissing); } @@ -1922,17 +1704,14 @@ export class ItemHelper return false; } - public getMoneyTpls(): string[] - { + public getMoneyTpls(): string[] { return Object.values(Money); } } -namespace ItemHelper -{ - export interface ItemSize - { - width: number - height: number +namespace ItemHelper { + export interface ItemSize { + width: number; + height: number; } } diff --git a/project/src/helpers/NotificationSendHelper.ts b/project/src/helpers/NotificationSendHelper.ts index 1cfa396e..8d35be44 100644 --- a/project/src/helpers/NotificationSendHelper.ts +++ b/project/src/helpers/NotificationSendHelper.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { Dialogue, IUserDialogInfo, Message } from "@spt/models/eft/profile/ISptProfile"; import { IWsChatMessageReceived } from "@spt/models/eft/ws/IWsChatMessageReceived"; import { IWsNotificationEvent } from "@spt/models/eft/ws/IWsNotificationEvent"; @@ -9,31 +8,26 @@ import { SaveServer } from "@spt/servers/SaveServer"; import { SptWebSocketConnectionHandler } from "@spt/servers/ws/SptWebSocketConnectionHandler"; import { NotificationService } from "@spt/services/NotificationService"; import { HashUtil } from "@spt/utils/HashUtil"; +import { inject, injectable } from "tsyringe"; @injectable() -export class NotificationSendHelper -{ +export class NotificationSendHelper { constructor( @inject("SptWebSocketConnectionHandler") protected sptWebSocketConnection: SptWebSocketConnectionHandler, @inject("HashUtil") protected hashUtil: HashUtil, @inject("SaveServer") protected saveServer: SaveServer, @inject("NotificationService") protected notificationService: NotificationService, - ) - {} + ) {} /** * Send notification message to the appropriate channel * @param sessionID * @param notificationMessage */ - public sendMessage(sessionID: string, notificationMessage: IWsNotificationEvent): void - { - if (this.sptWebSocketConnection.isConnectionWebSocket(sessionID)) - { + public sendMessage(sessionID: string, notificationMessage: IWsNotificationEvent): void { + if (this.sptWebSocketConnection.isConnectionWebSocket(sessionID)) { this.sptWebSocketConnection.sendMessage(sessionID, notificationMessage); - } - else - { + } else { this.notificationService.add(sessionID, notificationMessage); } } @@ -50,8 +44,7 @@ export class NotificationSendHelper senderDetails: IUserDialogInfo, messageText: string, messageType: MessageType, - ): void - { + ): void { const dialog = this.getDialog(sessionId, messageType, senderDetails); dialog.new += 1; @@ -83,11 +76,10 @@ export class NotificationSendHelper * @param senderDetails Who is sending the message * @returns Dialogue */ - protected getDialog(sessionId: string, messageType: MessageType, senderDetails: IUserDialogInfo): Dialogue - { + protected getDialog(sessionId: string, messageType: MessageType, senderDetails: IUserDialogInfo): Dialogue { // Use trader id if sender is trader, otherwise use nickname - const key - = senderDetails.Info.MemberCategory === MemberCategory.TRADER + const key = + senderDetails.Info.MemberCategory === MemberCategory.TRADER ? senderDetails._id : senderDetails.Info.Nickname; const dialogueData = this.saveServer.getProfile(sessionId).dialogues; @@ -95,8 +87,7 @@ export class NotificationSendHelper let dialogue: Dialogue = dialogueData[key]; // Existing dialog not found, make new one - if (isNewDialogue) - { + if (isNewDialogue) { dialogue = { _id: key, type: messageType, diff --git a/project/src/helpers/NotifierHelper.ts b/project/src/helpers/NotifierHelper.ts index ae8aa9e6..9ddde42f 100644 --- a/project/src/helpers/NotifierHelper.ts +++ b/project/src/helpers/NotifierHelper.ts @@ -1,24 +1,21 @@ -import { inject, injectable } from "tsyringe"; import { HttpServerHelper } from "@spt/helpers/HttpServerHelper"; import { Message, MessageContentRagfair } from "@spt/models/eft/profile/ISptProfile"; import { IWsChatMessageReceived } from "@spt/models/eft/ws/IWsChatMessageReceived"; import { IWsNotificationEvent } from "@spt/models/eft/ws/IWsNotificationEvent"; import { IWsRagfairOfferSold } from "@spt/models/eft/ws/IWsRagfairOfferSold"; import { NotificationEventType } from "@spt/models/enums/NotificationEventType"; +import { inject, injectable } from "tsyringe"; @injectable() -export class NotifierHelper -{ +export class NotifierHelper { /** * The default notification sent when waiting times out. */ protected defaultNotification: IWsNotificationEvent = { type: NotificationEventType.PING, eventId: "ping" }; - constructor(@inject("HttpServerHelper") protected httpServerHelper: HttpServerHelper) - {} + constructor(@inject("HttpServerHelper") protected httpServerHelper: HttpServerHelper) {} - public getDefaultNotification(): IWsNotificationEvent - { + public getDefaultNotification(): IWsNotificationEvent { return this.defaultNotification; } @@ -31,8 +28,7 @@ export class NotifierHelper public createRagfairOfferSoldNotification( dialogueMessage: Message, ragfairData: MessageContentRagfair, - ): IWsRagfairOfferSold - { + ): IWsRagfairOfferSold { return { type: NotificationEventType.RAGFAIR_OFFER_SOLD, eventId: dialogueMessage._id, @@ -45,8 +41,7 @@ export class NotifierHelper * @param dialogueMessage * @returns */ - public createNewMessageNotification(dialogueMessage: Message): IWsChatMessageReceived - { + public createNewMessageNotification(dialogueMessage: Message): IWsChatMessageReceived { return { type: NotificationEventType.CHAT_MESSAGE_RECEIVED, eventId: dialogueMessage._id, @@ -55,8 +50,7 @@ export class NotifierHelper }; } - public getWebSocketServer(sessionID: string): string - { + public getWebSocketServer(sessionID: string): string { return `${this.httpServerHelper.getWebsocketUrl()}/notifierServer/getwebsocket/${sessionID}`; } } diff --git a/project/src/helpers/PaymentHelper.ts b/project/src/helpers/PaymentHelper.ts index ca845fd7..a0b3c0d9 100644 --- a/project/src/helpers/PaymentHelper.ts +++ b/project/src/helpers/PaymentHelper.ts @@ -1,16 +1,14 @@ -import { inject, injectable } from "tsyringe"; import { ConfigTypes } from "@spt/models/enums/ConfigTypes"; import { Money } from "@spt/models/enums/Money"; import { IInventoryConfig } from "@spt/models/spt/config/IInventoryConfig"; import { ConfigServer } from "@spt/servers/ConfigServer"; +import { inject, injectable } from "tsyringe"; @injectable() -export class PaymentHelper -{ +export class PaymentHelper { protected inventoryConfig: IInventoryConfig; - constructor(@inject("ConfigServer") protected configServer: ConfigServer) - { + constructor(@inject("ConfigServer") protected configServer: ConfigServer) { this.inventoryConfig = this.configServer.getConfig(ConfigTypes.INVENTORY); } @@ -19,8 +17,7 @@ export class PaymentHelper * @param {string} tpl * @returns void */ - public isMoneyTpl(tpl: string): boolean - { + public isMoneyTpl(tpl: string): boolean { return [Money.DOLLARS, Money.EUROS, Money.ROUBLES, Money.GP, ...this.inventoryConfig.customMoneyTpls].some( (element) => element === tpl, ); @@ -31,10 +28,8 @@ export class PaymentHelper * @param {string} currency * @returns string */ - public getCurrency(currency: string): string - { - switch (currency) - { + public getCurrency(currency: string): string { + switch (currency) { case "EUR": return Money.EUROS; case "USD": diff --git a/project/src/helpers/PresetHelper.ts b/project/src/helpers/PresetHelper.ts index 3a74f8a8..db485bcc 100644 --- a/project/src/helpers/PresetHelper.ts +++ b/project/src/helpers/PresetHelper.ts @@ -1,13 +1,12 @@ -import { inject, injectable } from "tsyringe"; import { ItemHelper } from "@spt/helpers/ItemHelper"; import { IPreset } from "@spt/models/eft/common/IGlobals"; import { BaseClasses } from "@spt/models/enums/BaseClasses"; import { DatabaseService } from "@spt/services/DatabaseService"; import { ICloner } from "@spt/utils/cloners/ICloner"; +import { inject, injectable } from "tsyringe"; @injectable() -export class PresetHelper -{ +export class PresetHelper { protected lookup: Record = {}; protected defaultEquipmentPresets: Record; protected defaultWeaponPresets: Record; @@ -16,11 +15,9 @@ export class PresetHelper @inject("DatabaseService") protected databaseService: DatabaseService, @inject("ItemHelper") protected itemHelper: ItemHelper, @inject("PrimaryCloner") protected cloner: ICloner, - ) - {} + ) {} - public hydratePresetStore(input: Record): void - { + public hydratePresetStore(input: Record): void { this.lookup = input; } @@ -28,8 +25,7 @@ export class PresetHelper * Get default weapon and equipment presets * @returns Dictionary */ - public getDefaultPresets(): Record - { + public getDefaultPresets(): Record { const weapons = this.getDefaultWeaponPresets(); const equipment = this.getDefaultEquipmentPresets(); @@ -40,18 +36,15 @@ export class PresetHelper * Get default weapon presets * @returns Dictionary */ - public getDefaultWeaponPresets(): Record - { - if (!this.defaultWeaponPresets) - { + public getDefaultWeaponPresets(): Record { + if (!this.defaultWeaponPresets) { this.defaultWeaponPresets = Object.values(this.databaseService.getGlobals().ItemPresets) .filter( (preset) => - preset._encyclopedia !== undefined - && this.itemHelper.isOfBaseclass(preset._encyclopedia, BaseClasses.WEAPON), + preset._encyclopedia !== undefined && + this.itemHelper.isOfBaseclass(preset._encyclopedia, BaseClasses.WEAPON), ) - .reduce((acc, cur) => - { + .reduce((acc, cur) => { acc[cur._id] = cur; return acc; }, {}); @@ -64,18 +57,15 @@ export class PresetHelper * Get default equipment presets * @returns Dictionary */ - public getDefaultEquipmentPresets(): Record - { - if (!this.defaultEquipmentPresets) - { + public getDefaultEquipmentPresets(): Record { + if (!this.defaultEquipmentPresets) { this.defaultEquipmentPresets = Object.values(this.databaseService.getGlobals().ItemPresets) .filter( (preset) => - preset._encyclopedia !== undefined - && this.itemHelper.armorItemCanHoldMods(preset._encyclopedia), + preset._encyclopedia !== undefined && + this.itemHelper.armorItemCanHoldMods(preset._encyclopedia), ) - .reduce((acc, cur) => - { + .reduce((acc, cur) => { acc[cur._id] = cur; return acc; }, {}); @@ -84,8 +74,7 @@ export class PresetHelper return this.defaultEquipmentPresets; } - public isPreset(id: string): boolean - { + public isPreset(id: string): boolean { return id in this.databaseService.getGlobals().ItemPresets; } @@ -95,38 +84,31 @@ export class PresetHelper * @param baseClass The BaseClasses enum to check against * @returns True if the preset is of the given base class, false otherwise */ - public isPresetBaseClass(id: string, baseClass: BaseClasses): boolean - { + public isPresetBaseClass(id: string, baseClass: BaseClasses): boolean { return this.isPreset(id) && this.itemHelper.isOfBaseclass(this.getPreset(id)._encyclopedia, baseClass); } - public hasPreset(templateId: string): boolean - { + public hasPreset(templateId: string): boolean { return templateId in this.lookup; } - public getPreset(id: string): IPreset - { + public getPreset(id: string): IPreset { return this.cloner.clone(this.databaseService.getGlobals().ItemPresets[id]); } - public getAllPresets(): IPreset[] - { + public getAllPresets(): IPreset[] { return this.cloner.clone(Object.values(this.databaseService.getGlobals().ItemPresets)); } - public getPresets(templateId: string): IPreset[] - { - if (!this.hasPreset(templateId)) - { + public getPresets(templateId: string): IPreset[] { + if (!this.hasPreset(templateId)) { return []; } const presets = []; const ids = this.lookup[templateId]; - for (const id of ids) - { + for (const id of ids) { presets.push(this.getPreset(id)); } @@ -138,19 +120,15 @@ export class PresetHelper * @param templateId Item id to get preset for * @returns Null if no default preset, otherwise IPreset */ - public getDefaultPreset(templateId: string): IPreset | undefined - { - if (!this.hasPreset(templateId)) - { + public getDefaultPreset(templateId: string): IPreset | undefined { + if (!this.hasPreset(templateId)) { return undefined; } const allPresets = this.getPresets(templateId); - for (const preset of allPresets) - { - if ("_encyclopedia" in preset) - { + for (const preset of allPresets) { + if ("_encyclopedia" in preset) { return preset; } } @@ -158,16 +136,12 @@ export class PresetHelper return allPresets[0]; } - public getBaseItemTpl(presetId: string): string - { - if (this.isPreset(presetId)) - { + public getBaseItemTpl(presetId: string): string { + if (this.isPreset(presetId)) { const preset = this.getPreset(presetId); - for (const item of preset._items) - { - if (preset._parent === item._id) - { + for (const item of preset._items) { + if (preset._parent === item._id) { return item._tpl; } } @@ -181,8 +155,7 @@ export class PresetHelper * @param tpl The item template to get the price of * @returns The price of the given item preset, or base item if no preset exists */ - public getDefaultPresetOrItemPrice(tpl: string): number - { + public getDefaultPresetOrItemPrice(tpl: string): number { // Get default preset if it exists const defaultPreset = this.getDefaultPreset(tpl); diff --git a/project/src/helpers/ProbabilityHelper.ts b/project/src/helpers/ProbabilityHelper.ts index 1e868332..783c88bc 100644 --- a/project/src/helpers/ProbabilityHelper.ts +++ b/project/src/helpers/ProbabilityHelper.ts @@ -1,15 +1,13 @@ -import { inject, injectable } from "tsyringe"; import { ILogger } from "@spt/models/spt/utils/ILogger"; import { RandomUtil } from "@spt/utils/RandomUtil"; +import { inject, injectable } from "tsyringe"; @injectable() -export class ProbabilityHelper -{ +export class ProbabilityHelper { constructor( @inject("PrimaryLogger") protected logger: ILogger, @inject("RandomUtil") protected randomUtil: RandomUtil, - ) - {} + ) {} /** * Chance to roll a number out of 100 @@ -17,8 +15,7 @@ export class ProbabilityHelper * @param scale scale of chance to allow support of numbers > 1-100 * @returns true if success */ - public rollChance(chance: number, scale = 1): boolean - { + public rollChance(chance: number, scale = 1): boolean { return this.randomUtil.getInt(1, 100 * scale) / (1 * scale) <= chance; } } diff --git a/project/src/helpers/ProfileHelper.ts b/project/src/helpers/ProfileHelper.ts index 47750f5f..1c5c75bd 100644 --- a/project/src/helpers/ProfileHelper.ts +++ b/project/src/helpers/ProfileHelper.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { ItemHelper } from "@spt/helpers/ItemHelper"; import { IPmcData } from "@spt/models/eft/common/IPmcData"; import { BanType, Common, CounterKeyValue, Stats } from "@spt/models/eft/common/tables/IBotBase"; @@ -16,14 +15,14 @@ import { SaveServer } from "@spt/servers/SaveServer"; import { DatabaseService } from "@spt/services/DatabaseService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { ProfileSnapshotService } from "@spt/services/ProfileSnapshotService"; -import { ICloner } from "@spt/utils/cloners/ICloner"; import { HashUtil } from "@spt/utils/HashUtil"; import { TimeUtil } from "@spt/utils/TimeUtil"; import { Watermark } from "@spt/utils/Watermark"; +import { ICloner } from "@spt/utils/cloners/ICloner"; +import { inject, injectable } from "tsyringe"; @injectable() -export class ProfileHelper -{ +export class ProfileHelper { protected inventoryConfig: IInventoryConfig; constructor( @@ -38,8 +37,7 @@ export class ProfileHelper @inject("LocalisationService") protected localisationService: LocalisationService, @inject("ConfigServer") protected configServer: ConfigServer, @inject("PrimaryCloner") protected cloner: ICloner, - ) - { + ) { this.inventoryConfig = this.configServer.getConfig(ConfigTypes.INVENTORY); } @@ -48,17 +46,14 @@ export class ProfileHelper * @param sessionID Session id * @param questConditionId Quest with condition to remove */ - public removeQuestConditionFromProfile(pmcData: IPmcData, questConditionId: Record): void - { - for (const questId in questConditionId) - { + public removeQuestConditionFromProfile(pmcData: IPmcData, questConditionId: Record): void { + for (const questId in questConditionId) { const conditionId = questConditionId[questId]; const profileQuest = pmcData.Quests.find((x) => x.qid === questId); // Find index of condition in array const index = profileQuest.completedConditions.indexOf(conditionId); - if (index > -1) - { + if (index > -1) { // Remove condition profileQuest.completedConditions.splice(index, 1); } @@ -69,8 +64,7 @@ export class ProfileHelper * Get all profiles from server * @returns Dictionary of profiles */ - public getProfiles(): Record - { + public getProfiles(): Record { return this.saveServer.getProfiles(); } @@ -79,20 +73,17 @@ export class ProfileHelper * @param sessionId * @returns Array of IPmcData objects */ - public getCompleteProfile(sessionId: string): IPmcData[] - { + public getCompleteProfile(sessionId: string): IPmcData[] { const output: IPmcData[] = []; - if (this.isWiped(sessionId)) - { + if (this.isWiped(sessionId)) { return output; } const fullProfile = this.getFullProfile(sessionId); // Edge-case, true post raid - if (this.profileSnapshotService.hasProfileSnapshot(sessionId)) - { + if (this.profileSnapshotService.hasProfileSnapshot(sessionId)) { return this.postRaidXpWorkaroundFix( sessionId, fullProfile.characters.pmc, @@ -125,8 +116,7 @@ export class ProfileHelper pmcProfile: IPmcData, scavProfile: IPmcData, output: IPmcData[], - ): IPmcData[] - { + ): IPmcData[] { const clonedPmc = this.cloner.clone(pmcProfile); const clonedScav = this.cloner.clone(scavProfile); @@ -151,28 +141,27 @@ export class ProfileHelper * @param sessionID Session id * @returns True if already in use */ - public isNicknameTaken(nicknameRequest: IValidateNicknameRequestData, sessionID: string): boolean - { + public isNicknameTaken(nicknameRequest: IValidateNicknameRequestData, sessionID: string): boolean { const allProfiles = Object.values(this.saveServer.getProfiles()); // Find a profile that doesn't have same session id but has same name - return allProfiles.some((profile) => - this.profileHasInfoProperty(profile) - && !this.stringsMatch(profile.info.id, sessionID) // SessionIds dont match - && this.stringsMatch( // Nicknames do - profile.characters.pmc.Info.LowerNickname.toLowerCase(), - nicknameRequest.nickname.toLowerCase(), - ), + return allProfiles.some( + (profile) => + this.profileHasInfoProperty(profile) && + !this.stringsMatch(profile.info.id, sessionID) && // SessionIds dont match + this.stringsMatch( + // Nicknames do + profile.characters.pmc.Info.LowerNickname.toLowerCase(), + nicknameRequest.nickname.toLowerCase(), + ), ); } - protected profileHasInfoProperty(profile: ISptProfile): boolean - { + protected profileHasInfoProperty(profile: ISptProfile): boolean { return !!profile?.characters?.pmc?.Info; } - protected stringsMatch(stringA: string, stringB: string): boolean - { + protected stringsMatch(stringA: string, stringB: string): boolean { return stringA === stringB; } @@ -181,8 +170,7 @@ export class ProfileHelper * @param sessionID Session id * @param experienceToAdd Experience to add to PMC character */ - public addExperienceToPmc(sessionID: string, experienceToAdd: number): void - { + public addExperienceToPmc(sessionID: string, experienceToAdd: number): void { const pmcData = this.getPmcProfile(sessionID); pmcData.Info.Experience += experienceToAdd; } @@ -192,10 +180,9 @@ export class ProfileHelper * @param pmcId Profile id to find * @returns IPmcData */ - public getProfileByPmcId(pmcId: string): IPmcData | undefined - { - return Object.values(this.saveServer.getProfiles()) - .find((profile) => profile.characters.pmc?._id === pmcId)?.characters.pmc; + public getProfileByPmcId(pmcId: string): IPmcData | undefined { + return Object.values(this.saveServer.getProfiles()).find((profile) => profile.characters.pmc?._id === pmcId) + ?.characters.pmc; } /** @@ -203,20 +190,17 @@ export class ProfileHelper * @param level Level to get xp for * @returns Number of xp points for level */ - public getExperience(level: number): number - { + public getExperience(level: number): number { let playerLevel = level; const expTable = this.databaseService.getGlobals().config.exp.level.exp_table; let exp = 0; - if (playerLevel >= expTable.length) - { + if (playerLevel >= expTable.length) { // make sure to not go out of bounds playerLevel = expTable.length - 1; } - for (let i = 0; i < playerLevel; i++) - { + for (let i = 0; i < playerLevel; i++) { exp += expTable[i].exp; } @@ -227,13 +211,11 @@ export class ProfileHelper * Get the max level a player can be * @returns Max level */ - public getMaxLevel(): number - { + public getMaxLevel(): number { return this.databaseService.getGlobals().config.exp.level.exp_table.length - 1; } - public getDefaultSptDataObject(): any - { + public getDefaultSptDataObject(): any { return { version: this.watermark.getVersionTag(true) }; } @@ -242,11 +224,8 @@ export class ProfileHelper * @param sessionID Profile id to get * @returns ISptProfile object */ - public getFullProfile(sessionID: string): ISptProfile | undefined - { - return this.saveServer.profileExists(sessionID) - ? this.saveServer.getProfile(sessionID) - : undefined; + public getFullProfile(sessionID: string): ISptProfile | undefined { + return this.saveServer.profileExists(sessionID) ? this.saveServer.getProfile(sessionID) : undefined; } /** @@ -254,11 +233,9 @@ export class ProfileHelper * @param sessionID Profile id to return * @returns IPmcData object */ - public getPmcProfile(sessionID: string): IPmcData | undefined - { + public getPmcProfile(sessionID: string): IPmcData | undefined { const fullProfile = this.getFullProfile(sessionID); - if (!fullProfile?.characters?.pmc) - { + if (!fullProfile?.characters?.pmc) { return undefined; } @@ -270,8 +247,7 @@ export class ProfileHelper * @param userId Id to validate * @returns True is a player */ - public isPlayer(userId: string): boolean - { + public isPlayer(userId: string): boolean { return this.saveServer.profileExists(userId); } @@ -280,8 +256,7 @@ export class ProfileHelper * @param sessionID Profiles id * @returns IPmcData object */ - public getScavProfile(sessionID: string): IPmcData - { + public getScavProfile(sessionID: string): IPmcData { return this.saveServer.getProfile(sessionID).characters.scav; } @@ -289,8 +264,7 @@ export class ProfileHelper * Get baseline counter values for a fresh profile * @returns Default profile Stats object */ - public getDefaultCounters(): Stats - { + public getDefaultCounters(): Stats { return { Eft: { CarriedQuestItems: [], @@ -316,8 +290,7 @@ export class ProfileHelper * @param sessionID Profile id * @returns True if profile is to be wiped of data/progress */ - protected isWiped(sessionID: string): boolean - { + protected isWiped(sessionID: string): boolean { return this.saveServer.getProfile(sessionID).info.wipe; } @@ -326,12 +299,10 @@ export class ProfileHelper * @param profile Profile to remove secure container from * @returns profile without secure container */ - public removeSecureContainer(profile: IPmcData): IPmcData - { + public removeSecureContainer(profile: IPmcData): IPmcData { const items = profile.Inventory.items; const secureContainer = items.find((x) => x.slotId === "SecuredContainer"); - if (secureContainer) - { + if (secureContainer) { // Find and remove container + children const childItemsInSecureContainer = this.itemHelper.findAndReturnChildrenByItems( items, @@ -352,16 +323,14 @@ export class ProfileHelper * @param giftId Gift player received * @param maxCount Limit of how many of this gift a player can have */ - public flagGiftReceivedInProfile(playerId: string, giftId: string, maxCount: number): void - { + public flagGiftReceivedInProfile(playerId: string, giftId: string, maxCount: number): void { const profileToUpdate = this.getFullProfile(playerId); // nullguard receivedGifts profileToUpdate.spt.receivedGifts ||= []; const giftData = profileToUpdate.spt.receivedGifts.find((gift) => gift.giftId === giftId); - if (giftData) - { + if (giftData) { // Increment counter giftData.current++; @@ -369,12 +338,11 @@ export class ProfileHelper } // Player has never received gift, make a new object - profileToUpdate.spt.receivedGifts.push( - { - giftId: giftId, - timestampLastAccepted: this.timeUtil.getTimestamp(), - current: 1, - }); + profileToUpdate.spt.receivedGifts.push({ + giftId: giftId, + timestampLastAccepted: this.timeUtil.getTimestamp(), + current: 1, + }); } /** @@ -384,23 +352,19 @@ export class ProfileHelper * @param maxGiftCount Max times gift can be given to player * @returns True if player has recieved gift previously */ - public playerHasRecievedMaxNumberOfGift(playerId: string, giftId: string, maxGiftCount: number): boolean - { + public playerHasRecievedMaxNumberOfGift(playerId: string, giftId: string, maxGiftCount: number): boolean { const profile = this.getFullProfile(playerId); - if (!profile) - { + if (!profile) { this.logger.debug(`Unable to gift ${giftId}, profile: ${playerId} does not exist`); return false; } - if (!profile.spt.receivedGifts) - { + if (!profile.spt.receivedGifts) { return false; } const giftDataFromProfile = profile.spt.receivedGifts.find((x) => x.giftId === giftId); - if (!giftDataFromProfile) - { + if (!giftDataFromProfile) { return false; } @@ -412,11 +376,9 @@ export class ProfileHelper * @param counters Counters to search for key * @param keyToIncrement Key */ - public incrementStatCounter(counters: CounterKeyValue[], keyToIncrement: string): void - { + public incrementStatCounter(counters: CounterKeyValue[], keyToIncrement: string): void { const stat = counters.find((x) => x.Key.includes(keyToIncrement)); - if (stat) - { + if (stat) { stat.Value++; } } @@ -427,17 +389,14 @@ export class ProfileHelper * @param pmcProfile Profile to find skill in * @returns True if player has skill at elite level */ - public hasEliteSkillLevel(skillType: SkillTypes, pmcProfile: IPmcData): boolean - { + public hasEliteSkillLevel(skillType: SkillTypes, pmcProfile: IPmcData): boolean { const profileSkills = pmcProfile?.Skills?.Common; - if (!profileSkills) - { + if (!profileSkills) { return false; } const profileSkill = profileSkills.find((x) => x.Id === skillType); - if (!profileSkill) - { + if (!profileSkill) { this.logger.warning(`Unable to check for elite skill ${skillType}, not found in profile`); return false; @@ -458,12 +417,10 @@ export class ProfileHelper skill: SkillTypes, pointsToAdd: number, useSkillProgressRateMultipler = false, - ): void - { + ): void { let pointsToAddToSkill = pointsToAdd; - if (!pointsToAddToSkill || pointsToAddToSkill < 0) - { + if (!pointsToAddToSkill || pointsToAddToSkill < 0) { this.logger.warning( this.localisationService.getText("player-attempt_to_increment_skill_with_negative_value", skill), ); @@ -471,28 +428,24 @@ export class ProfileHelper } const profileSkills = pmcProfile?.Skills?.Common; - if (!profileSkills) - { + if (!profileSkills) { this.logger.warning(`Unable to add ${pointsToAddToSkill} points to ${skill}, profile has no skills`); return; } const profileSkill = profileSkills.find((profileSkill) => profileSkill.Id === skill); - if (!profileSkill) - { + if (!profileSkill) { this.logger.error(this.localisationService.getText("quest-no_skill_found", skill)); return; } - if (useSkillProgressRateMultipler) - { + if (useSkillProgressRateMultipler) { const skillProgressRate = this.databaseService.getGlobals().config.SkillsSettings.SkillProgressRate; pointsToAddToSkill *= skillProgressRate; } // Apply custom multipler to skill amount gained, if exists - if (this.inventoryConfig.skillGainMultiplers[skill]) - { + if (this.inventoryConfig.skillGainMultiplers[skill]) { pointsToAddToSkill *= this.inventoryConfig.skillGainMultiplers[skill]; } @@ -507,11 +460,9 @@ export class ProfileHelper * @param skill Skill to look up and return value from * @returns Common skill object from desired profile */ - public getSkillFromProfile(pmcData: IPmcData, skill: SkillTypes): Common - { + public getSkillFromProfile(pmcData: IPmcData, skill: SkillTypes): Common { const skillToReturn = pmcData.Skills.Common.find((commonSkill) => commonSkill.Id === skill); - if (!skillToReturn) - { + if (!skillToReturn) { this.logger.warning(`Profile ${pmcData.sessionId} does not have a skill named: ${skill}`); return undefined; } @@ -524,8 +475,7 @@ export class ProfileHelper * @param sessionID Profile id ot check * @returns True if account is developer */ - public isDeveloperAccount(sessionID: string): boolean - { + public isDeveloperAccount(sessionID: string): boolean { return this.getFullProfile(sessionID).info.edition.toLowerCase().startsWith(AccountTypes.SPT_DEVELOPER); } @@ -534,12 +484,10 @@ export class ProfileHelper * @param sessionId Profile id to give rows to * @param rowsToAdd How many rows to give profile */ - public addStashRowsBonusToProfile(sessionId: string, rowsToAdd: number): void - { + public addStashRowsBonusToProfile(sessionId: string, rowsToAdd: number): void { const profile = this.getPmcProfile(sessionId); const existingBonus = profile.Bonuses.find((bonus) => bonus.type === BonusType.STASH_ROWS); - if (!existingBonus) - { + if (!existingBonus) { profile.Bonuses.push({ id: this.hashUtil.generate(), value: rowsToAdd, @@ -548,18 +496,14 @@ export class ProfileHelper visible: true, production: false, }); - } - else - { + } else { existingBonus.value += rowsToAdd; } } - public playerIsFleaBanned(pmcProfile: IPmcData): boolean - { + public playerIsFleaBanned(pmcProfile: IPmcData): boolean { const currentTimestamp = this.timeUtil.getTimestamp(); - return pmcProfile.Info.Bans - .some((ban) => ban.banType === BanType.RAGFAIR && currentTimestamp < ban.dateTime); + return pmcProfile.Info.Bans.some((ban) => ban.banType === BanType.RAGFAIR && currentTimestamp < ban.dateTime); } /** @@ -567,14 +511,11 @@ export class ProfileHelper * @param pmcProfile Profile to add achievement to * @param achievementId Id of achievement to add */ - public addAchievementToProfile(pmcProfile: IPmcData, achievementId: string): void - { + public addAchievementToProfile(pmcProfile: IPmcData, achievementId: string): void { pmcProfile.Achievements[achievementId] = this.timeUtil.getTimestamp(); } - public hasAccessToRepeatableFreeRefreshSystem(pmcProfile: IPmcData): boolean - { - return [GameEditions.EDGE_OF_DARKNESS, GameEditions.UNHEARD] - .includes(pmcProfile.Info?.GameVersion); + public hasAccessToRepeatableFreeRefreshSystem(pmcProfile: IPmcData): boolean { + return [GameEditions.EDGE_OF_DARKNESS, GameEditions.UNHEARD].includes(pmcProfile.Info?.GameVersion); } } diff --git a/project/src/helpers/QuestConditionHelper.ts b/project/src/helpers/QuestConditionHelper.ts index 6260fdf5..6385eaff 100644 --- a/project/src/helpers/QuestConditionHelper.ts +++ b/project/src/helpers/QuestConditionHelper.ts @@ -1,38 +1,33 @@ -import { injectable } from "tsyringe"; import { IQuestCondition } from "@spt/models/eft/common/tables/IQuest"; +import { injectable } from "tsyringe"; @injectable() -export class QuestConditionHelper -{ +export class QuestConditionHelper { public getQuestConditions( q: IQuestCondition[], furtherFilter?: (a: IQuestCondition) => IQuestCondition[], - ): IQuestCondition[] - { + ): IQuestCondition[] { return this.filterConditions(q, "Quest", furtherFilter); } public getLevelConditions( q: IQuestCondition[], furtherFilter?: (a: IQuestCondition) => IQuestCondition[], - ): IQuestCondition[] - { + ): IQuestCondition[] { return this.filterConditions(q, "Level", furtherFilter); } public getLoyaltyConditions( q: IQuestCondition[], furtherFilter?: (a: IQuestCondition) => IQuestCondition[], - ): IQuestCondition[] - { + ): IQuestCondition[] { return this.filterConditions(q, "TraderLoyalty", furtherFilter); } public getStandingConditions( q: IQuestCondition[], furtherFilter?: (a: IQuestCondition) => IQuestCondition[], - ): IQuestCondition[] - { + ): IQuestCondition[] { return this.filterConditions(q, "TraderStanding", furtherFilter); } @@ -40,14 +35,10 @@ export class QuestConditionHelper q: IQuestCondition[], questType: string, furtherFilter?: (a: IQuestCondition) => IQuestCondition[], - ): IQuestCondition[] - { - const filteredQuests = q.filter((c) => - { - if (c.conditionType === questType) - { - if (furtherFilter) - { + ): IQuestCondition[] { + const filteredQuests = q.filter((c) => { + if (c.conditionType === questType) { + if (furtherFilter) { return furtherFilter(c); } return true; diff --git a/project/src/helpers/QuestHelper.ts b/project/src/helpers/QuestHelper.ts index 58633472..086fbcd6 100644 --- a/project/src/helpers/QuestHelper.ts +++ b/project/src/helpers/QuestHelper.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { DialogueHelper } from "@spt/helpers/DialogueHelper"; import { ItemHelper } from "@spt/helpers/ItemHelper"; import { PaymentHelper } from "@spt/helpers/PaymentHelper"; @@ -29,13 +28,13 @@ import { LocaleService } from "@spt/services/LocaleService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { MailSendService } from "@spt/services/MailSendService"; import { SeasonalEventService } from "@spt/services/SeasonalEventService"; -import { ICloner } from "@spt/utils/cloners/ICloner"; import { HashUtil } from "@spt/utils/HashUtil"; import { TimeUtil } from "@spt/utils/TimeUtil"; +import { ICloner } from "@spt/utils/cloners/ICloner"; +import { inject, injectable } from "tsyringe"; @injectable() -export class QuestHelper -{ +export class QuestHelper { protected questConfig: IQuestConfig; constructor( @@ -58,8 +57,7 @@ export class QuestHelper @inject("MailSendService") protected mailSendService: MailSendService, @inject("ConfigServer") protected configServer: ConfigServer, @inject("PrimaryCloner") protected cloner: ICloner, - ) - { + ) { this.questConfig = this.configServer.getConfig(ConfigTypes.QUEST); } @@ -69,8 +67,7 @@ export class QuestHelper * @param questId Quest id to look up * @returns QuestStatus enum */ - public getQuestStatus(pmcData: IPmcData, questId: string): QuestStatus - { + public getQuestStatus(pmcData: IPmcData, questId: string): QuestStatus { const quest = pmcData.Quests?.find((q) => q.qid === questId); return quest ? quest.status : QuestStatus.Locked; @@ -82,12 +79,9 @@ export class QuestHelper * @param condition Quest condition * @returns true if player level is greater than or equal to quest */ - public doesPlayerLevelFulfilCondition(playerLevel: number, condition: IQuestCondition): boolean - { - if (condition.conditionType === "Level") - { - switch (condition.compareMethod) - { + public doesPlayerLevelFulfilCondition(playerLevel: number, condition: IQuestCondition): boolean { + if (condition.conditionType === "Level") { + switch (condition.compareMethod) { case ">=": return playerLevel >= condition.value; case ">": @@ -116,18 +110,14 @@ export class QuestHelper * @param after Array of quests #2 * @returns Reduction of cartesian product between two quest arrays */ - public getDeltaQuests(before: IQuest[], after: IQuest[]): IQuest[] - { + public getDeltaQuests(before: IQuest[], after: IQuest[]): IQuest[] { const knownQuestsIds = []; - for (const q of before) - { + for (const q of before) { knownQuestsIds.push(q._id); } - if (knownQuestsIds.length) - { - return after.filter((q) => - { + if (knownQuestsIds.length) { + return after.filter((q) => { return knownQuestsIds.indexOf(q._id) === -1; }); } @@ -141,13 +131,11 @@ export class QuestHelper * @param progressAmount the amount of experience being added to the skill * @returns the adjusted skill progress gain */ - public adjustSkillExpForLowLevels(profileSkill: Common, progressAmount: number): number - { + public adjustSkillExpForLowLevels(profileSkill: Common, progressAmount: number): number { let currentLevel = Math.floor(profileSkill.Progress / 100); // Only run this if the current level is under 9 - if (currentLevel >= 9) - { + if (currentLevel >= 9) { return progressAmount; } @@ -160,8 +148,7 @@ export class QuestHelper // We have to do this loop to handle edge cases where the provided XP bumps your level up // See "CalculateExpOnFirstLevels" in client for original logic let adjustedSkillProgress = 0; - while (remainingProgress > 0 && currentLevel < 9) - { + while (remainingProgress > 0 && currentLevel < 9) { // Calculate how much progress to add, limiting it to the current level max progress const currentLevelRemainingProgress = (currentLevel + 1) * 10 - startingLevelProgress; this.logger.debug(`currentLevelRemainingProgress: ${currentLevelRemainingProgress}`); @@ -177,8 +164,7 @@ export class QuestHelper } // If there's any remaining progress, add it. This handles if you go from level 8 -> 9 - if (remainingProgress > 0) - { + if (remainingProgress > 0) { adjustedSkillProgress += remainingProgress; } @@ -190,8 +176,7 @@ export class QuestHelper * @param questId id to get * @returns */ - public getQuestNameFromLocale(questId: string): string - { + public getQuestNameFromLocale(questId: string): string { const questNameKey = `${questId} name`; return this.localeService.getLocaleDb()[questNameKey]; } @@ -202,13 +187,13 @@ export class QuestHelper * @param profile Player profile * @returns true if loyalty is high enough to fulfill quest requirement */ - public traderLoyaltyLevelRequirementCheck(questProperties: IQuestCondition, profile: IPmcData): boolean - { + public traderLoyaltyLevelRequirementCheck(questProperties: IQuestCondition, profile: IPmcData): boolean { const requiredLoyaltyLevel = Number(questProperties.value); const trader = profile.TradersInfo[questProperties.target]; - if (!trader) - { - this.logger.error(this.localisationService.getText("quest-unable_to_find_trader_in_profile", questProperties.target)); + if (!trader) { + this.logger.error( + this.localisationService.getText("quest-unable_to_find_trader_in_profile", questProperties.target), + ); } return this.compareAvailableForValues(trader.loyaltyLevel, requiredLoyaltyLevel, questProperties.compareMethod); @@ -220,22 +205,18 @@ export class QuestHelper * @param profile Player profile * @returns true if standing is high enough to fulfill quest requirement */ - public traderStandingRequirementCheck(questProperties: IQuestCondition, profile: IPmcData): boolean - { + public traderStandingRequirementCheck(questProperties: IQuestCondition, profile: IPmcData): boolean { const requiredStanding = Number(questProperties.value); const trader = profile.TradersInfo[questProperties.target]; - if (!trader) - { + if (!trader) { this.localisationService.getText("quest-unable_to_find_trader_in_profile", questProperties.target); } return this.compareAvailableForValues(trader.standing, requiredStanding, questProperties.compareMethod); } - protected compareAvailableForValues(current: number, required: number, compareMethod: string): boolean - { - switch (compareMethod) - { + protected compareAvailableForValues(current: number, required: number, compareMethod: string): boolean { + switch (compareMethod) { case ">=": return current >= required; case ">": @@ -261,58 +242,48 @@ export class QuestHelper * @param questReward Reward item to fix * @returns Fixed rewards */ - protected processReward(questReward: IQuestReward): Item[] - { + protected processReward(questReward: IQuestReward): Item[] { /** item with mods to return */ let rewardItems: Item[] = []; let targets: Item[] = []; const mods: Item[] = []; // Is armor item that may need inserts / plates - if (questReward.items.length === 1 && this.itemHelper.armorItemCanHoldMods(questReward.items[0]._tpl)) - { + if (questReward.items.length === 1 && this.itemHelper.armorItemCanHoldMods(questReward.items[0]._tpl)) { // Only process items with slots - if (this.itemHelper.itemHasSlots(questReward.items[0]._tpl)) - { + if (this.itemHelper.itemHasSlots(questReward.items[0]._tpl)) { // Attempt to pull default preset from globals and add child items to reward (clones questReward.items) this.generateArmorRewardChildSlots(questReward.items[0], questReward); } } - for (const rewardItem of questReward.items) - { + for (const rewardItem of questReward.items) { this.itemHelper.addUpdObjectToItem(rewardItem); // Reward items are granted Found in Raid status rewardItem.upd.SpawnedInSession = true; // Is root item, fix stacks - if (rewardItem._id === questReward.target) - { + if (rewardItem._id === questReward.target) { // Is base reward item if ( - rewardItem.parentId !== undefined - && rewardItem.parentId === "hideout" // Has parentId of hideout - && rewardItem.upd !== undefined - && rewardItem.upd.StackObjectsCount !== undefined // Has upd with stackobject count - && rewardItem.upd.StackObjectsCount > 1 // More than 1 item in stack - ) - { + rewardItem.parentId !== undefined && + rewardItem.parentId === "hideout" && // Has parentId of hideout + rewardItem.upd !== undefined && + rewardItem.upd.StackObjectsCount !== undefined && // Has upd with stackobject count + rewardItem.upd.StackObjectsCount > 1 // More than 1 item in stack + ) { rewardItem.upd.StackObjectsCount = 1; } targets = this.itemHelper.splitStack(rewardItem); // splitStack created new ids for the new stacks. This would destroy the relation to possible children. // Instead, we reset the id to preserve relations and generate a new id in the downstream loop, where we are also reparenting if required - for (const target of targets) - { + for (const target of targets) { target._id = rewardItem._id; } - } - else - { + } else { // Is child mod - if (questReward.items[0].upd.SpawnedInSession) - { + if (questReward.items[0].upd.SpawnedInSession) { // Propigate FiR status into child items rewardItem.upd.SpawnedInSession = questReward.items[0].upd.SpawnedInSession; } @@ -322,15 +293,13 @@ export class QuestHelper } // Add mods to the base items, fix ids - for (const target of targets) - { + for (const target of targets) { // This has all the original id relations since we reset the id to the original after the splitStack const itemsClone = [this.cloner.clone(target)]; // Here we generate a new id for the root item target._id = this.hashUtil.generate(); - for (const mod of mods) - { + for (const mod of mods) { itemsClone.push(this.cloner.clone(mod)); } @@ -345,12 +314,10 @@ export class QuestHelper * @param originalRewardRootItem Original armor reward item from IQuestReward.items object * @param questReward Armor reward from quest */ - protected generateArmorRewardChildSlots(originalRewardRootItem: Item, questReward: IQuestReward): void - { + protected generateArmorRewardChildSlots(originalRewardRootItem: Item, questReward: IQuestReward): void { // Look for a default preset from globals for armor const defaultPreset = this.presetHelper.getDefaultPreset(originalRewardRootItem._tpl); - if (defaultPreset) - { + if (defaultPreset) { // Found preset, use mods to hydrate reward item const presetAndMods: Item[] = this.itemHelper.replaceIDs(defaultPreset._items); const newRootId = this.itemHelper.remapRootItemId(presetAndMods); @@ -386,8 +353,7 @@ export class QuestHelper * @param status Quest status that holds the items (Started, Success, Fail) * @returns array of items with the correct maxStack */ - public getQuestRewardItems(quest: IQuest, status: QuestStatus): Item[] - { + public getQuestRewardItems(quest: IQuest, status: QuestStatus): Item[] { // Iterate over all rewards with the desired status, flatten out items that have a type of Item const questRewards = quest.rewards[QuestStatus[status]].flatMap((reward: IQuestReward) => reward.type === "Item" ? this.processReward(reward) : [], @@ -406,20 +372,17 @@ export class QuestHelper pmcData: IPmcData, newState: QuestStatus, acceptedQuest: IAcceptQuestRequestData, - ): IQuestStatus - { + ): IQuestStatus { const currentTimestamp = this.timeUtil.getTimestamp(); const existingQuest = pmcData.Quests.find((q) => q.qid === acceptedQuest.qid); - if (existingQuest) - { + if (existingQuest) { // Quest exists, update its status existingQuest.startTime = currentTimestamp; existingQuest.status = newState; existingQuest.statusTimers[newState] = currentTimestamp; existingQuest.completedConditions = []; - if (existingQuest.availableAfter) - { + if (existingQuest.availableAfter) { delete existingQuest.availableAfter; } @@ -436,21 +399,22 @@ export class QuestHelper // Check if quest has a prereq to be placed in a 'pending' state, otherwise set status timers value const questDbData = this.getQuestFromDb(acceptedQuest.qid, pmcData); - if (!questDbData) - { - this.logger.error(this.localisationService.getText("quest-unable_to_find_quest_in_db", { questId: acceptedQuest.qid, questType: acceptedQuest.type })); + if (!questDbData) { + this.logger.error( + this.localisationService.getText("quest-unable_to_find_quest_in_db", { + questId: acceptedQuest.qid, + questType: acceptedQuest.type, + }), + ); } const waitTime = questDbData?.conditions.AvailableForStart.find((x) => x.availableAfter > 0); - if (waitTime && acceptedQuest.type !== "repeatable") - { + if (waitTime && acceptedQuest.type !== "repeatable") { // Quest should be put into 'pending' state newQuest.startTime = 0; newQuest.status = QuestStatus.AvailableAfter; // 9 newQuest.availableAfter = currentTimestamp + waitTime.availableAfter; - } - else - { + } else { newQuest.statusTimers[newState.toString()] = currentTimestamp; newQuest.completedConditions = []; } @@ -464,51 +428,43 @@ export class QuestHelper * @param sessionID Session id * @returns Quests accessible to player incuding newly unlocked quests now quest (startedQuestId) was started */ - public getNewlyAccessibleQuestsWhenStartingQuest(startedQuestId: string, sessionID: string): IQuest[] - { + public getNewlyAccessibleQuestsWhenStartingQuest(startedQuestId: string, sessionID: string): IQuest[] { // Get quest acceptance data from profile const profile: IPmcData = this.profileHelper.getPmcProfile(sessionID); const startedQuestInProfile = profile.Quests.find((profileQuest) => profileQuest.qid === startedQuestId); // Get quests that - const eligibleQuests = this.getQuestsFromDb().filter((quest) => - { + const eligibleQuests = this.getQuestsFromDb().filter((quest) => { // Quest is accessible to player when the accepted quest passed into param is started // e.g. Quest A passed in, quest B is looped over and has requirement of A to be started, include it - const acceptedQuestCondition = quest.conditions.AvailableForStart.find((condition) => - { + const acceptedQuestCondition = quest.conditions.AvailableForStart.find((condition) => { return ( - condition.conditionType === "Quest" - && condition.target?.includes(startedQuestId) - && condition.status?.includes(QuestStatus.Started) + condition.conditionType === "Quest" && + condition.target?.includes(startedQuestId) && + condition.status?.includes(QuestStatus.Started) ); }); // Not found, skip quest - if (!acceptedQuestCondition) - { + if (!acceptedQuestCondition) { return false; } // Skip locked event quests - if (!this.showEventQuestToPlayer(quest._id)) - { + if (!this.showEventQuestToPlayer(quest._id)) { return false; } // Skip quest if its flagged as for other side - if (this.questIsForOtherSide(profile.Info.Side, quest._id)) - { + if (this.questIsForOtherSide(profile.Info.Side, quest._id)) { return false; } const standingRequirements = this.questConditionHelper.getStandingConditions( quest.conditions.AvailableForStart, ); - for (const condition of standingRequirements) - { - if (!this.traderStandingRequirementCheck(condition, profile)) - { + for (const condition of standingRequirements) { + if (!this.traderStandingRequirementCheck(condition, profile)) { return false; } } @@ -516,18 +472,16 @@ export class QuestHelper const loyaltyRequirements = this.questConditionHelper.getLoyaltyConditions( quest.conditions.AvailableForStart, ); - for (const condition of loyaltyRequirements) - { - if (!this.traderLoyaltyLevelRequirementCheck(condition, profile)) - { + for (const condition of loyaltyRequirements) { + if (!this.traderLoyaltyLevelRequirementCheck(condition, profile)) { return false; } } // Include if quest found in profile and is started or ready to hand in return ( - startedQuestInProfile - && [QuestStatus.Started, QuestStatus.AvailableForFinish].includes(startedQuestInProfile.status) + startedQuestInProfile && + [QuestStatus.Started, QuestStatus.AvailableForFinish].includes(startedQuestInProfile.status) ); }); @@ -539,35 +493,31 @@ export class QuestHelper * @param questId Quest to check * @returns true = show to player */ - public showEventQuestToPlayer(questId: string): boolean - { + public showEventQuestToPlayer(questId: string): boolean { const isChristmasEventActive = this.seasonalEventService.christmasEventEnabled(); const isHalloweenEventActive = this.seasonalEventService.halloweenEventEnabled(); // Not christmas + quest is for christmas if ( - !isChristmasEventActive - && this.seasonalEventService.isQuestRelatedToEvent(questId, SeasonalEventType.CHRISTMAS) - ) - { + !isChristmasEventActive && + this.seasonalEventService.isQuestRelatedToEvent(questId, SeasonalEventType.CHRISTMAS) + ) { return false; } // Not halloween + quest is for halloween if ( - !isHalloweenEventActive - && this.seasonalEventService.isQuestRelatedToEvent(questId, SeasonalEventType.HALLOWEEN) - ) - { + !isHalloweenEventActive && + this.seasonalEventService.isQuestRelatedToEvent(questId, SeasonalEventType.HALLOWEEN) + ) { return false; } // Should non-season event quests be shown to player if ( - !this.questConfig.showNonSeasonalEventQuests - && this.seasonalEventService.isQuestRelatedToEvent(questId, SeasonalEventType.NONE) - ) - { + !this.questConfig.showNonSeasonalEventQuests && + this.seasonalEventService.isQuestRelatedToEvent(questId, SeasonalEventType.NONE) + ) { return false; } @@ -579,17 +529,14 @@ export class QuestHelper * @param playerSide Player side (usec/bear) * @param questId QuestId to check */ - public questIsForOtherSide(playerSide: string, questId: string): boolean - { + public questIsForOtherSide(playerSide: string, questId: string): boolean { const isUsec = playerSide.toLowerCase() === "usec"; - if (isUsec && this.questConfig.bearOnlyQuests.includes(questId)) - { + if (isUsec && this.questConfig.bearOnlyQuests.includes(questId)) { // player is usec and quest is bear only, skip return true; } - if (!isUsec && this.questConfig.usecOnlyQuests.includes(questId)) - { + if (!isUsec && this.questConfig.usecOnlyQuests.includes(questId)) { // player is bear and quest is usec only, skip return true; } @@ -603,30 +550,25 @@ export class QuestHelper * @param sessionId Session id * @returns IQuest array */ - public failedUnlocked(failedQuestId: string, sessionId: string): IQuest[] - { + public failedUnlocked(failedQuestId: string, sessionId: string): IQuest[] { const profile = this.profileHelper.getPmcProfile(sessionId); const profileQuest = profile.Quests.find((x) => x.qid === failedQuestId); - const quests = this.getQuestsFromDb().filter((q) => - { - const acceptedQuestCondition = q.conditions.AvailableForStart.find((c) => - { + const quests = this.getQuestsFromDb().filter((q) => { + const acceptedQuestCondition = q.conditions.AvailableForStart.find((c) => { return ( c.conditionType === "Quest" && c.target.includes(failedQuestId) && c.status[0] === QuestStatus.Fail ); }); - if (!acceptedQuestCondition) - { + if (!acceptedQuestCondition) { return false; } return profileQuest && profileQuest.status === QuestStatus.Fail; }); - if (quests.length === 0) - { + if (quests.length === 0) { return quests; } @@ -640,15 +582,12 @@ export class QuestHelper * @param questStatus Status of quest to apply money boost to rewards of * @returns Updated quest */ - public applyMoneyBoost(quest: IQuest, bonusPercent: number, questStatus: QuestStatus): IQuest - { + public applyMoneyBoost(quest: IQuest, bonusPercent: number, questStatus: QuestStatus): IQuest { const rewards: IQuestReward[] = quest.rewards?.[QuestStatus[questStatus]] ?? []; - const multipler = (bonusPercent / 100) + 1; - for (const reward of rewards) - { + const multipler = bonusPercent / 100 + 1; + for (const reward of rewards) { // Skip non-money items - if (reward.type !== "Item" || !this.paymentHelper.isMoneyTpl(reward.items[0]._tpl)) - { + if (reward.type !== "Item" || !this.paymentHelper.isMoneyTpl(reward.items[0]._tpl)) { continue; } @@ -677,27 +616,22 @@ export class QuestHelper newStackSize: number, sessionID: string, output: IItemEventRouterResponse, - ): void - { + ): void { const inventoryItemIndex = pmcData.Inventory.items.findIndex((item) => item._id === itemId); - if (inventoryItemIndex < 0) - { + if (inventoryItemIndex < 0) { this.logger.error(this.localisationService.getText("quest-item_not_found_in_inventory", itemId)); return; } - if (newStackSize > 0) - { + if (newStackSize > 0) { const item = pmcData.Inventory.items[inventoryItemIndex]; this.itemHelper.addUpdObjectToItem(item); item.upd.StackObjectsCount = newStackSize; this.addItemStackSizeChangeIntoEventResponse(output, sessionID, item); - } - else - { + } else { // this case is probably dead Code right now, since the only calling function // checks explicitly for Value > 0. output.profileChanges[sessionID].items.del.push({ _id: itemId }); @@ -715,8 +649,7 @@ export class QuestHelper output: IItemEventRouterResponse, sessionId: string, item: Item, - ): void - { + ): void { output.profileChanges[sessionId].items.change.push({ _id: item._id, _tpl: item._tpl, @@ -732,10 +665,8 @@ export class QuestHelper * @param quests quests to process * @returns quest array without conditions */ - protected getQuestsWithOnlyLevelRequirementStartCondition(quests: IQuest[]): IQuest[] - { - for (const i in quests) - { + protected getQuestsWithOnlyLevelRequirementStartCondition(quests: IQuest[]): IQuest[] { + for (const i in quests) { quests[i] = this.getQuestWithOnlyLevelRequirementStartCondition(quests[i]); } @@ -747,8 +678,7 @@ export class QuestHelper * @param quest quest to clean * @returns reset IQuest object */ - public getQuestWithOnlyLevelRequirementStartCondition(quest: IQuest): IQuest - { + public getQuestWithOnlyLevelRequirementStartCondition(quest: IQuest): IQuest { const updatedQuest = this.cloner.clone(quest); updatedQuest.conditions.AvailableForStart = updatedQuest.conditions.AvailableForStart.filter( (q) => q.conditionType === "Level", @@ -769,13 +699,11 @@ export class QuestHelper failRequest: IFailQuestRequestData, sessionID: string, output?: IItemEventRouterResponse, - ): void - { + ): void { let updatedOutput = output; // Prepare response to send back to client - if (!updatedOutput) - { + if (!updatedOutput) { updatedOutput = this.eventOutputHolder.getOutput(sessionID); } @@ -797,10 +725,8 @@ export class QuestHelper ).find((activeQuest) => activeQuest._id === failRequest.qid); // Quest found and no repeatable found - if (quest && !matchingRepeatableQuest) - { - if (quest.failMessageText.trim().length > 0) - { + if (quest && !matchingRepeatableQuest) { + if (quest.failMessageText.trim().length > 0) { this.mailSendService.sendLocalisedNpcMessageToPlayer( sessionID, this.traderHelper.getTraderById(quest?.traderId ?? matchingRepeatableQuest?.traderId), // Can be undefined when repeatable quest has been moved to inactiveQuests @@ -820,8 +746,7 @@ export class QuestHelper * NOT CLONED * @returns Array of IQuest objects */ - public getQuestsFromDb(): IQuest[] - { + public getQuestsFromDb(): IQuest[] { return Object.values(this.databaseService.getQuests()); } @@ -831,18 +756,14 @@ export class QuestHelper * @param pmcData Player profile * @returns IQuest object */ - public getQuestFromDb(questId: string, pmcData: IPmcData): IQuest - { + public getQuestFromDb(questId: string, pmcData: IPmcData): IQuest { // May be a repeatable quest let quest = this.databaseService.getQuests()[questId]; - if (!quest) - { + if (!quest) { // Check daily/weekly objects - for (const repeatableType of pmcData.RepeatableQuests) - { + for (const repeatableType of pmcData.RepeatableQuests) { quest = (repeatableType.activeQuests.find((repeatable) => repeatable._id === questId)); - if (quest) - { + if (quest) { break; } } @@ -857,17 +778,15 @@ export class QuestHelper * @param questDescriptionId description property from IQuest * @returns message id */ - public getMessageIdForQuestStart(startedMessageTextId: string, questDescriptionId: string): string - { + public getMessageIdForQuestStart(startedMessageTextId: string, questDescriptionId: string): string { // blank or is a guid, use description instead const startedMessageText = this.getQuestLocaleIdFromDb(startedMessageTextId); if ( - !startedMessageText - || startedMessageText.trim() === "" - || startedMessageText.toLowerCase() === "test" - || startedMessageText.length === 24 - ) - { + !startedMessageText || + startedMessageText.trim() === "" || + startedMessageText.toLowerCase() === "test" || + startedMessageText.length === 24 + ) { return questDescriptionId; } @@ -879,8 +798,7 @@ export class QuestHelper * @param questMessageId Quest message id to look up * @returns Locale Id from locale db */ - public getQuestLocaleIdFromDb(questMessageId: string): string - { + public getQuestLocaleIdFromDb(questMessageId: string): string { const locale = this.localeService.getLocaleDb(); return locale[questMessageId]; } @@ -891,12 +809,10 @@ export class QuestHelper * @param newQuestState New state the quest should be in * @param questId Id of the quest to alter the status of */ - public updateQuestState(pmcData: IPmcData, newQuestState: QuestStatus, questId: string): void - { + public updateQuestState(pmcData: IPmcData, newQuestState: QuestStatus, questId: string): void { // Find quest in profile, update status to desired status const questToUpdate = pmcData.Quests.find((quest) => quest.qid === questId); - if (questToUpdate) - { + if (questToUpdate) { questToUpdate.status = newQuestState; questToUpdate.statusTimers[newQuestState] = this.timeUtil.getTimestamp(); } @@ -908,28 +824,23 @@ export class QuestHelper * @param newQuestState New state the quest should be in * @param questId Id of the quest to alter the status of */ - public resetQuestState(pmcData: IPmcData, newQuestState: QuestStatus, questId: string): void - { + public resetQuestState(pmcData: IPmcData, newQuestState: QuestStatus, questId: string): void { const questToUpdate = pmcData.Quests.find((quest) => quest.qid === questId); - if (questToUpdate) - { + if (questToUpdate) { const currentTimestamp = this.timeUtil.getTimestamp(); questToUpdate.status = newQuestState; // Only set start time when quest is being started - if (newQuestState === QuestStatus.Started) - { + if (newQuestState === QuestStatus.Started) { questToUpdate.startTime = currentTimestamp; } questToUpdate.statusTimers[newQuestState] = currentTimestamp; // Delete all status timers after applying new status - for (const statusKey in questToUpdate.statusTimers) - { - if (Number.parseInt(statusKey) > newQuestState) - { + for (const statusKey in questToUpdate.statusTimers) { + if (Number.parseInt(statusKey) > newQuestState) { delete questToUpdate.statusTimers[statusKey]; } } @@ -954,33 +865,30 @@ export class QuestHelper state: QuestStatus, sessionId: string, questResponse: IItemEventRouterResponse, - ): Item[] - { + ): Item[] { // Repeatable quest base data is always in PMCProfile, `profileData` may be scav profile // TODO: consider moving repeatable quest data to profile-agnostic location const pmcProfile = this.profileHelper.getPmcProfile(sessionId); let questDetails = this.getQuestFromDb(questId, pmcProfile); - if (!questDetails) - { - this.logger.warning(this.localisationService.getText("quest-unable_to_find_quest_in_db_no_quest_rewards", questId)); + if (!questDetails) { + this.logger.warning( + this.localisationService.getText("quest-unable_to_find_quest_in_db_no_quest_rewards", questId), + ); return []; } // Check for and apply intel center money bonus if it exists const questMoneyRewardBonusPercent = this.getQuestMoneyRewardBonus(pmcProfile); - if (questMoneyRewardBonusPercent > 0) - { + if (questMoneyRewardBonusPercent > 0) { // Apply additional bonus from hideout skill questDetails = this.applyMoneyBoost(questDetails, questMoneyRewardBonusPercent, state); // money = money + (money * intelCenterBonus / 100) } // e.g. 'Success' or 'AvailableForFinish' const questStateAsString = QuestStatus[state]; - for (const reward of questDetails.rewards[questStateAsString]) - { - switch (reward.type) - { + for (const reward of questDetails.rewards[questStateAsString]) { + switch (reward.type) { case QuestRewardType.SKILL: this.profileHelper.addSkillPointsToPlayer( profileData, @@ -1052,20 +960,19 @@ export class QuestHelper questDetails: IQuest, sessionID: string, response: IItemEventRouterResponse, - ): void - { + ): void { // Get hideout crafts and find those that match by areatype/required level/end product tpl - hope for just one match const hideoutProductions = this.databaseService.getHideout().production; const matchingProductions = hideoutProductions.filter( (prod) => - prod.areaType === Number.parseInt(craftUnlockReward.traderId) - && prod.requirements.some((requirement) => requirement.questId === questDetails._id) - && prod.requirements.some((x) => x.requiredLevel === craftUnlockReward.loyaltyLevel) - && prod.endProduct === craftUnlockReward.items[0]._tpl); + prod.areaType === Number.parseInt(craftUnlockReward.traderId) && + prod.requirements.some((requirement) => requirement.questId === questDetails._id) && + prod.requirements.some((x) => x.requiredLevel === craftUnlockReward.loyaltyLevel) && + prod.endProduct === craftUnlockReward.items[0]._tpl, + ); // More/less than 1 match, above filtering wasn't strict enough - if (matchingProductions.length !== 1) - { + if (matchingProductions.length !== 1) { this.logger.error( this.localisationService.getText("quest-unable_to_find_matching_hideout_production", { questName: questDetails.QuestName, @@ -1087,12 +994,10 @@ export class QuestHelper * @param pmcData player profile * @returns bonus as a percent */ - protected getQuestMoneyRewardBonus(pmcData: IPmcData): number - { + protected getQuestMoneyRewardBonus(pmcData: IPmcData): number { // Check player has intel center const moneyRewardBonuses = pmcData.Bonuses.filter((x) => x.type === "QuestMoneyReward"); - if (!moneyRewardBonuses) - { + if (!moneyRewardBonuses) { return 0; } @@ -1101,8 +1006,7 @@ export class QuestHelper // Apply hideout management bonus to money reward (up to 51% bonus) const hideoutManagementSkill = this.profileHelper.getSkillFromProfile(pmcData, SkillTypes.HIDEOUT_MANAGEMENT); - if (hideoutManagementSkill) - { + if (hideoutManagementSkill) { moneyRewardBonus *= 1 + hideoutManagementSkill.Progress / 10000; // 5100 becomes 0.51, add 1 to it, 1.51, multiply the moneyreward bonus by it (e.g. 15 x 51) } @@ -1119,14 +1023,11 @@ export class QuestHelper itemTpl: string, questIds: string[], allQuests: IQuest[], - ): Record - { + ): Record { const result: Record = {}; - for (const questId of questIds) - { + for (const questId of questIds) { const questInDb = allQuests.find((x) => x._id === questId); - if (!questInDb) - { + if (!questInDb) { this.logger.debug(`Unable to find quest: ${questId} in db, cannot get 'FindItem' condition, skipping`); continue; } @@ -1134,8 +1035,7 @@ export class QuestHelper const condition = questInDb.conditions.AvailableForFinish.find( (c) => c.conditionType === "FindItem" && c?.target?.includes(itemTpl), ); - if (condition) - { + if (condition) { result[questId] = condition.id; break; @@ -1150,22 +1050,18 @@ export class QuestHelper * @param pmcProfile profile to update * @param statuses statuses quests should have */ - public addAllQuestsToProfile(pmcProfile: IPmcData, statuses: QuestStatus[]): void - { + public addAllQuestsToProfile(pmcProfile: IPmcData, statuses: QuestStatus[]): void { // Iterate over all quests in db const quests = this.databaseService.getQuests(); - for (const questIdKey in quests) - { + for (const questIdKey in quests) { // Quest from db matches quests in profile, skip const questData = quests[questIdKey]; - if (pmcProfile.Quests.some((x) => x.qid === questData._id)) - { + if (pmcProfile.Quests.some((x) => x.qid === questData._id)) { continue; } const statusesDict = {}; - for (const status of statuses) - { + for (const status of statuses) { statusesDict[status] = this.timeUtil.getTimestamp(); } @@ -1178,26 +1074,21 @@ export class QuestHelper availableAfter: 0, }; - if (pmcProfile.Quests.some((x) => x.qid === questIdKey)) - { + if (pmcProfile.Quests.some((x) => x.qid === questIdKey)) { // Update existing const existingQuest = pmcProfile.Quests.find((x) => x.qid === questIdKey); existingQuest.status = questRecordToAdd.status; existingQuest.statusTimers = questRecordToAdd.statusTimers; - } - else - { + } else { // Add new pmcProfile.Quests.push(questRecordToAdd); } } } - public findAndRemoveQuestFromArrayIfExists(questId: string, quests: IQuestStatus[]): void - { + public findAndRemoveQuestFromArrayIfExists(questId: string, quests: IQuestStatus[]): void { const pmcQuestToReplaceStatus = quests.find((quest) => quest.qid === questId); - if (pmcQuestToReplaceStatus) - { + if (pmcQuestToReplaceStatus) { quests.splice(quests.indexOf(pmcQuestToReplaceStatus), 1); } } @@ -1207,14 +1098,11 @@ export class QuestHelper * @param completedQuestId quest completed id * @returns array of IQuest objects */ - public getQuestsFailedByCompletingQuest(completedQuestId: string): IQuest[] - { + public getQuestsFailedByCompletingQuest(completedQuestId: string): IQuest[] { const questsInDb = this.getQuestsFromDb(); - return questsInDb.filter((quest) => - { + return questsInDb.filter((quest) => { // No fail conditions, exit early - if (!quest.conditions.Fail || quest.conditions.Fail.length === 0) - { + if (!quest.conditions.Fail || quest.conditions.Fail.length === 0) { return false; } @@ -1227,11 +1115,9 @@ export class QuestHelper * @param pmcData Profile to get hours for * @returns Hours item will be available for */ - public getMailItemRedeemTimeHoursForProfile(pmcData: IPmcData): number - { + public getMailItemRedeemTimeHoursForProfile(pmcData: IPmcData): number { const value = this.questConfig.mailRedeemTimeHours[pmcData.Info.GameVersion]; - if (!value) - { + if (!value) { return this.questConfig.mailRedeemTimeHours["default"]; } diff --git a/project/src/helpers/RagfairHelper.ts b/project/src/helpers/RagfairHelper.ts index 2069cd60..c9681060 100644 --- a/project/src/helpers/RagfairHelper.ts +++ b/project/src/helpers/RagfairHelper.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { HandbookHelper } from "@spt/helpers/HandbookHelper"; import { ItemHelper } from "@spt/helpers/ItemHelper"; import { TraderAssortHelper } from "@spt/helpers/TraderAssortHelper"; @@ -14,10 +13,10 @@ import { ConfigServer } from "@spt/servers/ConfigServer"; import { DatabaseService } from "@spt/services/DatabaseService"; import { RagfairLinkedItemService } from "@spt/services/RagfairLinkedItemService"; import { ICloner } from "@spt/utils/cloners/ICloner"; +import { inject, injectable } from "tsyringe"; @injectable() -export class RagfairHelper -{ +export class RagfairHelper { protected ragfairConfig: IRagfairConfig; constructor( @@ -30,8 +29,7 @@ export class RagfairHelper @inject("UtilityHelper") protected utilityHelper: UtilityHelper, @inject("ConfigServer") protected configServer: ConfigServer, @inject("PrimaryCloner") protected cloner: ICloner, - ) - { + ) { this.ragfairConfig = this.configServer.getConfig(ConfigTypes.RAGFAIR); } @@ -40,10 +38,8 @@ export class RagfairHelper * @param {string} currency * @returns string */ - public getCurrencyTag(currency: string): string - { - switch (currency) - { + public getCurrencyTag(currency: string): string { + switch (currency) { case Money.EUROS: return "EUR"; @@ -59,34 +55,27 @@ export class RagfairHelper } } - public filterCategories(sessionID: string, request: ISearchRequestData): string[] - { + public filterCategories(sessionID: string, request: ISearchRequestData): string[] { let result: string[] = []; // Case: weapon builds - if (request.buildCount) - { + if (request.buildCount) { return Object.keys(request.buildItems); } // Case: search - if (request.linkedSearchId) - { + if (request.linkedSearchId) { const data = this.ragfairLinkedItemService.getLinkedItems(request.linkedSearchId); result = !data ? [] : [...data]; } // Case: category - if (request.handbookId) - { + if (request.handbookId) { const handbook = this.getCategoryList(request.handbookId); - if (result.length) - { + if (result.length) { result = this.utilityHelper.arrayIntersect(result, handbook); - } - else - { + } else { result = handbook; } } @@ -94,14 +83,11 @@ export class RagfairHelper return result; } - public getDisplayableAssorts(sessionID: string): Record - { + public getDisplayableAssorts(sessionID: string): Record { const result: Record = {}; - for (const traderID in this.databaseService.getTraders()) - { - if (this.ragfairConfig.traders[traderID]) - { + for (const traderID in this.databaseService.getTraders()) { + if (this.ragfairConfig.traders[traderID]) { result[traderID] = this.traderAssortHelper.getAssort(sessionID, traderID, true); } } @@ -109,17 +95,13 @@ export class RagfairHelper return result; } - protected getCategoryList(handbookId: string): string[] - { + protected getCategoryList(handbookId: string): string[] { let result: string[] = []; // if its "mods" great-parent category, do double recursive loop - if (handbookId === "5b5f71a686f77447ed5636ab") - { - for (const categ of this.handbookHelper.childrenCategories(handbookId)) - { - for (const subcateg of this.handbookHelper.childrenCategories(categ)) - { + if (handbookId === "5b5f71a686f77447ed5636ab") { + for (const categ of this.handbookHelper.childrenCategories(handbookId)) { + for (const subcateg of this.handbookHelper.childrenCategories(categ)) { result = [...result, ...this.handbookHelper.templatesWithParent(subcateg)]; } } @@ -128,13 +110,11 @@ export class RagfairHelper } // item is in any other category - if (this.handbookHelper.isCategory(handbookId)) - { + if (this.handbookHelper.isCategory(handbookId)) { // list all item of the category result = this.handbookHelper.templatesWithParent(handbookId); - for (const categ of this.handbookHelper.childrenCategories(handbookId)) - { + for (const categ of this.handbookHelper.childrenCategories(handbookId)) { result = [...result, ...this.handbookHelper.templatesWithParent(categ)]; } @@ -150,31 +130,23 @@ export class RagfairHelper * Iterate over array of identical items and merge stack count * Ragfair allows abnormally large stacks. */ - public mergeStackable(items: Item[]): Item[] - { + public mergeStackable(items: Item[]): Item[] { const list = []; let rootItem = undefined; - for (let item of items) - { + for (let item of items) { item = this.itemHelper.fixItemStackCount(item); const isChild = items.some((it) => it._id === item.parentId); - if (!isChild) - { - if (!rootItem) - { + if (!isChild) { + if (!rootItem) { rootItem = this.cloner.clone(item); rootItem.upd.OriginalStackObjectsCount = rootItem.upd.StackObjectsCount; - } - else - { + } else { rootItem.upd.StackObjectsCount += item.upd.StackObjectsCount; list.push(item); } - } - else - { + } else { list.push(item); } } @@ -188,10 +160,8 @@ export class RagfairHelper * @param currencyTpl currency to get symbol for * @returns symbol of currency */ - public getCurrencySymbol(currencyTpl: string): string - { - switch (currencyTpl) - { + public getCurrencySymbol(currencyTpl: string): string { + switch (currencyTpl) { case Money.EUROS: return "€"; case Money.DOLLARS: diff --git a/project/src/helpers/RagfairOfferHelper.ts b/project/src/helpers/RagfairOfferHelper.ts index a72edfc7..303e03bf 100644 --- a/project/src/helpers/RagfairOfferHelper.ts +++ b/project/src/helpers/RagfairOfferHelper.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { BotHelper } from "@spt/helpers/BotHelper"; import { ItemHelper } from "@spt/helpers/ItemHelper"; import { PaymentHelper } from "@spt/helpers/PaymentHelper"; @@ -35,10 +34,10 @@ import { RagfairOfferService } from "@spt/services/RagfairOfferService"; import { RagfairRequiredItemsService } from "@spt/services/RagfairRequiredItemsService"; import { HashUtil } from "@spt/utils/HashUtil"; import { TimeUtil } from "@spt/utils/TimeUtil"; +import { inject, injectable } from "tsyringe"; @injectable() -export class RagfairOfferHelper -{ +export class RagfairOfferHelper { protected static goodSoldTemplate = "5bdabfb886f7743e152e867e 0"; // Your {soldItem} {itemCount} items were bought by {buyerNickname}. protected ragfairConfig: IRagfairConfig; protected questConfig: IQuestConfig; @@ -66,8 +65,7 @@ export class RagfairOfferHelper @inject("LocalisationService") protected localisationService: LocalisationService, @inject("MailSendService") protected mailSendService: MailSendService, @inject("ConfigServer") protected configServer: ConfigServer, - ) - { + ) { this.ragfairConfig = this.configServer.getConfig(ConfigTypes.RAGFAIR); this.questConfig = this.configServer.getConfig(ConfigTypes.QUEST); } @@ -85,17 +83,21 @@ export class RagfairOfferHelper itemsToAdd: string[], traderAssorts: Record, pmcData: IPmcData, - ): IRagfairOffer[] - { + ): IRagfairOffer[] { const playerIsFleaBanned = this.profileHelper.playerIsFleaBanned(pmcData); - return this.ragfairOfferService.getOffers().filter((offer) => - { - if (!this.passesSearchFilterCriteria(searchRequest, offer, pmcData)) - { + return this.ragfairOfferService.getOffers().filter((offer) => { + if (!this.passesSearchFilterCriteria(searchRequest, offer, pmcData)) { return false; } - return this.isDisplayableOffer(searchRequest, itemsToAdd, traderAssorts, offer, pmcData, playerIsFleaBanned); + return this.isDisplayableOffer( + searchRequest, + itemsToAdd, + traderAssorts, + offer, + pmcData, + playerIsFleaBanned, + ); }); } @@ -105,14 +107,11 @@ export class RagfairOfferHelper * @param pmcDataPlayer profile * @returns Matching IRagfairOffer objects */ - public getOffersThatRequireItem(searchRequest: ISearchRequestData, pmcData: IPmcData): IRagfairOffer[] - { + public getOffersThatRequireItem(searchRequest: ISearchRequestData, pmcData: IPmcData): IRagfairOffer[] { // Get all offers that requre the desired item and filter out offers from non traders if player below ragifar unlock const requiredOffers = this.ragfairRequiredItemsService.getRequiredItemsById(searchRequest.neededSearchId); - return requiredOffers.filter((offer: IRagfairOffer) => - { - if (!this.passesSearchFilterCriteria(searchRequest, offer, pmcData)) - { + return requiredOffers.filter((offer: IRagfairOffer) => { + if (!this.passesSearchFilterCriteria(searchRequest, offer, pmcData)) { return false; } @@ -133,45 +132,36 @@ export class RagfairOfferHelper itemsToAdd: string[], traderAssorts: Record, pmcData: IPmcData, - ): IRagfairOffer[] - { + ): IRagfairOffer[] { const offersMap = new Map(); const offers: IRagfairOffer[] = []; const playerIsFleaBanned = this.profileHelper.playerIsFleaBanned(pmcData); - for (const offer of this.ragfairOfferService.getOffers()) - { - if (!this.passesSearchFilterCriteria(searchRequest, offer, pmcData)) - { + for (const offer of this.ragfairOfferService.getOffers()) { + if (!this.passesSearchFilterCriteria(searchRequest, offer, pmcData)) { continue; } - if (this.isDisplayableOffer(searchRequest, itemsToAdd, traderAssorts, offer, pmcData, playerIsFleaBanned)) - { + if (this.isDisplayableOffer(searchRequest, itemsToAdd, traderAssorts, offer, pmcData, playerIsFleaBanned)) { const isTraderOffer = offer.user.memberType === MemberCategory.TRADER; - if (isTraderOffer && this.traderBuyRestrictionReached(offer)) - { + if (isTraderOffer && this.traderBuyRestrictionReached(offer)) { continue; } - if (isTraderOffer && this.traderOutOfStock(offer)) - { + if (isTraderOffer && this.traderOutOfStock(offer)) { continue; } - if (isTraderOffer && this.traderOfferItemQuestLocked(offer, traderAssorts)) - { + if (isTraderOffer && this.traderOfferItemQuestLocked(offer, traderAssorts)) { continue; } - if (isTraderOffer && this.traderOfferLockedBehindLoyaltyLevel(offer, pmcData)) - { + if (isTraderOffer && this.traderOfferLockedBehindLoyaltyLevel(offer, pmcData)) { continue; } const key = offer.items[0]._tpl; - if (!offersMap.has(key)) - { + if (!offersMap.has(key)) { offersMap.set(key, []); } @@ -180,19 +170,16 @@ export class RagfairOfferHelper } // get best offer for each item to show on screen - for (let possibleOffers of offersMap.values()) - { + for (let possibleOffers of offersMap.values()) { // Remove offers with locked = true (quest locked) when > 1 possible offers // single trader item = shows greyed out // multiple offers for item = is greyed out - if (possibleOffers.length > 1) - { + if (possibleOffers.length > 1) { const lockedOffers = this.getLoyaltyLockedOffers(possibleOffers, pmcData); // Exclude locked offers + above loyalty locked offers if at least 1 was found const availableOffers = possibleOffers.filter((x) => !(x.locked || lockedOffers.includes(x._id))); - if (availableOffers.length > 0) - { + if (availableOffers.length > 0) { possibleOffers = availableOffers; } } @@ -210,8 +197,7 @@ export class RagfairOfferHelper * @param pmcProfile Player profile * @returns True if item is locked, false if item is purchaseable */ - protected traderOfferLockedBehindLoyaltyLevel(offer: IRagfairOffer, pmcProfile: IPmcData): boolean - { + protected traderOfferLockedBehindLoyaltyLevel(offer: IRagfairOffer, pmcProfile: IPmcData): boolean { const userTraderSettings = pmcProfile.TradersInfo[offer.user.id]; return userTraderSettings.loyaltyLevel < offer.loyaltyLevel; @@ -223,8 +209,7 @@ export class RagfairOfferHelper * @param traderAssorts all trader assorts for player * @returns true if quest locked */ - public traderOfferItemQuestLocked(offer: IRagfairOffer, traderAssorts: Record): boolean - { + public traderOfferItemQuestLocked(offer: IRagfairOffer, traderAssorts: Record): boolean { return offer.items?.some((i) => traderAssorts[offer.user.id].barter_scheme[i._id]?.some((bs1) => bs1?.some((bs2) => bs2.sptQuestLocked)), ); @@ -235,10 +220,8 @@ export class RagfairOfferHelper * @param offer Offer to check stock of * @returns true if out of stock */ - protected traderOutOfStock(offer: IRagfairOffer): boolean - { - if (offer?.items?.length === 0) - { + protected traderOutOfStock(offer: IRagfairOffer): boolean { + if (offer?.items?.length === 0) { return true; } @@ -250,16 +233,14 @@ export class RagfairOfferHelper * @param offer offer to check restriction properties of * @returns true if restriction reached, false if no restrictions/not reached */ - protected traderBuyRestrictionReached(offer: IRagfairOffer): boolean - { + protected traderBuyRestrictionReached(offer: IRagfairOffer): boolean { const traderAssorts = this.traderHelper.getTraderAssortsByTraderId(offer.user.id).items; // Find item being purchased from traders assorts const assortData = traderAssorts.find((item) => item._id === offer.items[0]._id); // No trader assort data - if (!assortData) - { + if (!assortData) { this.logger.warning( `Unable to find trader: ${offer.user.nickname} assort for item: ${this.itemHelper.getItemName( offer.items[0]._tpl, @@ -269,22 +250,19 @@ export class RagfairOfferHelper return false; } - if (!assortData.upd) - { + if (!assortData.upd) { return false; } // No restriction values // Can't use !assortData.upd.BuyRestrictionX as value could be 0 const assortUpd = assortData.upd; - if (assortUpd.BuyRestrictionMax === undefined || assortUpd.BuyRestrictionCurrent === undefined) - { + if (assortUpd.BuyRestrictionMax === undefined || assortUpd.BuyRestrictionCurrent === undefined) { return false; } // Current equals max, limit reached - if (assortUpd.BuyRestrictionCurrent >= assortUpd.BuyRestrictionMax) - { + if (assortUpd.BuyRestrictionCurrent >= assortUpd.BuyRestrictionMax) { return true; } @@ -297,16 +275,12 @@ export class RagfairOfferHelper * @param pmcProfile Players profile with trader loyalty levels * @returns array of offer ids player cannot see */ - protected getLoyaltyLockedOffers(offers: IRagfairOffer[], pmcProfile: IPmcData): string[] - { + protected getLoyaltyLockedOffers(offers: IRagfairOffer[], pmcProfile: IPmcData): string[] { const loyaltyLockedOffers: string[] = []; - for (const offer of offers) - { - if (offer.user.memberType === MemberCategory.TRADER) - { + for (const offer of offers) { + if (offer.user.memberType === MemberCategory.TRADER) { const traderDetails = pmcProfile.TradersInfo[offer.user.id]; - if (traderDetails.loyaltyLevel < offer.loyaltyLevel) - { + if (traderDetails.loyaltyLevel < offer.loyaltyLevel) { loyaltyLockedOffers.push(offer._id); } } @@ -320,28 +294,23 @@ export class RagfairOfferHelper * @param sessionID Session id to process offers for * @returns true = complete */ - public processOffersOnProfile(sessionID: string): boolean - { + public processOffersOnProfile(sessionID: string): boolean { const timestamp = this.timeUtil.getTimestamp(); const profileOffers = this.getProfileOffers(sessionID); // No offers, don't do anything - if (!profileOffers?.length) - { + if (!profileOffers?.length) { return true; } - for (const offer of profileOffers.values()) - { - if (offer.sellResult?.length > 0 - && timestamp >= offer.sellResult[0].sellTime) // Checks first item, first is spliced out of array after being processed - { + for (const offer of profileOffers.values()) { + if (offer.sellResult?.length > 0 && timestamp >= offer.sellResult[0].sellTime) { + // Checks first item, first is spliced out of array after being processed // Item sold let totalItemsCount = 1; let boughtAmount = 1; - if (!offer.sellInOnePiece) - { + if (!offer.sellInOnePiece) { // offer.items.reduce((sum, item) => sum + item.upd?.StackObjectsCount ?? 0, 0); totalItemsCount = this.getTotalStackCountSize([offer.items]); boughtAmount = offer.sellResult[0].amount; @@ -365,11 +334,9 @@ export class RagfairOfferHelper * @param itemsInInventoryToList items to sum up * @returns Total count */ - public getTotalStackCountSize(itemsInInventoryToList: Item[][]): number - { + public getTotalStackCountSize(itemsInInventoryToList: Item[][]): number { let total = 0; - for (const itemAndChildren of itemsInInventoryToList) - { + for (const itemAndChildren of itemsInInventoryToList) { // Only count the root items stack count in total const rootItem = itemAndChildren[0]; total += rootItem.upd?.StackObjectsCount ?? 1; @@ -383,21 +350,18 @@ export class RagfairOfferHelper * @param sessionId Profile to update * @param amountToIncrementBy Raw amount to add to players ragfair rating (excluding the reputation gain multiplier) */ - public increaseProfileRagfairRating(profile: ISptProfile, amountToIncrementBy: number): void - { + public increaseProfileRagfairRating(profile: ISptProfile, amountToIncrementBy: number): void { const ragfairGlobalsConfig = this.databaseService.getGlobals().config.RagFair; profile.characters.pmc.RagfairInfo.isRatingGrowing = true; - if (Number.isNaN(amountToIncrementBy)) - { + if (Number.isNaN(amountToIncrementBy)) { this.logger.warning(`Unable to increment ragfair rating, value was not a number: ${amountToIncrementBy}`); return; } - profile.characters.pmc.RagfairInfo.rating - += (ragfairGlobalsConfig.ratingIncreaseCount - / ragfairGlobalsConfig.ratingSumForIncrease) - * amountToIncrementBy; + profile.characters.pmc.RagfairInfo.rating += + (ragfairGlobalsConfig.ratingIncreaseCount / ragfairGlobalsConfig.ratingSumForIncrease) * + amountToIncrementBy; } /** @@ -405,12 +369,10 @@ export class RagfairOfferHelper * @param sessionID Session id * @returns Array of ragfair offers */ - protected getProfileOffers(sessionID: string): IRagfairOffer[] - { + protected getProfileOffers(sessionID: string): IRagfairOffer[] { const profile = this.profileHelper.getPmcProfile(sessionID); - if (profile.RagfairInfo === undefined || profile.RagfairInfo.offers === undefined) - { + if (profile.RagfairInfo === undefined || profile.RagfairInfo.offers === undefined) { return []; } @@ -422,8 +384,7 @@ export class RagfairOfferHelper * @param sessionID Session id of profile to delete offer from * @param offerId Id of offer to delete */ - protected deleteOfferById(sessionID: string, offerId: string): void - { + protected deleteOfferById(sessionID: string, offerId: string): void { const profileRagfairInfo = this.saveServer.getProfile(sessionID).characters.pmc.RagfairInfo; const index = profileRagfairInfo.offers.findIndex((o) => o._id === offerId); profileRagfairInfo.offers.splice(index, 1); @@ -439,19 +400,15 @@ export class RagfairOfferHelper * @param boughtAmount Amount item was purchased for * @returns IItemEventRouterResponse */ - public completeOffer(sessionID: string, offer: IRagfairOffer, boughtAmount: number): IItemEventRouterResponse - { + public completeOffer(sessionID: string, offer: IRagfairOffer, boughtAmount: number): IItemEventRouterResponse { const itemTpl = offer.items[0]._tpl; let paymentItemsToSendToPlayer: Item[] = []; const offerStackCount = offer.items[0].upd.StackObjectsCount; // Pack or ALL items of a multi-offer were bought - remove entire ofer - if (offer.sellInOnePiece || boughtAmount === offerStackCount) - { + if (offer.sellInOnePiece || boughtAmount === offerStackCount) { this.deleteOfferById(sessionID, offer._id); - } - else - { + } else { const offerRootItem = offer.items[0]; // Reduce offer root items stack count @@ -459,8 +416,7 @@ export class RagfairOfferHelper } // Assemble payment to send to seller now offer was purchased - for (const requirement of offer.requirements) - { + for (const requirement of offer.requirements) { // Create an item template item const requestedItem: Item = { _id: this.hashUtil.generate(), @@ -469,16 +425,13 @@ export class RagfairOfferHelper }; const stacks = this.itemHelper.splitStack(requestedItem); - for (const item of stacks) - { + for (const item of stacks) { const outItems = [item]; // TODO - is this code used?, may have been when adding barters to flea was still possible for player - if (requirement.onlyFunctional) - { + if (requirement.onlyFunctional) { const presetItems = this.ragfairServerHelper.getPresetItemsByTpl(item); - if (presetItems.length) - { + if (presetItems.length) { outItems.push(presetItems[0]); } } @@ -500,7 +453,8 @@ export class RagfairOfferHelper this.getLocalisedOfferSoldMessage(itemTpl, boughtAmount), paymentItemsToSendToPlayer, this.timeUtil.getHoursAsSeconds( - this.questHelper.getMailItemRedeemTimeHoursForProfile(this.profileHelper.getPmcProfile(sessionID))), + this.questHelper.getMailItemRedeemTimeHoursForProfile(this.profileHelper.getPmcProfile(sessionID)), + ), undefined, ragfairDetails, ); @@ -514,13 +468,11 @@ export class RagfairOfferHelper * @param boughtAmount How many were purchased * @returns Localised message text */ - protected getLocalisedOfferSoldMessage(itemTpl: string, boughtAmount: number): string - { + protected getLocalisedOfferSoldMessage(itemTpl: string, boughtAmount: number): string { // Generate a message to inform that item was sold const globalLocales = this.localeService.getLocaleDb(); const soldMessageLocaleGuid = globalLocales[RagfairOfferHelper.goodSoldTemplate]; - if (!soldMessageLocaleGuid) - { + if (!soldMessageLocaleGuid) { this.logger.error( this.localisationService.getText( "ragfair-unable_to_find_locale_by_key", @@ -536,8 +488,7 @@ export class RagfairOfferHelper itemCount: boughtAmount, }; - const offerSoldMessageText = soldMessageLocaleGuid.replace(/{\w+}/g, (matched) => - { + const offerSoldMessageText = soldMessageLocaleGuid.replace(/{\w+}/g, (matched) => { return tplVars[matched.replace(/{|}/g, "")]; }); @@ -555,105 +506,84 @@ export class RagfairOfferHelper searchRequest: ISearchRequestData, offer: IRagfairOffer, pmcData: IPmcData, - ): boolean - { + ): boolean { const isDefaultUserOffer = offer.user.memberType === MemberCategory.DEFAULT; const offerRootItem = offer.items[0]; const moneyTypeTpl = offer.requirements[0]._tpl; const isTraderOffer = offer.user.memberType === MemberCategory.TRADER; - if ( - pmcData.Info.Level < this.databaseService.getGlobals().config.RagFair.minUserLevel - && isDefaultUserOffer - ) - { + if (pmcData.Info.Level < this.databaseService.getGlobals().config.RagFair.minUserLevel && isDefaultUserOffer) { // Skip item if player is < global unlock level (default is 15) and item is from a dynamically generated source return false; } - if (searchRequest.offerOwnerType === OfferOwnerType.TRADEROWNERTYPE && !isTraderOffer) - { + if (searchRequest.offerOwnerType === OfferOwnerType.TRADEROWNERTYPE && !isTraderOffer) { // don't include player offers return false; } - if (searchRequest.offerOwnerType === OfferOwnerType.PLAYEROWNERTYPE && isTraderOffer) - { + if (searchRequest.offerOwnerType === OfferOwnerType.PLAYEROWNERTYPE && isTraderOffer) { // don't include trader offers return false; } if ( - searchRequest.oneHourExpiration - && offer.endTime - this.timeUtil.getTimestamp() > TimeUtil.ONE_HOUR_AS_SECONDS - ) - { + searchRequest.oneHourExpiration && + offer.endTime - this.timeUtil.getTimestamp() > TimeUtil.ONE_HOUR_AS_SECONDS + ) { // offer doesnt expire within an hour return false; } - if (searchRequest.quantityFrom > 0 && searchRequest.quantityFrom >= offerRootItem.upd.StackObjectsCount) - { + if (searchRequest.quantityFrom > 0 && searchRequest.quantityFrom >= offerRootItem.upd.StackObjectsCount) { // too little items to offer return false; } - if (searchRequest.quantityTo > 0 && searchRequest.quantityTo <= offerRootItem.upd.StackObjectsCount) - { + if (searchRequest.quantityTo > 0 && searchRequest.quantityTo <= offerRootItem.upd.StackObjectsCount) { // too many items to offer return false; } - if (searchRequest.onlyFunctional && !this.isItemFunctional(offerRootItem, offer)) - { + if (searchRequest.onlyFunctional && !this.isItemFunctional(offerRootItem, offer)) { // don't include non-functional items return false; } - if (offer.items.length === 1) - { + if (offer.items.length === 1) { // Single item if ( - this.isConditionItem(offerRootItem) - && !this.itemQualityInRange(offerRootItem, searchRequest.conditionFrom, searchRequest.conditionTo) - ) - { + this.isConditionItem(offerRootItem) && + !this.itemQualityInRange(offerRootItem, searchRequest.conditionFrom, searchRequest.conditionTo) + ) { return false; } - } - else - { + } else { const itemQualityPercent = this.itemHelper.getItemQualityModifierForItems(offer.items) * 100; - if (itemQualityPercent < searchRequest.conditionFrom) - { + if (itemQualityPercent < searchRequest.conditionFrom) { return false; } - if (itemQualityPercent > searchRequest.conditionTo) - { + if (itemQualityPercent > searchRequest.conditionTo) { return false; } } - if (searchRequest.currency > 0 && this.paymentHelper.isMoneyTpl(moneyTypeTpl)) - { + if (searchRequest.currency > 0 && this.paymentHelper.isMoneyTpl(moneyTypeTpl)) { const currencies = ["all", "RUB", "USD", "EUR"]; - if (this.ragfairHelper.getCurrencyTag(moneyTypeTpl) !== currencies[searchRequest.currency]) - { + if (this.ragfairHelper.getCurrencyTag(moneyTypeTpl) !== currencies[searchRequest.currency]) { // don't include item paid in wrong currency return false; } } - if (searchRequest.priceFrom > 0 && searchRequest.priceFrom >= offer.requirementsCost) - { + if (searchRequest.priceFrom > 0 && searchRequest.priceFrom >= offer.requirementsCost) { // price is too low return false; } - if (searchRequest.priceTo > 0 && searchRequest.priceTo <= offer.requirementsCost) - { + if (searchRequest.priceTo > 0 && searchRequest.priceTo <= offer.requirementsCost) { // price is too high return false; } @@ -668,17 +598,14 @@ export class RagfairOfferHelper * @param offer The flea offer * @returns True if the given item is functional */ - public isItemFunctional(offerRootItem: Item, offer: IRagfairOffer): boolean - { + public isItemFunctional(offerRootItem: Item, offer: IRagfairOffer): boolean { // Non-presets are always functional - if (!this.presetHelper.hasPreset(offerRootItem._tpl)) - { + if (!this.presetHelper.hasPreset(offerRootItem._tpl)) { return true; } // For armor items that can hold mods, make sure the item count is atleast the amount of required plates - if (this.itemHelper.armorItemCanHoldMods(offerRootItem._tpl)) - { + if (this.itemHelper.armorItemCanHoldMods(offerRootItem._tpl)) { const offerRootTemplate = this.itemHelper.getItem(offerRootItem._tpl)[1]; const requiredPlateCount = offerRootTemplate._props.Slots?.filter((item) => item._required)?.length; @@ -705,54 +632,47 @@ export class RagfairOfferHelper offer: IRagfairOffer, pmcProfile: IPmcData, playerIsFleaBanned?: boolean, - ): boolean - { + ): boolean { const offerRootItem = offer.items[0]; /** Currency offer is sold for */ const moneyTypeTpl = offer.requirements[0]._tpl; const isTraderOffer = offer.user.id in this.databaseService.getTraders(); - if (!isTraderOffer && playerIsFleaBanned) - { + if (!isTraderOffer && playerIsFleaBanned) { return false; } // Offer root items tpl not in searched for array - if (!itemsToAdd?.includes(offerRootItem._tpl)) - { + if (!itemsToAdd?.includes(offerRootItem._tpl)) { // skip items we shouldn't include return false; } // Performing a required search and offer doesn't have requirement for item if ( - searchRequest.neededSearchId - && !offer.requirements.some((requirement) => requirement._tpl === searchRequest.neededSearchId) - ) - { + searchRequest.neededSearchId && + !offer.requirements.some((requirement) => requirement._tpl === searchRequest.neededSearchId) + ) { return false; } // Weapon/equipment search + offer is preset if ( - Object.keys(searchRequest.buildItems).length === 0 // Prevent equipment loadout searches filtering out presets - && searchRequest.buildCount - && this.presetHelper.hasPreset(offerRootItem._tpl) - ) - { + Object.keys(searchRequest.buildItems).length === 0 && // Prevent equipment loadout searches filtering out presets + searchRequest.buildCount && + this.presetHelper.hasPreset(offerRootItem._tpl) + ) { return false; } // commented out as required search "which is for checking offers that are barters" // has info.removeBartering as true, this if statement removed barter items. - if (searchRequest.removeBartering && !this.paymentHelper.isMoneyTpl(moneyTypeTpl)) - { + if (searchRequest.removeBartering && !this.paymentHelper.isMoneyTpl(moneyTypeTpl)) { // don't include barter offers return false; } - if (Number.isNaN(offer.requirementsCost)) - { + if (Number.isNaN(offer.requirementsCost)) { // don't include offers with undefined or NaN in it return false; } @@ -760,21 +680,17 @@ export class RagfairOfferHelper // Handle trader items to remove items that are not available to the user right now // required search for "lamp" shows 4 items, 3 of which are not available to a new player // filter those out - if (isTraderOffer) - { - if (!(offer.user.id in traderAssorts)) - { + if (isTraderOffer) { + if (!(offer.user.id in traderAssorts)) { // trader not visible on flea market return false; } if ( - !traderAssorts[offer.user.id].items.some((item) => - { + !traderAssorts[offer.user.id].items.some((item) => { return item._id === offer.root; }) - ) - { + ) { // skip (quest) locked items return false; } @@ -783,10 +699,8 @@ export class RagfairOfferHelper return true; } - public isDisplayableOfferThatNeedsItem(searchRequest: ISearchRequestData, offer: IRagfairOffer): boolean - { - if (offer.requirements.some((requirement) => requirement._tpl === searchRequest.neededSearchId)) - { + public isDisplayableOfferThatNeedsItem(searchRequest: ISearchRequestData, offer: IRagfairOffer): boolean { + if (offer.requirements.some((requirement) => requirement._tpl === searchRequest.neededSearchId)) { return true; } @@ -798,16 +712,15 @@ export class RagfairOfferHelper * @param item Item to check * @returns True if has condition */ - protected isConditionItem(item: Item): boolean - { + protected isConditionItem(item: Item): boolean { // thanks typescript, undefined assertion is not returnable since it // tries to return a multitype object - return item.upd.MedKit - || item.upd.Repairable - || item.upd.Resource - || item.upd.FoodDrink - || item.upd.Key - || item.upd.RepairKit + return item.upd.MedKit || + item.upd.Repairable || + item.upd.Resource || + item.upd.FoodDrink || + item.upd.Key || + item.upd.RepairKit ? true : false; } @@ -819,17 +732,14 @@ export class RagfairOfferHelper * @param max Desired maximum quality * @returns True if in range */ - protected itemQualityInRange(item: Item, min: number, max: number): boolean - { + protected itemQualityInRange(item: Item, min: number, max: number): boolean { const itemQualityPercentage = 100 * this.itemHelper.getItemQualityModifier(item); - if (min > 0 && min > itemQualityPercentage) - { + if (min > 0 && min > itemQualityPercentage) { // Item condition too low return false; } - if (max < 100 && max <= itemQualityPercentage) - { + if (max < 100 && max <= itemQualityPercentage) { // Item condition too high return false; } diff --git a/project/src/helpers/RagfairSellHelper.ts b/project/src/helpers/RagfairSellHelper.ts index 0364df32..778fc9ff 100644 --- a/project/src/helpers/RagfairSellHelper.ts +++ b/project/src/helpers/RagfairSellHelper.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { SellResult } from "@spt/models/eft/ragfair/IRagfairOffer"; import { ConfigTypes } from "@spt/models/enums/ConfigTypes"; import { IRagfairConfig } from "@spt/models/spt/config/IRagfairConfig"; @@ -7,10 +6,10 @@ import { ConfigServer } from "@spt/servers/ConfigServer"; import { DatabaseService } from "@spt/services/DatabaseService"; import { RandomUtil } from "@spt/utils/RandomUtil"; import { TimeUtil } from "@spt/utils/TimeUtil"; +import { inject, injectable } from "tsyringe"; @injectable() -export class RagfairSellHelper -{ +export class RagfairSellHelper { protected ragfairConfig: IRagfairConfig; constructor( @@ -19,8 +18,7 @@ export class RagfairSellHelper @inject("TimeUtil") protected timeUtil: TimeUtil, @inject("DatabaseService") protected databaseService: DatabaseService, @inject("ConfigServer") protected configServer: ConfigServer, - ) - { + ) { this.ragfairConfig = this.configServer.getConfig(ConfigTypes.RAGFAIR); } @@ -35,8 +33,7 @@ export class RagfairSellHelper averageOfferPriceRub: number, playerListedPriceRub: number, qualityMultiplier: number, - ): number - { + ): number { const sellConfig = this.ragfairConfig.sell.chance; // Base sell chance modified by items quality @@ -47,14 +44,12 @@ export class RagfairSellHelper let sellChance = Math.round(baseSellChancePercent * sellModifier * sellModifier ** 3 + 10); // Power of 3 // Adjust sell chance if below config value - if (sellChance < sellConfig.minSellChancePercent) - { + if (sellChance < sellConfig.minSellChancePercent) { sellChance = sellConfig.minSellChancePercent; } // Adjust sell chance if above config value - if (sellChance > sellConfig.maxSellChancePercent) - { + if (sellChance > sellConfig.maxSellChancePercent) { sellChance = sellConfig.maxSellChancePercent; } @@ -68,16 +63,13 @@ export class RagfairSellHelper * @param sellInOneGo All items listed get sold at once * @returns Array of purchases of item(s) listed */ - public rollForSale(sellChancePercent: number, itemSellCount: number, sellInOneGo = false): SellResult[] - { + public rollForSale(sellChancePercent: number, itemSellCount: number, sellInOneGo = false): SellResult[] { const startTime = this.timeUtil.getTimestamp(); // Get a time in future to stop simulating sell chances at - const endTime - = startTime - + this.timeUtil.getHoursAsSeconds( - this.databaseService.getGlobals().config.RagFair.offerDurationTimeInHour, - ); + const endTime = + startTime + + this.timeUtil.getHoursAsSeconds(this.databaseService.getGlobals().config.RagFair.offerDurationTimeInHour); let sellTime = startTime; let remainingCount = itemSellCount; @@ -87,8 +79,7 @@ export class RagfairSellHelper const effectiveSellChance = Number.isNaN(sellChancePercent) ? this.ragfairConfig.sell.chance.base : sellChancePercent; - if (Number.isNaN(sellChancePercent)) - { + if (Number.isNaN(sellChancePercent)) { this.logger.warning( `Sell chance was not a number: ${sellChancePercent}, defaulting to ${this.ragfairConfig.sell.chance.base}%`, ); @@ -97,31 +88,24 @@ export class RagfairSellHelper this.logger.debug(`Rolling to sell: ${itemSellCount} items (chance: ${effectiveSellChance}%)`); // No point rolling for a sale on a 0% chance item, exit early - if (effectiveSellChance === 0) - { + if (effectiveSellChance === 0) { return result; } - while (remainingCount > 0 && sellTime < endTime) - { - const boughtAmount = (sellInOneGo) - ? remainingCount - : this.randomUtil.getInt(1, remainingCount); - if (this.randomUtil.getChance100(effectiveSellChance)) - { + while (remainingCount > 0 && sellTime < endTime) { + const boughtAmount = sellInOneGo ? remainingCount : this.randomUtil.getInt(1, remainingCount); + if (this.randomUtil.getChance100(effectiveSellChance)) { // Passed roll check, item will be sold // Weight time to sell towards selling faster based on how cheap the item sold const weighting = (100 - effectiveSellChance) / 100; let maximumTime = weighting * (this.ragfairConfig.sell.time.max * 60); const minimumTime = this.ragfairConfig.sell.time.min * 60; - if (maximumTime < minimumTime) - { + if (maximumTime < minimumTime) { maximumTime = minimumTime + 5; } // Sell time will be random between min/max let newSellTime = Math.floor(Math.random() * (maximumTime - minimumTime) + minimumTime); - if (newSellTime === 0) - { + if (newSellTime === 0) { // Ensure all sales dont occur the same exact time newSellTime += 1; } @@ -129,10 +113,10 @@ export class RagfairSellHelper result.push({ sellTime: sellTime, amount: boughtAmount }); - this.logger.debug(`Offer will sell at: ${new Date(sellTime * 1000).toLocaleTimeString("en-US")}, bought: ${boughtAmount}`); - } - else - { + this.logger.debug( + `Offer will sell at: ${new Date(sellTime * 1000).toLocaleTimeString("en-US")}, bought: ${boughtAmount}`, + ); + } else { this.logger.debug(`Offer rolled not to sell, item count: ${boughtAmount}`); } diff --git a/project/src/helpers/RagfairServerHelper.ts b/project/src/helpers/RagfairServerHelper.ts index 40044f41..376e7da2 100644 --- a/project/src/helpers/RagfairServerHelper.ts +++ b/project/src/helpers/RagfairServerHelper.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { ItemHelper } from "@spt/helpers/ItemHelper"; import { ProfileHelper } from "@spt/helpers/ProfileHelper"; import { TraderHelper } from "@spt/helpers/TraderHelper"; @@ -17,16 +16,16 @@ import { DatabaseService } from "@spt/services/DatabaseService"; import { ItemFilterService } from "@spt/services/ItemFilterService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { MailSendService } from "@spt/services/MailSendService"; -import { ICloner } from "@spt/utils/cloners/ICloner"; import { RandomUtil } from "@spt/utils/RandomUtil"; import { TimeUtil } from "@spt/utils/TimeUtil"; +import { ICloner } from "@spt/utils/cloners/ICloner"; +import { inject, injectable } from "tsyringe"; /** * Helper class for common ragfair server actions */ @injectable() -export class RagfairServerHelper -{ +export class RagfairServerHelper { protected ragfairConfig: IRagfairConfig; protected questConfig: IQuestConfig; protected static goodsReturnedTemplate = "5bdabfe486f7743e1665df6e 0"; // Your item was not sold @@ -45,8 +44,7 @@ export class RagfairServerHelper @inject("ItemFilterService") protected itemFilterService: ItemFilterService, @inject("ConfigServer") protected configServer: ConfigServer, @inject("PrimaryCloner") protected cloner: ICloner, - ) - { + ) { this.ragfairConfig = this.configServer.getConfig(ConfigTypes.RAGFAIR); this.questConfig = this.configServer.getConfig(ConfigTypes.QUEST); } @@ -56,56 +54,48 @@ export class RagfairServerHelper * @param itemDetails * @returns boolean */ - public isItemValidRagfairItem(itemDetails: [boolean, ITemplateItem]): boolean - { + public isItemValidRagfairItem(itemDetails: [boolean, ITemplateItem]): boolean { const blacklistConfig = this.ragfairConfig.dynamic.blacklist; // Skip invalid items - if (!itemDetails[0]) - { + if (!itemDetails[0]) { return false; } // Skip blacklisted items - if (this.itemFilterService.isItemBlacklisted(itemDetails[1]._id)) - { + if (this.itemFilterService.isItemBlacklisted(itemDetails[1]._id)) { return false; } // Skip bsg blacklisted items - if (blacklistConfig.enableBsgList && !itemDetails[1]._props.CanSellOnRagfair) - { + if (blacklistConfig.enableBsgList && !itemDetails[1]._props.CanSellOnRagfair) { return false; } // Skip custom blacklisted items - if (this.isItemOnCustomFleaBlacklist(itemDetails[1]._id)) - { + if (this.isItemOnCustomFleaBlacklist(itemDetails[1]._id)) { return false; } // Skip custom category blacklisted items if ( - blacklistConfig.enableCustomItemCategoryList - && this.isItemCategoryOnCustomFleaBlacklist(itemDetails[1]._parent) - ) - { + blacklistConfig.enableCustomItemCategoryList && + this.isItemCategoryOnCustomFleaBlacklist(itemDetails[1]._parent) + ) { return false; } // Skip quest items - if (blacklistConfig.enableQuestList && this.itemHelper.isQuestItem(itemDetails[1]._id)) - { + if (blacklistConfig.enableQuestList && this.itemHelper.isQuestItem(itemDetails[1]._id)) { return false; } // Don't include damaged ammo packs if ( - this.ragfairConfig.dynamic.blacklist.damagedAmmoPacks - && itemDetails[1]._parent === BaseClasses.AMMO_BOX - && itemDetails[1]._name.includes("_damaged") - ) - { + this.ragfairConfig.dynamic.blacklist.damagedAmmoPacks && + itemDetails[1]._parent === BaseClasses.AMMO_BOX && + itemDetails[1]._name.includes("_damaged") + ) { return false; } @@ -117,10 +107,8 @@ export class RagfairServerHelper * @param itemTemplateId Item tpl to check is blacklisted * @returns True if its blacklsited */ - protected isItemOnCustomFleaBlacklist(itemTemplateId: string): boolean - { - if (!this.itemHelper.isValidItem(itemTemplateId)) - { + protected isItemOnCustomFleaBlacklist(itemTemplateId: string): boolean { + if (!this.itemHelper.isValidItem(itemTemplateId)) { return true; } @@ -132,8 +120,7 @@ export class RagfairServerHelper * @param parentId Parent Id to check is blacklisted * @returns true if blacklisted */ - protected isItemCategoryOnCustomFleaBlacklist(itemParentId: string): boolean - { + protected isItemCategoryOnCustomFleaBlacklist(itemParentId: string): boolean { return this.ragfairConfig.dynamic.blacklist.customItemCategoryList.includes(itemParentId); } @@ -142,8 +129,7 @@ export class RagfairServerHelper * @param traderId * @returns True if id was a trader */ - public isTrader(traderId: string): boolean - { + public isTrader(traderId: string): boolean { return traderId in this.databaseService.getTraders(); } @@ -152,8 +138,7 @@ export class RagfairServerHelper * @param sessionID Player to send items to * @param returnedItems Items to send to player */ - public returnItems(sessionID: string, returnedItems: Item[]): void - { + public returnItems(sessionID: string, returnedItems: Item[]): void { this.mailSendService.sendLocalisedNpcMessageToPlayer( sessionID, this.traderHelper.getTraderById(Traders.RAGMAN), @@ -166,23 +151,25 @@ export class RagfairServerHelper ); } - public calculateDynamicStackCount(tplId: string, isWeaponPreset: boolean): number - { + public calculateDynamicStackCount(tplId: string, isWeaponPreset: boolean): number { const config = this.ragfairConfig.dynamic; // Lookup item details - check if item not found const itemDetails = this.itemHelper.getItem(tplId); - if (!itemDetails[0]) - { - throw new Error(this.localisationService.getText("ragfair-item_not_in_db_unable_to_generate_dynamic_stack_count", tplId)); + if (!itemDetails[0]) { + throw new Error( + this.localisationService.getText( + "ragfair-item_not_in_db_unable_to_generate_dynamic_stack_count", + tplId, + ), + ); } // Item Types to return one of if ( - isWeaponPreset - || this.itemHelper.isOfBaseclasses(itemDetails[1]._id, this.ragfairConfig.dynamic.showAsSingleStack) - ) - { + isWeaponPreset || + this.itemHelper.isOfBaseclasses(itemDetails[1]._id, this.ragfairConfig.dynamic.showAsSingleStack) + ) { return 1; } @@ -190,8 +177,7 @@ export class RagfairServerHelper const maxStackCount = itemDetails[1]._props.StackMaxSize; // non-stackable - use different values to calculate stack size - if (!maxStackCount || maxStackCount === 1) - { + if (!maxStackCount || maxStackCount === 1) { return Math.round(this.randomUtil.getInt(config.nonStackableCount.min, config.nonStackableCount.max)); } @@ -206,15 +192,12 @@ export class RagfairServerHelper * Choose a currency at random with bias * @returns currency tpl */ - public getDynamicOfferCurrency(): string - { + public getDynamicOfferCurrency(): string { const currencies = this.ragfairConfig.dynamic.currencies; const bias: string[] = []; - for (const item in currencies) - { - for (let i = 0; i < currencies[item]; i++) - { + for (const item in currencies) { + for (let i = 0; i < currencies[item]; i++) { bias.push(item); } } @@ -227,8 +210,7 @@ export class RagfairServerHelper * @param item Preset item * @returns Array of weapon and its children */ - public getPresetItems(item: Item): Item[] - { + public getPresetItems(item: Item): Item[] { const preset = this.cloner.clone(this.databaseService.getGlobals().ItemPresets[item._id]._items); return this.itemHelper.reparentItemAndChildren(item, preset); } @@ -238,16 +220,11 @@ export class RagfairServerHelper * @param item Preset item * @returns */ - public getPresetItemsByTpl(item: Item): Item[] - { + public getPresetItemsByTpl(item: Item): Item[] { const presets = []; - for (const itemId in this.databaseService.getGlobals().ItemPresets) - { - if (this.databaseService.getGlobals().ItemPresets[itemId]._items[0]._tpl === item._tpl) - { - const presetItems = this.cloner.clone( - this.databaseService.getGlobals().ItemPresets[itemId]._items, - ); + for (const itemId in this.databaseService.getGlobals().ItemPresets) { + if (this.databaseService.getGlobals().ItemPresets[itemId]._items[0]._tpl === item._tpl) { + const presetItems = this.cloner.clone(this.databaseService.getGlobals().ItemPresets[itemId]._items); presets.push(this.itemHelper.reparentItemAndChildren(item, presetItems)); } } diff --git a/project/src/helpers/RagfairSortHelper.ts b/project/src/helpers/RagfairSortHelper.ts index 10272e75..a30670bb 100644 --- a/project/src/helpers/RagfairSortHelper.ts +++ b/project/src/helpers/RagfairSortHelper.ts @@ -1,18 +1,16 @@ -import { inject, injectable } from "tsyringe"; import { IRagfairOffer } from "@spt/models/eft/ragfair/IRagfairOffer"; import { Money } from "@spt/models/enums/Money"; import { RagfairSort } from "@spt/models/enums/RagfairSort"; import { DatabaseServer } from "@spt/servers/DatabaseServer"; import { LocaleService } from "@spt/services/LocaleService"; +import { inject, injectable } from "tsyringe"; @injectable() -export class RagfairSortHelper -{ +export class RagfairSortHelper { constructor( @inject("DatabaseServer") protected databaseServer: DatabaseServer, @inject("LocaleService") protected localeService: LocaleService, - ) - {} + ) {} /** * Sort a list of ragfair offers by something (id/rating/offer name/price/expiry time) @@ -21,11 +19,9 @@ export class RagfairSortHelper * @param direction Ascending/descending * @returns Sorted offers */ - public sortOffers(offers: IRagfairOffer[], type: RagfairSort, direction = 0): IRagfairOffer[] - { + public sortOffers(offers: IRagfairOffer[], type: RagfairSort, direction = 0): IRagfairOffer[] { // Sort results - switch (type) - { + switch (type) { case RagfairSort.ID: offers.sort(this.sortOffersByID); break; @@ -52,34 +48,29 @@ export class RagfairSortHelper } // 0=ASC 1=DESC - if (direction === 1) - { + if (direction === 1) { offers.reverse(); } return offers; } - protected sortOffersByID(a: IRagfairOffer, b: IRagfairOffer): number - { + protected sortOffersByID(a: IRagfairOffer, b: IRagfairOffer): number { return a.intId - b.intId; } - protected sortOffersByBarter(a: IRagfairOffer, b: IRagfairOffer): number - { + protected sortOffersByBarter(a: IRagfairOffer, b: IRagfairOffer): number { const moneyTpls = Object.values(Money); const aIsOnlyMoney = a.requirements.length == 1 && moneyTpls.includes(a.requirements[0]._tpl) ? 1 : 0; const bIsOnlyMoney = b.requirements.length == 1 && moneyTpls.includes(b.requirements[0]._tpl) ? 1 : 0; return aIsOnlyMoney - bIsOnlyMoney; } - protected sortOffersByRating(a: IRagfairOffer, b: IRagfairOffer): number - { + protected sortOffersByRating(a: IRagfairOffer, b: IRagfairOffer): number { return a.user.rating - b.user.rating; } - protected sortOffersByName(a: IRagfairOffer, b: IRagfairOffer): number - { + protected sortOffersByName(a: IRagfairOffer, b: IRagfairOffer): number { const locale = this.localeService.getLocaleDb(); const tplA = a.items[0]._tpl; @@ -96,13 +87,11 @@ export class RagfairSortHelper * @param b Offer b * @returns */ - protected sortOffersByPrice(a: IRagfairOffer, b: IRagfairOffer): number - { + protected sortOffersByPrice(a: IRagfairOffer, b: IRagfairOffer): number { return a.requirementsCost - b.requirementsCost; } - protected sortOffersByExpiry(a: IRagfairOffer, b: IRagfairOffer): number - { + protected sortOffersByExpiry(a: IRagfairOffer, b: IRagfairOffer): number { return a.endTime - b.endTime; } } diff --git a/project/src/helpers/RepairHelper.ts b/project/src/helpers/RepairHelper.ts index e2911b45..e7b3256d 100644 --- a/project/src/helpers/RepairHelper.ts +++ b/project/src/helpers/RepairHelper.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { Item } from "@spt/models/eft/common/tables/IItem"; import { ITemplateItem, Props } from "@spt/models/eft/common/tables/ITemplateItem"; import { ConfigTypes } from "@spt/models/enums/ConfigTypes"; @@ -6,12 +5,12 @@ import { IRepairConfig } from "@spt/models/spt/config/IRepairConfig"; import { ILogger } from "@spt/models/spt/utils/ILogger"; import { ConfigServer } from "@spt/servers/ConfigServer"; import { DatabaseService } from "@spt/services/DatabaseService"; -import { ICloner } from "@spt/utils/cloners/ICloner"; import { RandomUtil } from "@spt/utils/RandomUtil"; +import { ICloner } from "@spt/utils/cloners/ICloner"; +import { inject, injectable } from "tsyringe"; @injectable() -export class RepairHelper -{ +export class RepairHelper { protected repairConfig: IRepairConfig; constructor( @@ -20,8 +19,7 @@ export class RepairHelper @inject("DatabaseService") protected databaseService: DatabaseService, @inject("ConfigServer") protected configServer: ConfigServer, @inject("PrimaryCloner") protected cloner: ICloner, - ) - { + ) { this.repairConfig = this.configServer.getConfig(ConfigTypes.REPAIR); } @@ -43,8 +41,7 @@ export class RepairHelper useRepairKit: boolean, traderQualityMultipler: number, applyMaxDurabilityDegradation = true, - ): void - { + ): void { this.logger.debug(`Adding ${amountToRepair} to ${itemToRepairDetails._name} using kit: ${useRepairKit}`); const itemMaxDurability = this.cloner.clone(itemToRepair.upd.Repairable.MaxDurability); @@ -55,14 +52,12 @@ export class RepairHelper let newCurrentMaxDurability = itemCurrentMaxDurability + amountToRepair; // Ensure new max isnt above items max - if (newCurrentMaxDurability > itemMaxDurability) - { + if (newCurrentMaxDurability > itemMaxDurability) { newCurrentMaxDurability = itemMaxDurability; } // Ensure new current isnt above items max - if (newCurrentDurability > itemMaxDurability) - { + if (newCurrentDurability > itemMaxDurability) { newCurrentDurability = itemMaxDurability; } @@ -71,35 +66,32 @@ export class RepairHelper // when modders set the repair coefficient to 0 it means that they dont want to lose durability on items // the code below generates a random degradation on the weapon durability - if (applyMaxDurabilityDegradation) - { + if (applyMaxDurabilityDegradation) { const randomisedWearAmount = isArmor ? this.getRandomisedArmorRepairDegradationValue( - itemToRepairDetails._props.ArmorMaterial, - useRepairKit, - itemCurrentMaxDurability, - traderQualityMultipler, - ) + itemToRepairDetails._props.ArmorMaterial, + useRepairKit, + itemCurrentMaxDurability, + traderQualityMultipler, + ) : this.getRandomisedWeaponRepairDegradationValue( - itemToRepairDetails._props, - useRepairKit, - itemCurrentMaxDurability, - traderQualityMultipler, - ); + itemToRepairDetails._props, + useRepairKit, + itemCurrentMaxDurability, + traderQualityMultipler, + ); // Apply wear to durability itemToRepair.upd.Repairable.MaxDurability -= randomisedWearAmount; // After adjusting max durability with degradation, ensure current dura isnt above max - if (itemToRepair.upd.Repairable.Durability > itemToRepair.upd.Repairable.MaxDurability) - { + if (itemToRepair.upd.Repairable.Durability > itemToRepair.upd.Repairable.MaxDurability) { itemToRepair.upd.Repairable.Durability = itemToRepair.upd.Repairable.MaxDurability; } } // Repair mask cracks - if (itemToRepair.upd.FaceShield && itemToRepair.upd.FaceShield?.Hits > 0) - { + if (itemToRepair.upd.FaceShield && itemToRepair.upd.FaceShield?.Hits > 0) { itemToRepair.upd.FaceShield.Hits = 0; } } @@ -117,8 +109,7 @@ export class RepairHelper isRepairKit: boolean, armorMax: number, traderQualityMultipler: number, - ): number - { + ): number { // Degradation value is based on the armor material const armorMaterialSettings = this.databaseService.getGlobals().config.ArmorMaterials[armorMaterial]; @@ -149,14 +140,12 @@ export class RepairHelper isRepairKit: boolean, weaponMax: number, traderQualityMultipler: number, - ): number - { + ): number { const minRepairDeg = isRepairKit ? itemProps.MinRepairKitDegradation : itemProps.MinRepairDegradation; let maxRepairDeg = isRepairKit ? itemProps.MaxRepairKitDegradation : itemProps.MaxRepairDegradation; // WORKAROUND: Some items are always 0 when repairkit is true - if (maxRepairDeg === 0) - { + if (maxRepairDeg === 0) { maxRepairDeg = itemProps.MaxRepairDegradation; } diff --git a/project/src/helpers/RepeatableQuestHelper.ts b/project/src/helpers/RepeatableQuestHelper.ts index e5e143ca..61601aa2 100644 --- a/project/src/helpers/RepeatableQuestHelper.ts +++ b/project/src/helpers/RepeatableQuestHelper.ts @@ -1,22 +1,20 @@ -import { inject, injectable } from "tsyringe"; import { ConfigTypes } from "@spt/models/enums/ConfigTypes"; import { IEliminationConfig, IQuestConfig, IRepeatableQuestConfig } from "@spt/models/spt/config/IQuestConfig"; import { ConfigServer } from "@spt/servers/ConfigServer"; -import { ICloner } from "@spt/utils/cloners/ICloner"; import { MathUtil } from "@spt/utils/MathUtil"; import { ProbabilityObject, ProbabilityObjectArray } from "@spt/utils/RandomUtil"; +import { ICloner } from "@spt/utils/cloners/ICloner"; +import { inject, injectable } from "tsyringe"; @injectable() -export class RepeatableQuestHelper -{ +export class RepeatableQuestHelper { protected questConfig: IQuestConfig; constructor( @inject("MathUtil") protected mathUtil: MathUtil, @inject("ConfigServer") protected configServer: ConfigServer, @inject("PrimaryCloner") protected cloner: ICloner, - ) - { + ) { this.questConfig = this.configServer.getConfig(ConfigTypes.QUEST); } @@ -29,19 +27,16 @@ export class RepeatableQuestHelper public getEliminationConfigByPmcLevel( pmcLevel: number, repeatableConfig: IRepeatableQuestConfig, - ): IEliminationConfig - { + ): IEliminationConfig { return repeatableConfig.questConfig.Elimination.find( (x) => pmcLevel >= x.levelRange.min && pmcLevel <= x.levelRange.max, ); } - public probabilityObjectArray(configArrayInput: ProbabilityObject[]): ProbabilityObjectArray - { + public probabilityObjectArray(configArrayInput: ProbabilityObject[]): ProbabilityObjectArray { const configArray = this.cloner.clone(configArrayInput); const probabilityArray = new ProbabilityObjectArray(this.mathUtil, this.cloner); - for (const configObject of configArray) - { + for (const configObject of configArray) { probabilityArray.push( new ProbabilityObject(configObject.key, configObject.relativeProbability, configObject.data), ); diff --git a/project/src/helpers/SecureContainerHelper.ts b/project/src/helpers/SecureContainerHelper.ts index f893d397..9a045f30 100644 --- a/project/src/helpers/SecureContainerHelper.ts +++ b/project/src/helpers/SecureContainerHelper.ts @@ -1,33 +1,28 @@ -import { inject, injectable } from "tsyringe"; import { ItemHelper } from "@spt/helpers/ItemHelper"; import { Item } from "@spt/models/eft/common/tables/IItem"; +import { inject, injectable } from "tsyringe"; -export interface OwnerInventoryItems -{ - from: Item[] - to: Item[] - sameInventory: boolean - isMail: boolean +export interface OwnerInventoryItems { + from: Item[]; + to: Item[]; + sameInventory: boolean; + isMail: boolean; } @injectable() -export class SecureContainerHelper -{ - constructor(@inject("ItemHelper") protected itemHelper: ItemHelper) - {} +export class SecureContainerHelper { + constructor(@inject("ItemHelper") protected itemHelper: ItemHelper) {} /** * Get an array of the item IDs (NOT tpls) inside a secure container * @param items Inventory items to look for secure container in * @returns Array of ids */ - public getSecureContainerItems(items: Item[]): string[] - { + public getSecureContainerItems(items: Item[]): string[] { const secureContainer = items.find((x) => x.slotId === "SecuredContainer"); // No container found, drop out - if (!secureContainer) - { + if (!secureContainer) { return []; } diff --git a/project/src/helpers/TradeHelper.ts b/project/src/helpers/TradeHelper.ts index 2e577bc0..c7c3ba82 100644 --- a/project/src/helpers/TradeHelper.ts +++ b/project/src/helpers/TradeHelper.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { InventoryHelper } from "@spt/helpers/InventoryHelper"; import { ItemHelper } from "@spt/helpers/ItemHelper"; import { TraderAssortHelper } from "@spt/helpers/TraderAssortHelper"; @@ -22,12 +21,12 @@ import { FenceService } from "@spt/services/FenceService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { PaymentService } from "@spt/services/PaymentService"; import { TraderPurchasePersisterService } from "@spt/services/TraderPurchasePersisterService"; -import { ICloner } from "@spt/utils/cloners/ICloner"; import { HttpResponseUtil } from "@spt/utils/HttpResponseUtil"; +import { ICloner } from "@spt/utils/cloners/ICloner"; +import { inject, injectable } from "tsyringe"; @injectable() -export class TradeHelper -{ +export class TradeHelper { protected traderConfig: ITraderConfig; protected inventoryConfig: IInventoryConfig; @@ -47,8 +46,7 @@ export class TradeHelper protected traderPurchasePersisterService: TraderPurchasePersisterService, @inject("ConfigServer") protected configServer: ConfigServer, @inject("PrimaryCloner") protected cloner: ICloner, - ) - { + ) { this.traderConfig = this.configServer.getConfig(ConfigTypes.TRADER); this.inventoryConfig = this.configServer.getConfig(ConfigTypes.INVENTORY); } @@ -68,14 +66,11 @@ export class TradeHelper sessionID: string, foundInRaid: boolean, output: IItemEventRouterResponse, - ): void - { + ): void { let offerItems: Item[] = []; let buyCallback: (buyCount: number) => void; - if (buyRequestData.tid.toLocaleLowerCase() === "ragfair") - { - buyCallback = (buyCount: number) => - { + if (buyRequestData.tid.toLocaleLowerCase() === "ragfair") { + buyCallback = (buyCount: number) => { const allOffers = this.ragfairServer.getOffers(); // We store ragfair offerid in buyRequestData.item_id @@ -84,8 +79,7 @@ export class TradeHelper // Ensure purchase does not exceed trader item limit const assortHasBuyRestrictions = this.itemHelper.hasBuyRestrictions(itemPurchased); - if (assortHasBuyRestrictions) - { + if (assortHasBuyRestrictions) { this.checkPurchaseIsWithinTraderItemLimit( sessionID, pmcData, @@ -108,11 +102,8 @@ export class TradeHelper const allOffers = this.ragfairServer.getOffers(); const offerWithItemCloned = this.cloner.clone(allOffers.find((x) => x._id === buyRequestData.item_id)); offerItems = offerWithItemCloned.items; - } - else if (buyRequestData.tid === Traders.FENCE) - { - buyCallback = (buyCount: number) => - { + } else if (buyRequestData.tid === Traders.FENCE) { + buyCallback = (buyCount: number) => { // Update assort/flea item values const traderAssorts = this.traderHelper.getTraderAssortsByTraderId(buyRequestData.tid).items; const itemPurchased = traderAssorts.find((assort) => assort._id === buyRequestData.item_id); @@ -125,8 +116,7 @@ export class TradeHelper const fenceItems = this.fenceService.getRawFenceAssorts().items; const rootItemIndex = fenceItems.findIndex((item) => item._id === buyRequestData.item_id); - if (rootItemIndex === -1) - { + if (rootItemIndex === -1) { this.logger.debug(`Tried to buy item ${buyRequestData.item_id} from fence that no longer exists`); const message = this.localisationService.getText("ragfair-offer_no_longer_exists"); this.httpResponse.appendErrorToOutput(output, message); @@ -135,20 +125,16 @@ export class TradeHelper } offerItems = this.itemHelper.findAndReturnChildrenAsItems(fenceItems, buyRequestData.item_id); - } - else - { + } else { // Non-fence trader - buyCallback = (buyCount: number) => - { + buyCallback = (buyCount: number) => { // Update assort/flea item values const traderAssorts = this.traderHelper.getTraderAssortsByTraderId(buyRequestData.tid).items; const itemPurchased = traderAssorts.find((item) => item._id === buyRequestData.item_id); // Ensure purchase does not exceed trader item limit const assortHasBuyRestrictions = this.itemHelper.hasBuyRestrictions(itemPurchased); - if (assortHasBuyRestrictions) - { + if (assortHasBuyRestrictions) { // Will throw error if check fails this.checkPurchaseIsWithinTraderItemLimit( sessionID, @@ -161,8 +147,7 @@ export class TradeHelper } // Check if trader has enough stock - if (itemPurchased.upd.StackObjectsCount < buyCount) - { + if (itemPurchased.upd.StackObjectsCount < buyCount) { throw new Error( `Unable to purchase ${buyCount} items, this would exceed the remaining stock left ${itemPurchased.upd.StackObjectsCount} from the traders assort: ${buyRequestData.tid} this refresh`, ); @@ -171,8 +156,7 @@ export class TradeHelper // Decrement trader item count itemPurchased.upd.StackObjectsCount -= buyCount; - if (assortHasBuyRestrictions) - { + if (assortHasBuyRestrictions) { const itemPurchaseDat = { items: [{ itemId: buyRequestData.item_id, count: buyCount }], traderId: buyRequestData.tid, @@ -186,9 +170,10 @@ export class TradeHelper // Get item + children for purchase const relevantItems = this.itemHelper.findAndReturnChildrenAsItems(traderItems, buyRequestData.item_id); - if (relevantItems.length === 0) - { - this.logger.error(`Purchased trader: ${buyRequestData.tid} offer: ${buyRequestData.item_id} has no items`); + if (relevantItems.length === 0) { + this.logger.error( + `Purchased trader: ${buyRequestData.tid} offer: ${buyRequestData.item_id} has no items`, + ); } offerItems.push(...relevantItems); } @@ -201,8 +186,7 @@ export class TradeHelper // Construct array of items to send to player const itemsToSendToPlayer: Item[][] = []; - while (itemsToSendRemaining > 0) - { + while (itemsToSendRemaining > 0) { const offerClone = this.cloner.clone(offerItems); // Handle stackable items that have a max stack size limit const itemCountToSend = Math.min(itemMaxStackSize, itemsToSendRemaining); @@ -210,8 +194,7 @@ export class TradeHelper // Prevent any collisions this.itemHelper.remapRootItemId(offerClone); - if (offerClone.length > 1) - { + if (offerClone.length > 1) { this.itemHelper.reparentItemAndChildren(offerClone[0], offerClone); } @@ -231,15 +214,13 @@ export class TradeHelper // Add items + their children to stash this.inventoryHelper.addItemsToStash(sessionID, request, pmcData, output); - if (output.warnings.length > 0) - { + if (output.warnings.length > 0) { return; } /// Pay for purchase this.paymentService.payMoney(pmcData, buyRequestData, sessionID, output); - if (output.warnings.length > 0) - { + if (output.warnings.length > 0) { const errorMessage = `Transaction failed: ${output.warnings[0].errmsg}`; this.httpResponse.appendErrorToOutput(output, errorMessage, BackendErrorCodes.UNKNOWN_TRADING_ERROR); } @@ -259,17 +240,14 @@ export class TradeHelper sellRequest: IProcessSellTradeRequestData, sessionID: string, output: IItemEventRouterResponse, - ): void - { + ): void { // Find item in inventory and remove it - for (const itemToBeRemoved of sellRequest.items) - { + for (const itemToBeRemoved of sellRequest.items) { const itemIdToFind = itemToBeRemoved.id.replace(/\s+/g, ""); // Strip out whitespace // Find item in player inventory, or show error to player if not found const matchingItemInInventory = profileWithItemsToSell.Inventory.items.find((x) => x._id === itemIdToFind); - if (!matchingItemInInventory) - { + if (!matchingItemInInventory) { const errorMessage = `Unable to sell item ${itemToBeRemoved.id}, cannot be found in player inventory`; this.logger.error(errorMessage); @@ -280,8 +258,7 @@ export class TradeHelper this.logger.debug(`Selling: id: ${matchingItemInInventory._id} tpl: ${matchingItemInInventory._tpl}`); - if (sellRequest.tid === Traders.FENCE) - { + if (sellRequest.tid === Traders.FENCE) { this.fenceService.addItemsToFenceAssort( profileWithItemsToSell.Inventory.items, matchingItemInInventory, @@ -312,20 +289,17 @@ export class TradeHelper assortBeingPurchased: Item, assortId: string, count: number, - ): void - { - const traderPurchaseData - = this.traderPurchasePersisterService.getProfileTraderPurchase( - sessionId, - traderId, - assortBeingPurchased._id, - ); - const traderItemPurchaseLimit - = this.traderHelper.getAccountTypeAdjustedTraderPurchaseLimit( - assortBeingPurchased.upd?.BuyRestrictionMax, - pmcData.Info.GameVersion); - if ((traderPurchaseData?.count ?? 0 + count) > traderItemPurchaseLimit) - { + ): void { + const traderPurchaseData = this.traderPurchasePersisterService.getProfileTraderPurchase( + sessionId, + traderId, + assortBeingPurchased._id, + ); + const traderItemPurchaseLimit = this.traderHelper.getAccountTypeAdjustedTraderPurchaseLimit( + assortBeingPurchased.upd?.BuyRestrictionMax, + pmcData.Info.GameVersion, + ); + if ((traderPurchaseData?.count ?? 0 + count) > traderItemPurchaseLimit) { throw new Error( `Unable to purchase: ${count} items, this would exceed your purchase limit of ${traderItemPurchaseLimit} from the trader: ${traderId} assort: ${assortId} this refresh`, ); diff --git a/project/src/helpers/TraderAssortHelper.ts b/project/src/helpers/TraderAssortHelper.ts index 15f8c4a7..3f3ecab7 100644 --- a/project/src/helpers/TraderAssortHelper.ts +++ b/project/src/helpers/TraderAssortHelper.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { RagfairAssortGenerator } from "@spt/generators/RagfairAssortGenerator"; import { RagfairOfferGenerator } from "@spt/generators/RagfairOfferGenerator"; import { AssortHelper } from "@spt/helpers/AssortHelper"; @@ -17,13 +16,13 @@ import { FenceService } from "@spt/services/FenceService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { TraderAssortService } from "@spt/services/TraderAssortService"; import { TraderPurchasePersisterService } from "@spt/services/TraderPurchasePersisterService"; -import { ICloner } from "@spt/utils/cloners/ICloner"; import { MathUtil } from "@spt/utils/MathUtil"; import { TimeUtil } from "@spt/utils/TimeUtil"; +import { ICloner } from "@spt/utils/cloners/ICloner"; +import { inject, injectable } from "tsyringe"; @injectable() -export class TraderAssortHelper -{ +export class TraderAssortHelper { protected traderConfig: ITraderConfig; protected mergedQuestAssorts: Record> = { started: {}, success: {}, fail: {} }; protected createdMergedQuestAssorts = false; @@ -46,8 +45,7 @@ export class TraderAssortHelper @inject("FenceService") protected fenceService: FenceService, @inject("ConfigServer") protected configServer: ConfigServer, @inject("PrimaryCloner") protected cloner: ICloner, - ) - { + ) { this.traderConfig = this.configServer.getConfig(ConfigTypes.TRADER); } @@ -60,11 +58,9 @@ export class TraderAssortHelper * @param flea Should assorts player hasn't unlocked be returned - default false * @returns a traders' assorts */ - public getAssort(sessionId: string, traderId: string, flea = false): ITraderAssort - { + public getAssort(sessionId: string, traderId: string, flea = false): ITraderAssort { // Special case for getting ragfair items as they're dynamically generated - if (traderId === "ragfair") - { + if (traderId === "ragfair") { return this.getRagfairDataAsTraderAssort(); } @@ -72,14 +68,12 @@ export class TraderAssortHelper const fullProfile = this.profileHelper.getFullProfile(sessionId); const pmcProfile = fullProfile.characters.pmc; - if (traderId === Traders.FENCE) - { + if (traderId === Traders.FENCE) { return this.fenceService.getFenceAssorts(pmcProfile); } // Strip assorts player should not see yet - if (!flea) - { + if (!flea) { traderClone.assort = this.assortHelper.stripLockedLoyaltyAssort(pmcProfile, traderId, traderClone.assort); } @@ -93,12 +87,10 @@ export class TraderAssortHelper sessionId, traderId, ); - for (const assortId in assortPurchasesfromTrader) - { + for (const assortId in assortPurchasesfromTrader) { // Find assort we want to update current buy count of const assortToAdjust = traderClone.assort.items.find((x) => x._id === assortId); - if (!assortToAdjust) - { + if (!assortToAdjust) { this.logger.debug( `Cannot find trader: ${traderClone.base.nickname} assort: ${assortId} to adjust BuyRestrictionCurrent value, skipping`, ); @@ -106,8 +98,7 @@ export class TraderAssortHelper continue; } - if (!assortToAdjust.upd) - { + if (!assortToAdjust.upd) { this.logger.debug( `Unable to adjust assort ${assortToAdjust._id} item: ${assortToAdjust._tpl} BuyRestrictionCurrent value, assort has an undefined upd object`, ); @@ -119,8 +110,7 @@ export class TraderAssortHelper } // Get rid of quest locked assorts - if (!this.createdMergedQuestAssorts) - { + if (!this.createdMergedQuestAssorts) { this.hydrateMergedQuestAssorts(); this.createdMergedQuestAssorts = true; } @@ -133,14 +123,12 @@ export class TraderAssortHelper ); // Filter out root assorts that are blacklisted for this profile - if (fullProfile.spt.blacklistedItemTpls?.length > 0) - { + if (fullProfile.spt.blacklistedItemTpls?.length > 0) { this.removeItemsFromAssort(traderClone.assort, fullProfile.spt.blacklistedItemTpls); } // Multiply price if multiplier is other than 1 - if (this.traderConfig.traderPriceMultipler !== 1) - { + if (this.traderConfig.traderPriceMultipler !== 1) { this.multiplyItemPricesByConfigMultiplier(traderClone.assort); } @@ -152,13 +140,10 @@ export class TraderAssortHelper * @param assortToFilter Trader assort to modify * @param itemsTplsToRemove Item TPLs the assort should not have */ - protected removeItemsFromAssort(assortToFilter: ITraderAssort, itemsTplsToRemove: string[]): void - { - function isValid(item: Item, blacklist: string[]): boolean - { + protected removeItemsFromAssort(assortToFilter: ITraderAssort, itemsTplsToRemove: string[]): void { + function isValid(item: Item, blacklist: string[]): boolean { // Is root item + blacklisted - if (item.parentId === "hideout" && blacklist.includes(item._tpl)) - { + if (item.parentId === "hideout" && blacklist.includes(item._tpl)) { // We want it gone return false; } @@ -173,14 +158,11 @@ export class TraderAssortHelper * Reset every traders root item `BuyRestrictionCurrent` property to 0 * @param assortItems Items to adjust */ - protected resetBuyRestrictionCurrentValue(assortItems: Item[]): void - { + protected resetBuyRestrictionCurrentValue(assortItems: Item[]): void { // iterate over root items - for (const assort of assortItems.filter((item) => item.slotId === "hideout")) - { + for (const assort of assortItems.filter((item) => item.slotId === "hideout")) { // no value to adjust - if (!assort.upd.BuyRestrictionCurrent) - { + if (!assort.upd.BuyRestrictionCurrent) { continue; } @@ -191,25 +173,19 @@ export class TraderAssortHelper /** * Create a dict of all assort id = quest id mappings used to work out what items should be shown to player based on the quests they've started/completed/failed */ - protected hydrateMergedQuestAssorts(): void - { + protected hydrateMergedQuestAssorts(): void { // Loop every trader const traders = this.databaseService.getTraders(); - for (const traderId in traders) - { + for (const traderId in traders) { // Trader has quest assort data const trader = traders[traderId]; - if (trader.questassort) - { + if (trader.questassort) { // Started/Success/fail - for (const questStatus in trader.questassort) - { + for (const questStatus in trader.questassort) { // Each assort to quest id record - for (const assortId in trader.questassort[questStatus]) - { + for (const assortId in trader.questassort[questStatus]) { // Null guard - if (!this.mergedQuestAssorts[questStatus]) - { + if (!this.mergedQuestAssorts[questStatus]) { this.mergedQuestAssorts[questStatus] = {}; } @@ -225,8 +201,7 @@ export class TraderAssortHelper * Flag trader as needing a flea offer reset to be picked up by flea update() function * @param trader trader details to alter */ - public resetExpiredTrader(trader: ITrader): void - { + public resetExpiredTrader(trader: ITrader): void { trader.assort.items = this.getPristineTraderAssorts(trader.base._id); // Update resupply value to next timestamp @@ -241,8 +216,7 @@ export class TraderAssortHelper * @param traderID Trader to check * @returns true they need refreshing */ - public traderAssortsHaveExpired(traderID: string): boolean - { + public traderAssortsHaveExpired(traderID: string): boolean { const time = this.timeUtil.getTimestamp(); const trader = this.databaseService.getTables().traders![traderID]; @@ -253,19 +227,15 @@ export class TraderAssortHelper * Iterate over all assorts barter_scheme values, find barters selling for money and multiply by multipler in config * @param traderAssort Assorts to multiple price of */ - protected multiplyItemPricesByConfigMultiplier(traderAssort: ITraderAssort): void - { - if (!this.traderConfig.traderPriceMultipler || this.traderConfig.traderPriceMultipler <= 0) - { + protected multiplyItemPricesByConfigMultiplier(traderAssort: ITraderAssort): void { + if (!this.traderConfig.traderPriceMultipler || this.traderConfig.traderPriceMultipler <= 0) { this.traderConfig.traderPriceMultipler = 0.01; this.logger.warning(this.localisationService.getText("trader-price_multipler_is_zero_use_default")); } - for (const assortId in traderAssort.barter_scheme) - { + for (const assortId in traderAssort.barter_scheme) { const schemeDetails = traderAssort.barter_scheme[assortId][0]; - if (schemeDetails.length === 1 && this.paymentHelper.isMoneyTpl(schemeDetails[0]._tpl)) - { + if (schemeDetails.length === 1 && this.paymentHelper.isMoneyTpl(schemeDetails[0]._tpl)) { schemeDetails[0].count = Math.ceil(schemeDetails[0].count * this.traderConfig.traderPriceMultipler); } } @@ -276,8 +246,7 @@ export class TraderAssortHelper * @param traderId trader id * @returns array of Items */ - protected getPristineTraderAssorts(traderId: string): Item[] - { + protected getPristineTraderAssorts(traderId: string): Item[] { return this.cloner.clone(this.traderAssortService.getPristineTraderAssort(traderId).items); } @@ -285,8 +254,7 @@ export class TraderAssortHelper * Returns generated ragfair offers in a trader assort format * @returns Trader assort object */ - protected getRagfairDataAsTraderAssort(): ITraderAssort - { + protected getRagfairDataAsTraderAssort(): ITraderAssort { return { items: this.ragfairAssortGenerator.getAssortItems().flat(), barter_scheme: {}, diff --git a/project/src/helpers/TraderHelper.ts b/project/src/helpers/TraderHelper.ts index dbe27205..0afc309b 100644 --- a/project/src/helpers/TraderHelper.ts +++ b/project/src/helpers/TraderHelper.ts @@ -1,5 +1,4 @@ import { error } from "node:console"; -import { inject, injectable } from "tsyringe"; import { HandbookHelper } from "@spt/helpers/HandbookHelper"; import { ItemHelper } from "@spt/helpers/ItemHelper"; import { ProfileHelper } from "@spt/helpers/ProfileHelper"; @@ -22,10 +21,10 @@ import { LocalisationService } from "@spt/services/LocalisationService"; import { PlayerService } from "@spt/services/PlayerService"; import { RandomUtil } from "@spt/utils/RandomUtil"; import { TimeUtil } from "@spt/utils/TimeUtil"; +import { inject, injectable } from "tsyringe"; @injectable() -export class TraderHelper -{ +export class TraderHelper { protected traderConfig: ITraderConfig; /** Dictionary of item tpl and the highest trader sell rouble price */ protected highestTraderPriceItems?: Record = undefined; @@ -42,8 +41,7 @@ export class TraderHelper @inject("TimeUtil") protected timeUtil: TimeUtil, @inject("RandomUtil") protected randomUtil: RandomUtil, @inject("ConfigServer") protected configServer: ConfigServer, - ) - { + ) { this.traderConfig = this.configServer.getConfig(ConfigTypes.TRADER); } @@ -54,25 +52,21 @@ export class TraderHelper * @param sessionID Players id * @returns Trader base */ - public getTrader(traderID: string, sessionID: string): ITraderBase | undefined - { + public getTrader(traderID: string, sessionID: string): ITraderBase | undefined { const pmcData = this.profileHelper.getPmcProfile(sessionID); - if (!pmcData) - { + if (!pmcData) { throw new error(this.localisationService.getText("trader-unable_to_find_profile_with_id", sessionID)); } // Profile has traderInfo dict (profile beyond creation stage) but no requested trader in profile - if (pmcData.TradersInfo && !(traderID in pmcData.TradersInfo)) - { + if (pmcData.TradersInfo && !(traderID in pmcData.TradersInfo)) { // Add trader values to profile this.resetTrader(sessionID, traderID); this.lvlUp(traderID, pmcData); } const traderBase = this.databaseService.getTrader(traderID).base; - if (!traderBase) - { + if (!traderBase) { this.logger.error(this.localisationService.getText("trader-unable_to_find_trader_by_id", traderID)); } @@ -84,8 +78,7 @@ export class TraderHelper * @param traderId Trader to get assorts for * @returns ITraderAssort */ - public getTraderAssortsByTraderId(traderId: string): ITraderAssort - { + public getTraderAssortsByTraderId(traderId: string): ITraderAssort { return traderId === Traders.FENCE ? this.fenceService.getRawFenceAssorts() : this.databaseService.getTrader(traderId).assort; @@ -97,11 +90,9 @@ export class TraderHelper * @param assortId Id of assort to find * @returns Item object */ - public getTraderAssortItemByAssortId(traderId: string, assortId: string): Item | undefined - { + public getTraderAssortItemByAssortId(traderId: string, assortId: string): Item | undefined { const traderAssorts = this.getTraderAssortsByTraderId(traderId); - if (!traderAssorts) - { + if (!traderAssorts) { this.logger.debug(`No assorts on trader: ${traderId} found`); return undefined; @@ -109,8 +100,7 @@ export class TraderHelper // Find specific assort in traders data const purchasedAssort = traderAssorts.items.find((item) => item._id === assortId); - if (!purchasedAssort) - { + if (!purchasedAssort) { this.logger.debug(`No assort ${assortId} on trader: ${traderId} found`); return undefined; @@ -125,21 +115,18 @@ export class TraderHelper * @param sessionID session id of player * @param traderID trader id to reset */ - public resetTrader(sessionID: string, traderID: string): void - { + public resetTrader(sessionID: string, traderID: string): void { const profiles = this.databaseService.getProfiles(); const trader = this.databaseService.getTrader(traderID); const fullProfile = this.profileHelper.getFullProfile(sessionID); - if (!fullProfile) - { + if (!fullProfile) { throw new error(this.localisationService.getText("trader-unable_to_find_profile_by_id", sessionID)); } const pmcData = fullProfile.characters.pmc; - const rawProfileTemplate: ProfileTraderTemplate - = profiles[fullProfile.info.edition][pmcData.Info.Side.toLowerCase()] - .trader; + const rawProfileTemplate: ProfileTraderTemplate = + profiles[fullProfile.info.edition][pmcData.Info.Side.toLowerCase()].trader; pmcData.TradersInfo[traderID] = { disabled: false, @@ -151,42 +138,36 @@ export class TraderHelper }; // Check if trader should be locked by default - if (rawProfileTemplate.lockedByDefaultOverride?.includes(traderID)) - { + if (rawProfileTemplate.lockedByDefaultOverride?.includes(traderID)) { pmcData.TradersInfo[traderID].unlocked = true; } - if (rawProfileTemplate.purchaseAllClothingByDefaultForTrader?.includes(traderID)) - { + if (rawProfileTemplate.purchaseAllClothingByDefaultForTrader?.includes(traderID)) { // Get traders clothing const clothing = this.databaseService.getTrader(traderID).suits; - if (clothing?.length > 0) - { + if (clothing?.length > 0) { // Force suit ids into profile - this.addSuitsToProfile(fullProfile, clothing!.map((suit) => suit.suiteId)); + this.addSuitsToProfile( + fullProfile, + clothing!.map((suit) => suit.suiteId), + ); } } - if ((rawProfileTemplate.fleaBlockedDays ?? 0) > 0) - { + if ((rawProfileTemplate.fleaBlockedDays ?? 0) > 0) { const newBanDateTime = this.timeUtil.getTimeStampFromNowDays(rawProfileTemplate.fleaBlockedDays!); const existingBan = pmcData.Info.Bans.find((ban) => ban.banType === BanType.RAGFAIR); - if (existingBan) - { + if (existingBan) { existingBan.dateTime = newBanDateTime; - } - else - { - pmcData.Info.Bans.push( - { - banType: BanType.RAGFAIR, - dateTime: newBanDateTime, - }); + } else { + pmcData.Info.Bans.push({ + banType: BanType.RAGFAIR, + dateTime: newBanDateTime, + }); } } - if (traderID === Traders.JAEGER) - { + if (traderID === Traders.JAEGER) { pmcData.TradersInfo[traderID].unlocked = rawProfileTemplate.jaegerUnlocked; } } @@ -197,13 +178,11 @@ export class TraderHelper * @param rawProfileTemplate Raw profile from profiles.json to look up standing from * @returns Standing value */ - protected getStartingStanding(traderId: string, rawProfileTemplate: ProfileTraderTemplate): number - { - const initialStanding = rawProfileTemplate.initialStanding[traderId] - ?? rawProfileTemplate.initialStanding.default; + protected getStartingStanding(traderId: string, rawProfileTemplate: ProfileTraderTemplate): number { + const initialStanding = + rawProfileTemplate.initialStanding[traderId] ?? rawProfileTemplate.initialStanding.default; // Edge case for Lightkeeper, 0 standing means seeing `Make Amends - Buyout` quest - if (traderId === Traders.LIGHTHOUSEKEEPER && initialStanding === 0) - { + if (traderId === Traders.LIGHTHOUSEKEEPER && initialStanding === 0) { return 0.01; } @@ -215,18 +194,14 @@ export class TraderHelper * @param fullProfile Profile to add to * @param suitIds Suit Ids to add */ - protected addSuitsToProfile(fullProfile: ISptProfile, suitIds: string[]): void - { - if (!fullProfile.suits) - { + protected addSuitsToProfile(fullProfile: ISptProfile, suitIds: string[]): void { + if (!fullProfile.suits) { fullProfile.suits = []; } - for (const suitId of suitIds) - { + for (const suitId of suitIds) { // Don't add dupes - if (!fullProfile.suits.includes(suitId)) - { + if (!fullProfile.suits.includes(suitId)) { fullProfile.suits.push(suitId); } } @@ -238,8 +213,7 @@ export class TraderHelper * @param status New status to use * @param sessionId Session id of player */ - public setTraderUnlockedState(traderId: string, status: boolean, sessionId: string): void - { + public setTraderUnlockedState(traderId: string, status: boolean, sessionId: string): void { const pmcData = this.profileHelper.getPmcProfile(sessionId); pmcData.TradersInfo[traderId].unlocked = status; } @@ -250,16 +224,14 @@ export class TraderHelper * @param traderId Traders id to add standing to * @param standingToAdd Standing value to add to trader */ - public addStandingToTrader(sessionId: string, traderId: string, standingToAdd: number): void - { + public addStandingToTrader(sessionId: string, traderId: string, standingToAdd: number): void { const fullProfile = this.profileHelper.getFullProfile(sessionId); const pmcTraderInfo = fullProfile.characters.pmc.TradersInfo[traderId]; // Add standing to trader pmcTraderInfo.standing = this.addStandingValuesTogether(pmcTraderInfo.standing, standingToAdd); - if (traderId === Traders.FENCE) - { + if (traderId === Traders.FENCE) { // Must add rep to scav profile to ensure consistency fullProfile.characters.scav.TradersInfo[traderId].standing = pmcTraderInfo.standing; } @@ -273,8 +245,7 @@ export class TraderHelper * @param standingToAdd stansding to add to trader standing * @returns current standing + added standing (clamped if needed) */ - protected addStandingValuesTogether(currentStanding: number, standingToAdd: number): number - { + protected addStandingValuesTogether(currentStanding: number, standingToAdd: number): number { const newStanding = currentStanding + standingToAdd; // Never let standing fall below 0 @@ -285,12 +256,10 @@ export class TraderHelper * iterate over a profiles traders and ensure they have the correct loyaltyLevel for the player * @param sessionId Profile to check */ - public validateTraderStandingsAndPlayerLevelForProfile(sessionId: string): void - { + public validateTraderStandingsAndPlayerLevelForProfile(sessionId: string): void { const profile = this.profileHelper.getPmcProfile(sessionId); const traders = Object.keys(this.databaseService.getTraders()); - for (const trader of traders) - { + for (const trader of traders) { this.lvlUp(trader, profile); } } @@ -301,8 +270,7 @@ export class TraderHelper * @param traderID Trader to check standing of * @param pmcData Profile to update trader in */ - public lvlUp(traderID: string, pmcData: IPmcData): void - { + public lvlUp(traderID: string, pmcData: IPmcData): void { const loyaltyLevels = this.databaseService.getTrader(traderID).base.loyaltyLevels; // Level up player @@ -314,17 +282,15 @@ export class TraderHelper // Round standing to 2 decimal places to address floating point inaccuracies pmcData.TradersInfo[traderID].standing = Math.round(pmcData.TradersInfo[traderID].standing * 100) / 100; - for (const level in loyaltyLevels) - { + for (const level in loyaltyLevels) { const loyalty = loyaltyLevels[level]; if ( - loyalty.minLevel <= pmcData.Info.Level - && loyalty.minSalesSum <= pmcData.TradersInfo[traderID].salesSum - && loyalty.minStanding <= pmcData.TradersInfo[traderID].standing - && targetLevel < 4 - ) - { + loyalty.minLevel <= pmcData.Info.Level && + loyalty.minSalesSum <= pmcData.TradersInfo[traderID].salesSum && + loyalty.minStanding <= pmcData.TradersInfo[traderID].standing && + targetLevel < 4 + ) { // level reached targetLevel++; } @@ -339,8 +305,7 @@ export class TraderHelper * @param traderID Trader to look up update value for * @returns future timestamp */ - public getNextUpdateTimestamp(traderID: string): number - { + public getNextUpdateTimestamp(traderID: string): number { const time = this.timeUtil.getTimestamp(); const updateSeconds = this.getTraderUpdateSeconds(traderID) ?? 0; return time + updateSeconds; @@ -351,11 +316,9 @@ export class TraderHelper * @param traderId Trader to look up * @returns Time in seconds */ - public getTraderUpdateSeconds(traderId: string): number | undefined - { + public getTraderUpdateSeconds(traderId: string): number | undefined { const traderDetails = this.traderConfig.updateTime.find((x) => x.traderId === traderId); - if (!traderDetails || traderDetails.seconds.min === undefined || traderDetails.seconds.max === undefined) - { + if (!traderDetails || traderDetails.seconds.min === undefined || traderDetails.seconds.max === undefined) { this.logger.warning( this.localisationService.getText("trader-missing_trader_details_using_default_refresh_time", { traderId: traderId, @@ -371,25 +334,20 @@ export class TraderHelper }, ); return undefined; - } - else - { + } else { return this.randomUtil.getInt(traderDetails.seconds.min, traderDetails.seconds.max); } } - public getLoyaltyLevel(traderID: string, pmcData: IPmcData): LoyaltyLevel - { + public getLoyaltyLevel(traderID: string, pmcData: IPmcData): LoyaltyLevel { const traderBase = this.databaseService.getTrader(traderID).base; let loyaltyLevel = pmcData.TradersInfo[traderID].loyaltyLevel; - if (!loyaltyLevel || loyaltyLevel < 1) - { + if (!loyaltyLevel || loyaltyLevel < 1) { loyaltyLevel = 1; } - if (loyaltyLevel > traderBase.loyaltyLevels.length) - { + if (loyaltyLevel > traderBase.loyaltyLevels.length) { loyaltyLevel = traderBase.loyaltyLevels.length; } @@ -403,16 +361,14 @@ export class TraderHelper */ public addTraderPurchasesToPlayerProfile( sessionID: string, - newPurchaseDetails: { items: { itemId: string, count: number }[], traderId: string }, + newPurchaseDetails: { items: { itemId: string; count: number }[]; traderId: string }, itemPurchased: Item, - ): void - { + ): void { const profile = this.profileHelper.getFullProfile(sessionID); const traderId = newPurchaseDetails.traderId; // Iterate over assorts bought and add to profile - for (const purchasedItem of newPurchaseDetails.items) - { + for (const purchasedItem of newPurchaseDetails.items) { const currentTime = this.timeUtil.getTimestamp(); // Nullguard traderPurchases @@ -422,8 +378,7 @@ export class TraderHelper // Null guard when dict doesnt exist - if (!profile.traderPurchases[traderId][purchasedItem.itemId]) - { + if (!profile.traderPurchases[traderId][purchasedItem.itemId]) { profile.traderPurchases[traderId][purchasedItem.itemId] = { count: purchasedItem.count, purchaseTimestamp: currentTime, @@ -433,18 +388,17 @@ export class TraderHelper } if ( - profile.traderPurchases[traderId][purchasedItem.itemId].count + purchasedItem.count - > this.getAccountTypeAdjustedTraderPurchaseLimit( + profile.traderPurchases[traderId][purchasedItem.itemId].count + purchasedItem.count > + this.getAccountTypeAdjustedTraderPurchaseLimit( itemPurchased.upd!.BuyRestrictionMax!, - profile.characters.pmc.Info.GameVersion) - ) - { + profile.characters.pmc.Info.GameVersion, + ) + ) { throw new Error( - this.localisationService.getText("trader-unable_to_purchase_item_limit_reached", - { - traderId: traderId, - limit: itemPurchased.upd!.BuyRestrictionMax, - }), + this.localisationService.getText("trader-unable_to_purchase_item_limit_reached", { + traderId: traderId, + limit: itemPurchased.upd!.BuyRestrictionMax, + }), ); } profile.traderPurchases[traderId][purchasedItem.itemId].count += purchasedItem.count; @@ -458,10 +412,8 @@ export class TraderHelper * @param gameVersion Profiles game version * @returns buyRestrictionMax value */ - public getAccountTypeAdjustedTraderPurchaseLimit(buyRestrictionMax: number, gameVersion: string): number - { - if (([GameEditions.EDGE_OF_DARKNESS, GameEditions.UNHEARD] as string[]).includes(gameVersion)) - { + public getAccountTypeAdjustedTraderPurchaseLimit(buyRestrictionMax: number, gameVersion: string): number { + if (([GameEditions.EDGE_OF_DARKNESS, GameEditions.UNHEARD] as string[]).includes(gameVersion)) { return Math.floor(buyRestrictionMax * 1.2); } @@ -474,49 +426,41 @@ export class TraderHelper * @param tpl Item to look up highest pride for * @returns highest rouble cost for item */ - public getHighestTraderPriceRouble(tpl: string): number - { - if (this.highestTraderPriceItems) - { + public getHighestTraderPriceRouble(tpl: string): number { + if (this.highestTraderPriceItems) { return this.highestTraderPriceItems[tpl]; } - if (!this.highestTraderPriceItems) - { + if (!this.highestTraderPriceItems) { this.highestTraderPriceItems = {}; } // Init dict and fill - for (const traderName in Traders) - { + for (const traderName in Traders) { // Skip some traders - if (traderName === Traders.FENCE) - { + if (traderName === Traders.FENCE) { continue; } // Get assorts for trader, skip trader if no assorts found const traderAssorts = this.databaseService.getTrader(Traders[traderName]).assort; - if (!traderAssorts) - { + if (!traderAssorts) { continue; } // Get all item assorts that have parentid of hideout (base item and not a mod of other item) - for (const item of traderAssorts.items.filter((x) => x.parentId === "hideout")) - { + for (const item of traderAssorts.items.filter((x) => x.parentId === "hideout")) { // Get barter scheme (contains cost of item) const barterScheme = traderAssorts.barter_scheme[item._id][0][0]; // Convert into roubles - const roubleAmount - = barterScheme._tpl === Money.ROUBLES + const roubleAmount = + barterScheme._tpl === Money.ROUBLES ? barterScheme.count : this.handbookHelper.inRUB(barterScheme.count, barterScheme._tpl); // Existing price smaller in dict than current iteration, overwrite - if (this.highestTraderPriceItems[item._tpl] ?? 0 < roubleAmount) - { + if (this.highestTraderPriceItems[item._tpl] ?? 0 < roubleAmount) { this.highestTraderPriceItems[item._tpl] = roubleAmount; } } @@ -530,18 +474,15 @@ export class TraderHelper * @param tpl Item to look up best trader sell-to price * @returns Rouble price */ - public getHighestSellToTraderPrice(tpl: string): number - { + public getHighestSellToTraderPrice(tpl: string): number { // Find highest trader price for item let highestPrice = 1; // Default price - for (const traderName in Traders) - { + for (const traderName in Traders) { // Get trader and check buy category allows tpl const traderBase = this.databaseService.getTrader(Traders[traderName]).base; // Skip traders that dont sell - if (!traderBase || !this.itemHelper.isOfBaseclasses(tpl, traderBase.items_buy.category)) - { + if (!traderBase || !this.itemHelper.isOfBaseclasses(tpl, traderBase.items_buy.category)) { continue; } @@ -556,8 +497,7 @@ export class TraderHelper ); // Price from this trader is higher than highest found, update - if (priceTraderBuysItemAt > highestPrice) - { + if (priceTraderBuysItemAt > highestPrice) { highestPrice = priceTraderBuysItemAt; } } @@ -570,12 +510,10 @@ export class TraderHelper * @param traderId Traders id * @returns Traders key */ - public getTraderById(traderId: string): Traders | undefined - { + public getTraderById(traderId: string): Traders | undefined { const keys = Object.keys(Traders).filter((x) => Traders[x] === traderId); - if (keys.length === 0) - { + if (keys.length === 0) { this.logger.error(this.localisationService.getText("trader-unable_to_find_trader_in_enum", traderId)); return undefined; @@ -598,11 +536,11 @@ export class TraderHelper * @param traderEnumValue The trader enum value to validate * @returns The validated trader enum value as a string, or an empty string if invalid */ - public getValidTraderIdByEnumValue(traderEnumValue: Traders): string - { - if (!this.traderEnumHasKey(traderEnumValue)) - { - this.logger.error(this.localisationService.getText("trader-unable_to_find_trader_in_enum", traderEnumValue)); + public getValidTraderIdByEnumValue(traderEnumValue: Traders): string { + if (!this.traderEnumHasKey(traderEnumValue)) { + this.logger.error( + this.localisationService.getText("trader-unable_to_find_trader_in_enum", traderEnumValue), + ); return ""; } @@ -615,8 +553,7 @@ export class TraderHelper * @param key Value to check for * @returns True, values exists in Traders enum as a value */ - public traderEnumHasKey(key: string): boolean - { + public traderEnumHasKey(key: string): boolean { return Object.keys(Traders).some((x) => x === key); } @@ -625,8 +562,7 @@ export class TraderHelper * @param traderId Trader id * @returns Ttrue if Traders enum has the param as a value */ - public traderEnumHasValue(traderId: string): boolean - { + public traderEnumHasValue(traderId: string): boolean { return Object.values(Traders).some((x) => x === traderId); } } diff --git a/project/src/helpers/UtilityHelper.ts b/project/src/helpers/UtilityHelper.ts index 6e10d619..c19df9b3 100644 --- a/project/src/helpers/UtilityHelper.ts +++ b/project/src/helpers/UtilityHelper.ts @@ -1,10 +1,8 @@ import { injectable } from "tsyringe"; @injectable() -export class UtilityHelper -{ - public arrayIntersect(a: T[], b: T[]): T[] - { +export class UtilityHelper { + public arrayIntersect(a: T[], b: T[]): T[] { return a.filter((x) => b.includes(x)); } } diff --git a/project/src/helpers/WeightedRandomHelper.ts b/project/src/helpers/WeightedRandomHelper.ts index 12cf1cb2..aa79b482 100644 --- a/project/src/helpers/WeightedRandomHelper.ts +++ b/project/src/helpers/WeightedRandomHelper.ts @@ -1,16 +1,14 @@ import { injectable } from "tsyringe"; @injectable() -export class WeightedRandomHelper -{ +export class WeightedRandomHelper { /** * @deprecated USE getWeightedValue() WHERE POSSIBLE * Gets a tplId from a weighted dictionary * @param {tplId: weighting[]} itemArray * @returns tplId */ - public getWeightedInventoryItem(itemArray: { [tplId: string]: unknown } | ArrayLike): string - { + public getWeightedInventoryItem(itemArray: { [tplId: string]: unknown } | ArrayLike): string { const itemKeys = Object.keys(itemArray); const weights = Object.values(itemArray); const chosenItem = this.weightedRandom(itemKeys, weights); @@ -23,8 +21,7 @@ export class WeightedRandomHelper * @param itemArray Items and weights to use * @returns Chosen item from array */ - public getWeightedValue(itemArray: { [key: string]: unknown } | ArrayLike): T - { + public getWeightedValue(itemArray: { [key: string]: unknown } | ArrayLike): T { const itemKeys = Object.keys(itemArray); const weights = Object.values(itemArray); @@ -47,20 +44,16 @@ export class WeightedRandomHelper * @param {number[]} weights * @returns {{item: any, index: number}} */ - public weightedRandom(items: any[], weights: any[]): { item: any, index: number } - { - if (!items || items.length === 0) - { + public weightedRandom(items: any[], weights: any[]): { item: any; index: number } { + if (!items || items.length === 0) { throw new Error("Items must not be empty"); } - if (!weights || weights.length === 0) - { + if (!weights || weights.length === 0) { throw new Error("Item weights must not be empty"); } - if (items.length !== weights.length) - { + if (items.length !== weights.length) { throw new Error("Items and weight inputs must be of the same length"); } @@ -69,8 +62,7 @@ export class WeightedRandomHelper // - weights = [1, 4, 3] // - cumulativeWeights = [1, 5, 8] const cumulativeWeights = []; - for (let i = 0; i < weights.length; i += 1) - { + for (let i = 0; i < weights.length; i += 1) { cumulativeWeights[i] = weights[i] + (cumulativeWeights[i - 1] || 0); } @@ -84,10 +76,8 @@ export class WeightedRandomHelper // Picking the random item based on its weight. // The items with higher weight will be picked more often. - for (let itemIndex = 0; itemIndex < items.length; itemIndex += 1) - { - if (cumulativeWeights[itemIndex] >= randomNumber) - { + for (let itemIndex = 0; itemIndex < items.length; itemIndex += 1) { + if (cumulativeWeights[itemIndex] >= randomNumber) { return { item: items[itemIndex], index: itemIndex }; } } @@ -97,17 +87,14 @@ export class WeightedRandomHelper * Find the greated common divisor of all weights and use it on the passed in dictionary * @param weightedDict values to reduce */ - public reduceWeightValues(weightedDict: Record): void - { + public reduceWeightValues(weightedDict: Record): void { // No values, nothing to reduce - if (Object.keys(weightedDict).length === 0) - { + if (Object.keys(weightedDict).length === 0) { return; } // Only one value, set to 1 and exit - if (Object.keys(weightedDict).length === 1) - { + if (Object.keys(weightedDict).length === 1) { const key = Object.keys(weightedDict)[0]; weightedDict[key] = 1; return; @@ -117,37 +104,30 @@ export class WeightedRandomHelper const commonDivisor = this.commonDivisor(weights); // No point in dividing by 1 - if (commonDivisor === 1) - { + if (commonDivisor === 1) { return; } - for (const key in weightedDict) - { - if (Object.hasOwn(weightedDict, key)) - { + for (const key in weightedDict) { + if (Object.hasOwn(weightedDict, key)) { weightedDict[key] /= commonDivisor; } } } - protected commonDivisor(numbers: number[]): number - { + protected commonDivisor(numbers: number[]): number { let result = numbers[0]; - for (let i = 1; i < numbers.length; i++) - { + for (let i = 1; i < numbers.length; i++) { result = this.gcd(result, numbers[i]); } return result; } - protected gcd(a: number, b: number): number - { + protected gcd(a: number, b: number): number { let x = a; let y = b; - while (y !== 0) - { + while (y !== 0) { const temp = y; y = x % y; x = temp; diff --git a/project/src/loaders/BundleLoader.ts b/project/src/loaders/BundleLoader.ts index db1f04d8..8965bb9e 100644 --- a/project/src/loaders/BundleLoader.ts +++ b/project/src/loaders/BundleLoader.ts @@ -1,20 +1,18 @@ import path from "node:path"; -import { inject, injectable } from "tsyringe"; import { HttpServerHelper } from "@spt/helpers/HttpServerHelper"; import { BundleHashCacheService } from "@spt/services/cache/BundleHashCacheService"; -import { ICloner } from "@spt/utils/cloners/ICloner"; import { JsonUtil } from "@spt/utils/JsonUtil"; import { VFS } from "@spt/utils/VFS"; +import { ICloner } from "@spt/utils/cloners/ICloner"; +import { inject, injectable } from "tsyringe"; -export class BundleInfo -{ +export class BundleInfo { modpath: string; filename: string; crc: number; dependencies: string[]; - constructor(modpath: string, bundle: BundleManifestEntry, bundleHash: number) - { + constructor(modpath: string, bundle: BundleManifestEntry, bundleHash: number) { this.modpath = modpath; this.filename = bundle.key; this.crc = bundleHash; @@ -23,8 +21,7 @@ export class BundleInfo } @injectable() -export class BundleLoader -{ +export class BundleLoader { protected bundles: Record = {}; constructor( @@ -33,42 +30,35 @@ export class BundleLoader @inject("JsonUtil") protected jsonUtil: JsonUtil, @inject("BundleHashCacheService") protected bundleHashCacheService: BundleHashCacheService, @inject("PrimaryCloner") protected cloner: ICloner, - ) - {} + ) {} /** * Handle singleplayer/bundles */ - public getBundles(): BundleInfo[] - { + public getBundles(): BundleInfo[] { const result: BundleInfo[] = []; - for (const bundle in this.bundles) - { + for (const bundle in this.bundles) { result.push(this.getBundle(bundle)); } return result; } - public getBundle(key: string): BundleInfo - { + public getBundle(key: string): BundleInfo { return this.cloner.clone(this.bundles[key]); } - public addBundles(modpath: string): void - { + public addBundles(modpath: string): void { const bundleManifestArr = this.jsonUtil.deserialize( this.vfs.readFile(`${modpath}bundles.json`), ).manifest; - for (const bundleManifest of bundleManifestArr) - { + for (const bundleManifest of bundleManifestArr) { const absoluteModPath = path.join(process.cwd(), modpath).slice(0, -1).replace(/\\/g, "/"); const bundleLocalPath = `${modpath}bundles/${bundleManifest.key}`.replace(/\\/g, "/"); - if (!this.bundleHashCacheService.calculateAndMatchHash(bundleLocalPath)) - { + if (!this.bundleHashCacheService.calculateAndMatchHash(bundleLocalPath)) { this.bundleHashCacheService.calculateAndStoreHash(bundleLocalPath); } @@ -78,19 +68,16 @@ export class BundleLoader } } - public addBundle(key: string, b: BundleInfo): void - { + public addBundle(key: string, b: BundleInfo): void { this.bundles[key] = b; } } -export interface BundleManifest -{ - manifest: BundleManifestEntry[] +export interface BundleManifest { + manifest: BundleManifestEntry[]; } -export interface BundleManifestEntry -{ - key: string - dependencyKeys: string[] +export interface BundleManifestEntry { + key: string; + dependencyKeys: string[]; } diff --git a/project/src/loaders/ModLoadOrder.ts b/project/src/loaders/ModLoadOrder.ts index 236eecf6..b95732ed 100644 --- a/project/src/loaders/ModLoadOrder.ts +++ b/project/src/loaders/ModLoadOrder.ts @@ -1,11 +1,10 @@ -import { inject, injectable } from "tsyringe"; import { IPackageJsonData } from "@spt/models/spt/mod/IPackageJsonData"; import { ILogger } from "@spt/models/spt/utils/ILogger"; import { LocalisationService } from "@spt/services/LocalisationService"; +import { inject, injectable } from "tsyringe"; @injectable() -export class ModLoadOrder -{ +export class ModLoadOrder { protected mods = new Map(); protected modsAvailable = new Map(); protected loadOrder = new Set(); @@ -13,11 +12,9 @@ export class ModLoadOrder constructor( @inject("PrimaryLogger") protected logger: ILogger, @inject("LocalisationService") protected localisationService: LocalisationService, - ) - {} + ) {} - public setModList(mods: Record): void - { + public setModList(mods: Record): void { this.mods = new Map(Object.entries(mods)); this.modsAvailable = structuredClone(this.mods); this.loadOrder = new Set(); @@ -25,29 +22,23 @@ export class ModLoadOrder const visited = new Set(); // invert loadBefore into loadAfter on specified mods - for (const [modName, modConfig] of this.modsAvailable) - { - if ((modConfig.loadBefore ?? []).length > 0) - { + for (const [modName, modConfig] of this.modsAvailable) { + if ((modConfig.loadBefore ?? []).length > 0) { this.invertLoadBefore(modName); } } - for (const modName of this.modsAvailable.keys()) - { + for (const modName of this.modsAvailable.keys()) { this.getLoadOrderRecursive(modName, visited); } } - public getLoadOrder(): string[] - { + public getLoadOrder(): string[] { return Array.from(this.loadOrder); } - public getModsOnLoadBefore(mod: string): Set - { - if (!this.mods.has(mod)) - { + public getModsOnLoadBefore(mod: string): Set { + if (!this.mods.has(mod)) { throw new Error(this.localisationService.getText("modloader-mod_isnt_present", mod)); } @@ -55,10 +46,8 @@ export class ModLoadOrder const loadBefore = new Set(config.loadBefore); - for (const loadBeforeMod of loadBefore) - { - if (!this.mods.has(loadBeforeMod)) - { + for (const loadBeforeMod of loadBefore) { + if (!this.mods.has(loadBeforeMod)) { loadBefore.delete(loadBeforeMod); } } @@ -66,10 +55,8 @@ export class ModLoadOrder return loadBefore; } - public getModsOnLoadAfter(mod: string): Set - { - if (!this.mods.has(mod)) - { + public getModsOnLoadAfter(mod: string): Set { + if (!this.mods.has(mod)) { throw new Error(this.localisationService.getText("modloader-mod_isnt_present", mod)); } @@ -77,10 +64,8 @@ export class ModLoadOrder const loadAfter = new Set(config.loadAfter); - for (const loadAfterMod of loadAfter) - { - if (!this.mods.has(loadAfterMod)) - { + for (const loadAfterMod of loadAfter) { + if (!this.mods.has(loadAfterMod)) { loadAfter.delete(loadAfterMod); } } @@ -88,12 +73,10 @@ export class ModLoadOrder return loadAfter; } - protected invertLoadBefore(mod: string): void - { + protected invertLoadBefore(mod: string): void { const loadBefore = this.getModsOnLoadBefore(mod); - for (const loadBeforeMod of loadBefore) - { + for (const loadBeforeMod of loadBefore) { const loadBeforeModConfig = this.modsAvailable.get(loadBeforeMod); loadBeforeModConfig.loadAfter ??= []; @@ -103,16 +86,13 @@ export class ModLoadOrder } } - protected getLoadOrderRecursive(mod: string, visited: Set): void - { + protected getLoadOrderRecursive(mod: string, visited: Set): void { // Validate package - if (this.loadOrder.has(mod)) - { + if (this.loadOrder.has(mod)) { return; } - if (visited.has(mod)) - { + if (visited.has(mod)) { // Additional info to help debug this.logger.debug(this.localisationService.getText("modloader-checking_mod", mod)); this.logger.debug(`${this.localisationService.getText("modloader-checked")}:`); @@ -124,8 +104,7 @@ export class ModLoadOrder } // Check dependencies - if (!this.modsAvailable.has(mod)) - { + if (!this.modsAvailable.has(mod)) { throw new Error(this.localisationService.getText("modloader-error_parsing_mod_load_order")); } @@ -136,12 +115,9 @@ export class ModLoadOrder const dependencies = new Set(Object.keys(config.modDependencies)); - for (const modAfter of config.loadAfter) - { - if (this.modsAvailable.has(modAfter)) - { - if (this.modsAvailable.get(modAfter)?.loadAfter?.includes(mod)) - { + for (const modAfter of config.loadAfter) { + if (this.modsAvailable.has(modAfter)) { + if (this.modsAvailable.get(modAfter)?.loadAfter?.includes(mod)) { throw new Error( this.localisationService.getText("modloader-load_order_conflict", { modOneName: mod, @@ -156,8 +132,7 @@ export class ModLoadOrder visited.add(mod); - for (const mod of dependencies) - { + for (const mod of dependencies) { this.getLoadOrderRecursive(mod, visited); } diff --git a/project/src/loaders/ModTypeCheck.ts b/project/src/loaders/ModTypeCheck.ts index 9af891af..0c8e0a21 100644 --- a/project/src/loaders/ModTypeCheck.ts +++ b/project/src/loaders/ModTypeCheck.ts @@ -1,20 +1,18 @@ -import { injectable } from "tsyringe"; import { IPostDBLoadMod } from "@spt/models/external/IPostDBLoadMod"; import { IPostDBLoadModAsync } from "@spt/models/external/IPostDBLoadModAsync"; import { IPostSptLoadMod } from "@spt/models/external/IPostSptLoadMod"; import { IPostSptLoadModAsync } from "@spt/models/external/IPostSptLoadModAsync"; import { IPreSptLoadMod } from "@spt/models/external/IPreSptLoadMod"; import { IPreSptLoadModAsync } from "@spt/models/external/IPreSptLoadModAsync"; +import { injectable } from "tsyringe"; @injectable() -export class ModTypeCheck -{ +export class ModTypeCheck { /** * Use defined safe guard to check if the mod is a IPreSptLoadMod * @returns boolean */ - public isPreSptLoad(mod: any): mod is IPreSptLoadMod - { + public isPreSptLoad(mod: any): mod is IPreSptLoadMod { return mod?.preSptLoad; } @@ -22,8 +20,7 @@ export class ModTypeCheck * Use defined safe guard to check if the mod is a IPostSptLoadMod * @returns boolean */ - public isPostSptLoad(mod: any): mod is IPostSptLoadMod - { + public isPostSptLoad(mod: any): mod is IPostSptLoadMod { return mod?.postSptLoad; } @@ -31,8 +28,7 @@ export class ModTypeCheck * Use defined safe guard to check if the mod is a IPostDBLoadMod * @returns boolean */ - public isPostDBLoad(mod: any): mod is IPostDBLoadMod - { + public isPostDBLoad(mod: any): mod is IPostDBLoadMod { return mod?.postDBLoad; } @@ -40,8 +36,7 @@ export class ModTypeCheck * Use defined safe guard to check if the mod is a IPreSptLoadModAsync * @returns boolean */ - public isPreSptLoadAsync(mod: any): mod is IPreSptLoadModAsync - { + public isPreSptLoadAsync(mod: any): mod is IPreSptLoadModAsync { return mod?.preSptLoadAsync; } @@ -49,8 +44,7 @@ export class ModTypeCheck * Use defined safe guard to check if the mod is a IPostSptLoadModAsync * @returns boolean */ - public isPostSptLoadAsync(mod: any): mod is IPostSptLoadModAsync - { + public isPostSptLoadAsync(mod: any): mod is IPostSptLoadModAsync { return mod?.postSptLoadAsync; } @@ -58,8 +52,7 @@ export class ModTypeCheck * Use defined safe guard to check if the mod is a IPostDBLoadModAsync * @returns boolean */ - public isPostDBLoadAsync(mod: any): mod is IPostDBLoadModAsync - { + public isPostDBLoadAsync(mod: any): mod is IPostDBLoadModAsync { return mod?.postDBLoadAsync; } @@ -67,15 +60,14 @@ export class ModTypeCheck * Checks for mod to be compatible with 3.X+ * @returns boolean */ - public isPostV3Compatible(mod: any): boolean - { + public isPostV3Compatible(mod: any): boolean { return ( - this.isPreSptLoad(mod) - || this.isPostSptLoad(mod) - || this.isPostDBLoad(mod) - || this.isPreSptLoadAsync(mod) - || this.isPostSptLoadAsync(mod) - || this.isPostDBLoadAsync(mod) + this.isPreSptLoad(mod) || + this.isPostSptLoad(mod) || + this.isPostDBLoad(mod) || + this.isPreSptLoadAsync(mod) || + this.isPostSptLoadAsync(mod) || + this.isPostDBLoadAsync(mod) ); } } diff --git a/project/src/loaders/PostDBModLoader.ts b/project/src/loaders/PostDBModLoader.ts index c43b8537..ca7ed104 100644 --- a/project/src/loaders/PostDBModLoader.ts +++ b/project/src/loaders/PostDBModLoader.ts @@ -1,4 +1,3 @@ -import { DependencyContainer, inject, injectable } from "tsyringe"; import { OnLoad } from "@spt/di/OnLoad"; import { BundleLoader } from "@spt/loaders/BundleLoader"; import { ModTypeCheck } from "@spt/loaders/ModTypeCheck"; @@ -7,10 +6,10 @@ import { IPostDBLoadMod } from "@spt/models/external/IPostDBLoadMod"; import { IPostDBLoadModAsync } from "@spt/models/external/IPostDBLoadModAsync"; import { ILogger } from "@spt/models/spt/utils/ILogger"; import { LocalisationService } from "@spt/services/LocalisationService"; +import { DependencyContainer, inject, injectable } from "tsyringe"; @injectable() -export class PostDBModLoader implements OnLoad -{ +export class PostDBModLoader implements OnLoad { protected container: DependencyContainer; constructor( @@ -19,34 +18,27 @@ export class PostDBModLoader implements OnLoad @inject("PreSptModLoader") protected preSptModLoader: PreSptModLoader, @inject("LocalisationService") protected localisationService: LocalisationService, @inject("ModTypeCheck") protected modTypeCheck: ModTypeCheck, - ) - {} + ) {} - public async onLoad(): Promise - { - if (globalThis.G_MODS_ENABLED) - { + public async onLoad(): Promise { + if (globalThis.G_MODS_ENABLED) { this.container = this.preSptModLoader.getContainer(); await this.executeModsAsync(); this.addBundles(); } } - public getRoute(): string - { + public getRoute(): string { return "spt-mods"; } - public getModPath(mod: string): string - { + public getModPath(mod: string): string { return this.preSptModLoader.getModPath(mod); } - protected async executeModsAsync(): Promise - { + protected async executeModsAsync(): Promise { const mods = this.preSptModLoader.sortModsLoadOrder(); - for (const modName of mods) - { + for (const modName of mods) { // import class const filepath = `${this.preSptModLoader.getModPath(modName)}${ this.preSptModLoader.getImportedModDetails()[modName].main @@ -54,14 +46,10 @@ export class PostDBModLoader implements OnLoad const modpath = `${process.cwd()}/${filepath}`; const mod = require(modpath); - if (this.modTypeCheck.isPostDBLoadAsync(mod.mod)) - { - try - { + if (this.modTypeCheck.isPostDBLoadAsync(mod.mod)) { + try { await (mod.mod as IPostDBLoadModAsync).postDBLoadAsync(this.container); - } - catch (err) - { + } catch (err) { this.logger.error( this.localisationService.getText( "modloader-async_mod_error", @@ -71,22 +59,18 @@ export class PostDBModLoader implements OnLoad } } - if (this.modTypeCheck.isPostDBLoad(mod.mod)) - { + if (this.modTypeCheck.isPostDBLoad(mod.mod)) { (mod.mod as IPostDBLoadMod).postDBLoad(this.container); } } } - protected addBundles(): void - { + protected addBundles(): void { const importedMods = this.preSptModLoader.getImportedModDetails(); - for (const [mod, pkg] of Object.entries(importedMods)) - { + for (const [mod, pkg] of Object.entries(importedMods)) { const modPath = this.preSptModLoader.getModPath(mod); - if (pkg.isBundleMod ?? false) - { + if (pkg.isBundleMod ?? false) { this.bundleLoader.addBundles(modPath); } } diff --git a/project/src/loaders/PostSptModLoader.ts b/project/src/loaders/PostSptModLoader.ts index 5f03b407..448b9a4e 100644 --- a/project/src/loaders/PostSptModLoader.ts +++ b/project/src/loaders/PostSptModLoader.ts @@ -1,4 +1,3 @@ -import { DependencyContainer, inject, injectable } from "tsyringe"; import { ModTypeCheck } from "@spt/loaders/ModTypeCheck"; import { PreSptModLoader } from "@spt/loaders/PreSptModLoader"; import { IPostSptLoadMod } from "@spt/models/external/IPostSptLoadMod"; @@ -6,10 +5,10 @@ import { IPostSptLoadModAsync } from "@spt/models/external/IPostSptLoadModAsync" import { IModLoader } from "@spt/models/spt/mod/IModLoader"; import { ILogger } from "@spt/models/spt/utils/ILogger"; import { LocalisationService } from "@spt/services/LocalisationService"; +import { DependencyContainer, inject, injectable } from "tsyringe"; @injectable() -export class PostSptModLoader implements IModLoader -{ +export class PostSptModLoader implements IModLoader { protected container: DependencyContainer; constructor( @@ -17,28 +16,22 @@ export class PostSptModLoader implements IModLoader @inject("PreSptModLoader") protected preSptModLoader: PreSptModLoader, @inject("LocalisationService") protected localisationService: LocalisationService, @inject("ModTypeCheck") protected modTypeCheck: ModTypeCheck, - ) - {} + ) {} - public getModPath(mod: string): string - { + public getModPath(mod: string): string { return this.preSptModLoader.getModPath(mod); } - public async load(): Promise - { - if (globalThis.G_MODS_ENABLED) - { + public async load(): Promise { + if (globalThis.G_MODS_ENABLED) { this.container = this.preSptModLoader.getContainer(); await this.executeModsAsync(); } } - protected async executeModsAsync(): Promise - { + protected async executeModsAsync(): Promise { const mods = this.preSptModLoader.sortModsLoadOrder(); - for (const modName of mods) - { + for (const modName of mods) { // // import class const filepath = `${this.preSptModLoader.getModPath(modName)}${ this.preSptModLoader.getImportedModDetails()[modName].main @@ -46,14 +39,10 @@ export class PostSptModLoader implements IModLoader const modpath = `${process.cwd()}/${filepath}`; const mod = require(modpath); - if (this.modTypeCheck.isPostSptLoadAsync(mod.mod)) - { - try - { + if (this.modTypeCheck.isPostSptLoadAsync(mod.mod)) { + try { await (mod.mod as IPostSptLoadModAsync).postSptLoadAsync(this.container); - } - catch (err) - { + } catch (err) { this.logger.error( this.localisationService.getText( "modloader-async_mod_error", @@ -63,8 +52,7 @@ export class PostSptModLoader implements IModLoader } } - if (this.modTypeCheck.isPostSptLoad(mod.mod)) - { + if (this.modTypeCheck.isPostSptLoad(mod.mod)) { (mod.mod as IPostSptLoadMod).postSptLoad(this.container); } } diff --git a/project/src/loaders/PreSptModLoader.ts b/project/src/loaders/PreSptModLoader.ts index fa75b8c5..a436ffcb 100644 --- a/project/src/loaders/PreSptModLoader.ts +++ b/project/src/loaders/PreSptModLoader.ts @@ -1,8 +1,6 @@ import { execSync } from "node:child_process"; import os from "node:os"; import path from "node:path"; -import { maxSatisfying, valid, validRange, satisfies } from "semver"; -import { DependencyContainer, inject, injectable } from "tsyringe"; import { ModLoadOrder } from "@spt/loaders/ModLoadOrder"; import { ModTypeCheck } from "@spt/loaders/ModTypeCheck"; import { ModDetails } from "@spt/models/eft/profile/ISptProfile"; @@ -18,10 +16,11 @@ import { LocalisationService } from "@spt/services/LocalisationService"; import { ModCompilerService } from "@spt/services/ModCompilerService"; import { JsonUtil } from "@spt/utils/JsonUtil"; import { VFS } from "@spt/utils/VFS"; +import { maxSatisfying, satisfies, valid, validRange } from "semver"; +import { DependencyContainer, inject, injectable } from "tsyringe"; @injectable() -export class PreSptModLoader implements IModLoader -{ +export class PreSptModLoader implements IModLoader { protected container: DependencyContainer; protected readonly basepath = "user/mods/"; @@ -41,8 +40,7 @@ export class PreSptModLoader implements IModLoader @inject("ConfigServer") protected configServer: ConfigServer, @inject("ModLoadOrder") protected modLoadOrder: ModLoadOrder, @inject("ModTypeCheck") protected modTypeCheck: ModTypeCheck, - ) - { + ) { this.sptConfig = this.configServer.getConfig(ConfigTypes.CORE); const packageJsonPath: string = path.join(__dirname, "../../package.json"); @@ -50,10 +48,8 @@ export class PreSptModLoader implements IModLoader this.skippedMods = new Set(); } - public async load(container: DependencyContainer): Promise - { - if (globalThis.G_MODS_ENABLED) - { + public async load(container: DependencyContainer): Promise { + if (globalThis.G_MODS_ENABLED) { this.container = container; await this.importModsAsync(); await this.executeModsAsync(); @@ -64,24 +60,19 @@ export class PreSptModLoader implements IModLoader * Returns a list of mods with preserved load order * @returns Array of mod names in load order */ - public getImportedModsNames(): string[] - { + public getImportedModsNames(): string[] { return Object.keys(this.imported); } - public getImportedModDetails(): Record - { + public getImportedModDetails(): Record { return this.imported; } - public getProfileModsGroupedByModName(profileMods: ModDetails[]): ModDetails[] - { + public getProfileModsGroupedByModName(profileMods: ModDetails[]): ModDetails[] { // Group all mods used by profile by name const modsGroupedByName: Record = {}; - for (const mod of profileMods) - { - if (!modsGroupedByName[mod.name]) - { + for (const mod of profileMods) { + if (!modsGroupedByName[mod.name]) { modsGroupedByName[mod.name] = []; } @@ -90,15 +81,13 @@ export class PreSptModLoader implements IModLoader // Find the highest versioned mod and add to results array const result = []; - for (const modName in modsGroupedByName) - { + for (const modName in modsGroupedByName) { const modDatas = modsGroupedByName[modName]; const modVersions = modDatas.map((x) => x.version); const highestVersion = maxSatisfying(modVersions, "*"); const chosenVersion = modDatas.find((x) => x.name === modName && x.version === highestVersion); - if (!chosenVersion) - { + if (!chosenVersion) { continue; } @@ -108,15 +97,12 @@ export class PreSptModLoader implements IModLoader return result; } - public getModPath(mod: string): string - { + public getModPath(mod: string): string { return `${this.basepath}${mod}/`; } - protected async importModsAsync(): Promise - { - if (!this.vfs.exists(this.basepath)) - { + protected async importModsAsync(): Promise { + if (!this.vfs.exists(this.basepath)) { // no mods folder found this.logger.info(this.localisationService.getText("modloader-user_mod_folder_missing")); this.vfs.createDir(this.basepath); @@ -131,26 +117,19 @@ export class PreSptModLoader implements IModLoader this.logger.info(this.localisationService.getText("modloader-loading_mods", mods.length)); // Mod order - if (!this.vfs.exists(this.modOrderPath)) - { + if (!this.vfs.exists(this.modOrderPath)) { this.logger.info(this.localisationService.getText("modloader-mod_order_missing")); // Write file with empty order array to disk this.vfs.writeFile(this.modOrderPath, this.jsonUtil.serializeAdvanced({ order: [] }, undefined, 4)); - } - else - { + } else { const modOrder = this.vfs.readFile(this.modOrderPath, { encoding: "utf8" }); - try - { + try { const modOrderArray = this.jsonUtil.deserialize(modOrder, this.modOrderPath).order; - for (const [index, mod] of modOrderArray.entries()) - { + for (const [index, mod] of modOrderArray.entries()) { this.order[mod] = index; } - } - catch (error) - { + } catch (error) { this.logger.error(this.localisationService.getText("modloader-mod_order_error")); } } @@ -164,45 +143,38 @@ export class PreSptModLoader implements IModLoader // Used to check all errors before stopping the load execution let errorsFound = false; - for (const [modFolderName, modToValidate] of modPackageData) - { - if (this.shouldSkipMod(modToValidate)) - { + for (const [modFolderName, modToValidate] of modPackageData) { + if (this.shouldSkipMod(modToValidate)) { // skip error checking and dependency install for mods already marked as skipped. continue; } // if the mod has library dependencies check if these dependencies are bundled in the server, if not install them if ( - modToValidate.dependencies - && Object.keys(modToValidate.dependencies).length > 0 - && !this.vfs.exists(`${this.basepath}${modFolderName}/node_modules`) - ) - { + modToValidate.dependencies && + Object.keys(modToValidate.dependencies).length > 0 && + !this.vfs.exists(`${this.basepath}${modFolderName}/node_modules`) + ) { this.autoInstallDependencies(`${this.basepath}${modFolderName}`, modToValidate); } // Returns if any mod dependency is not satisfied - if (!this.areModDependenciesFulfilled(modToValidate, modPackageData)) - { + if (!this.areModDependenciesFulfilled(modToValidate, modPackageData)) { errorsFound = true; } // Returns if at least two incompatible mods are found - if (!this.isModCompatible(modToValidate, modPackageData)) - { + if (!this.isModCompatible(modToValidate, modPackageData)) { errorsFound = true; } // Returns if mod isnt compatible with this verison of spt - if (!this.isModCombatibleWithSpt(modToValidate)) - { + if (!this.isModCombatibleWithSpt(modToValidate)) { errorsFound = true; } } - if (errorsFound) - { + if (errorsFound) { this.logger.error(this.localisationService.getText("modloader-no_mods_loaded")); return; } @@ -212,18 +184,15 @@ export class PreSptModLoader implements IModLoader validMods.sort((prev, next) => this.sortMods(prev, next, missingFromOrderJSON)); // log the missing mods from order.json - for (const missingMod of Object.keys(missingFromOrderJSON)) - { + for (const missingMod of Object.keys(missingFromOrderJSON)) { this.logger.debug(this.localisationService.getText("modloader-mod_order_missing_from_json", missingMod)); } // add mods - for (const mod of validMods) - { + for (const mod of validMods) { const pkg = modPackageData.get(mod); - if (this.shouldSkipMod(pkg)) - { + if (this.shouldSkipMod(pkg)) { this.logger.warning(this.localisationService.getText("modloader-skipped_mod", { mod: mod })); continue; } @@ -234,21 +203,18 @@ export class PreSptModLoader implements IModLoader this.modLoadOrder.setModList(this.imported); } - protected sortMods(prev: string, next: string, missingFromOrderJSON: Record): number - { + protected sortMods(prev: string, next: string, missingFromOrderJSON: Record): number { const previndex = this.order[prev]; const nextindex = this.order[next]; // mod is not on the list, move the mod to last - if (previndex === undefined) - { + if (previndex === undefined) { missingFromOrderJSON[prev] = true; return 1; } - if (nextindex === undefined) - { + if (nextindex === undefined) { missingFromOrderJSON[next] = true; return -1; @@ -261,25 +227,21 @@ export class PreSptModLoader implements IModLoader * Check for duplicate mods loaded, show error if any * @param modPackageData map of mod package.json data */ - protected checkForDuplicateMods(modPackageData: Map): void - { + protected checkForDuplicateMods(modPackageData: Map): void { const grouppedMods: Map = new Map(); - for (const mod of modPackageData.values()) - { + for (const mod of modPackageData.values()) { const name = `${mod.author}-${mod.name}`; grouppedMods.set(name, [...(grouppedMods.get(name) ?? []), mod]); // if there's more than one entry for a given mod it means there's at least 2 mods with the same author and name trying to load. - if (grouppedMods.get(name).length > 1 && !this.skippedMods.has(name)) - { + if (grouppedMods.get(name).length > 1 && !this.skippedMods.has(name)) { this.skippedMods.add(name); } } // at this point this.skippedMods only contains mods that are duplicated, so we can just go through every single entry and log it - for (const modName of this.skippedMods) - { + for (const modName of this.skippedMods) { this.logger.error(this.localisationService.getText("modloader-x_duplicates_found", modName)); } } @@ -290,14 +252,11 @@ export class PreSptModLoader implements IModLoader * @param mods mods to validate * @returns array of mod folder names */ - protected getValidMods(mods: string[]): string[] - { + protected getValidMods(mods: string[]): string[] { const validMods: string[] = []; - for (const mod of mods) - { - if (this.validMod(mod)) - { + for (const mod of mods) { + if (this.validMod(mod)) { validMods.push(mod); } } @@ -310,12 +269,10 @@ export class PreSptModLoader implements IModLoader * @param mods mods to get packageJson for * @returns map */ - protected getModsPackageData(mods: string[]): Map - { + protected getModsPackageData(mods: string[]): Map { const loadedMods = new Map(); - for (const mod of mods) - { + for (const mod of mods) { loadedMods.set(mod, this.jsonUtil.deserialize(this.vfs.readFile(`${this.getModPath(mod)}/package.json`))); } @@ -327,31 +284,33 @@ export class PreSptModLoader implements IModLoader * @param mod Mod to check compatibiltiy with SPT * @returns True if compatible */ - protected isModCombatibleWithSpt(mod: IPackageJsonData): boolean - { + protected isModCombatibleWithSpt(mod: IPackageJsonData): boolean { const sptVersion = globalThis.G_SPTVERSION || this.sptConfig.sptVersion; const modName = `${mod.author}-${mod.name}`; // Error and prevent loading If no sptVersion property exists - if (!mod.sptVersion) - { + if (!mod.sptVersion) { this.logger.error(this.localisationService.getText("modloader-missing_sptversion_field", modName)); return false; } // Error and prevent loading if sptVersion property is not a valid semver string - if (!(valid(mod.sptVersion) || validRange(mod.sptVersion))) - { + if (!(valid(mod.sptVersion) || validRange(mod.sptVersion))) { this.logger.error(this.localisationService.getText("modloader-invalid_sptversion_field", modName)); return false; } // Warning and allow loading if semver is not satisfied - if (!satisfies(sptVersion, mod.sptVersion)) - { - this.logger.warning(this.localisationService.getText("modloader-outdated_sptversion_field", { modName: modName, modVersion: mod.version, desiredSptVersion: mod.sptVersion })); + if (!satisfies(sptVersion, mod.sptVersion)) { + this.logger.warning( + this.localisationService.getText("modloader-outdated_sptversion_field", { + modName: modName, + modVersion: mod.version, + desiredSptVersion: mod.sptVersion, + }), + ); return true; } @@ -363,16 +322,13 @@ export class PreSptModLoader implements IModLoader * Execute each mod found in this.imported * @returns void promise */ - protected async executeModsAsync(): Promise - { + protected async executeModsAsync(): Promise { // Sort mods load order const source = this.sortModsLoadOrder(); // Import mod classes - for (const mod of source) - { - if (!this.imported[mod].main) - { + for (const mod of source) { + if (!this.imported[mod].main) { this.logger.error(this.localisationService.getText("modloader-mod_has_no_main_property", mod)); continue; @@ -384,8 +340,7 @@ export class PreSptModLoader implements IModLoader const requiredMod = require(modFilePath); - if (!this.modTypeCheck.isPostV3Compatible(requiredMod.mod)) - { + if (!this.modTypeCheck.isPostV3Compatible(requiredMod.mod)) { this.logger.error(this.localisationService.getText("modloader-mod_incompatible", mod)); delete this.imported[mod]; @@ -393,15 +348,11 @@ export class PreSptModLoader implements IModLoader } // Perform async load of mod - if (this.modTypeCheck.isPreSptLoadAsync(requiredMod.mod)) - { - try - { + if (this.modTypeCheck.isPreSptLoadAsync(requiredMod.mod)) { + try { await (requiredMod.mod as IPreSptLoadModAsync).preSptLoadAsync(this.container); globalThis[mod] = requiredMod; - } - catch (err) - { + } catch (err) { this.logger.error( this.localisationService.getText( "modloader-async_mod_error", @@ -414,8 +365,7 @@ export class PreSptModLoader implements IModLoader } // Perform sync load of mod - if (this.modTypeCheck.isPreSptLoad(requiredMod.mod)) - { + if (this.modTypeCheck.isPreSptLoad(requiredMod.mod)) { (requiredMod.mod as IPreSptLoadMod).preSptLoad(this.container); globalThis[mod] = requiredMod; } @@ -426,12 +376,10 @@ export class PreSptModLoader implements IModLoader * Read loadorder.json (create if doesnt exist) and return sorted list of mods * @returns string array of sorted mod names */ - public sortModsLoadOrder(): string[] - { + public sortModsLoadOrder(): string[] { // if loadorder.json exists: load it, otherwise generate load order const loadOrderPath = `${this.basepath}loadorder.json`; - if (this.vfs.exists(loadOrderPath)) - { + if (this.vfs.exists(loadOrderPath)) { return this.jsonUtil.deserialize(this.vfs.readFile(loadOrderPath), loadOrderPath); } @@ -442,21 +390,16 @@ export class PreSptModLoader implements IModLoader * Compile mod and add into class property "imported" * @param mod Name of mod to compile/add */ - protected async addModAsync(mod: string, pkg: IPackageJsonData): Promise - { + protected async addModAsync(mod: string, pkg: IPackageJsonData): Promise { const modPath = this.getModPath(mod); const typeScriptFiles = this.vfs.getFilesOfType(`${modPath}src`, ".ts"); - if (typeScriptFiles.length > 0) - { - if (globalThis.G_MODS_TRANSPILE_TS) - { + if (typeScriptFiles.length > 0) { + if (globalThis.G_MODS_TRANSPILE_TS) { // compile ts into js if ts files exist and globalThis.G_MODS_TRANSPILE_TS is set to true await this.modCompilerService.compileMod(mod, modPath, typeScriptFiles); - } - else - { + } else { // rename the mod entry point to .ts if it's set to .js because G_MODS_TRANSPILE_TS is set to false pkg.main = pkg.main.replace(".js", ".ts"); } @@ -482,38 +425,32 @@ export class PreSptModLoader implements IModLoader * @param pkg mod package.json data * @returns */ - protected shouldSkipMod(pkg: IPackageJsonData): boolean - { + protected shouldSkipMod(pkg: IPackageJsonData): boolean { return this.skippedMods.has(`${pkg.author}-${pkg.name}`); } - protected autoInstallDependencies(modPath: string, pkg: IPackageJsonData): void - { + protected autoInstallDependencies(modPath: string, pkg: IPackageJsonData): void { const dependenciesToInstall = new Map(); - for (const [depName, depVersion] of Object.entries(pkg.dependencies)) - { + for (const [depName, depVersion] of Object.entries(pkg.dependencies)) { // currently not checking for version mismatches, but we could check it, just don't know what we would do afterwards, some options would be: // 1 - throw an error // 2 - use the server's version (which is what's currently happening by not checking the version) // 3 - use the mod's version (don't know the reprecursions this would have, or if it would even work) // if a mod's dependency does not exist in the server's dependencies we can add it to the list of dependencies to install. - if (!this.serverDependencies[depName]) - { + if (!this.serverDependencies[depName]) { dependenciesToInstall.set(depName, depVersion); } } // If the mod has no extra dependencies return as there's nothing that needs to be done. - if (dependenciesToInstall.size === 0) - { + if (dependenciesToInstall.size === 0) { return; } // If this feature flag is set to false, we warn the user he has a mod that requires extra dependencies and might not work, point them in the right direction on how to enable this feature. - if (!this.sptConfig.features.autoInstallModDependencies) - { + if (!this.sptConfig.features.autoInstallModDependencies) { this.logger.warning( this.localisationService.getText("modloader-installing_external_dependencies_disabled", { name: pkg.name, @@ -548,8 +485,7 @@ export class PreSptModLoader implements IModLoader ); let command = `"${pnpmPath}" install `; - for (const [depName, depVersion] of dependenciesToInstall) - { + for (const [depName, depVersion] of dependenciesToInstall) { command += `${depName}@${depVersion} `; } @@ -561,20 +497,16 @@ export class PreSptModLoader implements IModLoader this.vfs.rename(`${modPath}/package.json.bak`, `${modPath}/package.json`); } - protected areModDependenciesFulfilled(pkg: IPackageJsonData, loadedMods: Map): boolean - { - if (!pkg.modDependencies) - { + protected areModDependenciesFulfilled(pkg: IPackageJsonData, loadedMods: Map): boolean { + if (!pkg.modDependencies) { return true; } const modName = `${pkg.author}-${pkg.name}`; - for (const [modDependency, requiredVersion] of Object.entries(pkg.modDependencies)) - { + for (const [modDependency, requiredVersion] of Object.entries(pkg.modDependencies)) { // Raise dependency version incompatible if the dependency is not found in the mod list - if (!loadedMods.has(modDependency)) - { + if (!loadedMods.has(modDependency)) { this.logger.error( this.localisationService.getText("modloader-missing_dependency", { mod: modName, @@ -584,8 +516,7 @@ export class PreSptModLoader implements IModLoader return false; } - if (!satisfies(loadedMods.get(modDependency).version, requiredVersion)) - { + if (!satisfies(loadedMods.get(modDependency).version, requiredVersion)) { this.logger.error( this.localisationService.getText("modloader-outdated_dependency", { mod: modName, @@ -601,19 +532,15 @@ export class PreSptModLoader implements IModLoader return true; } - protected isModCompatible(mod: IPackageJsonData, loadedMods: Map): boolean - { + protected isModCompatible(mod: IPackageJsonData, loadedMods: Map): boolean { const incompatbileModsList = mod.incompatibilities; - if (!incompatbileModsList) - { + if (!incompatbileModsList) { return true; } - for (const incompatibleModName of incompatbileModsList) - { + for (const incompatibleModName of incompatbileModsList) { // Raise dependency version incompatible if any incompatible mod is found - if (loadedMods.has(incompatibleModName)) - { + if (loadedMods.has(incompatibleModName)) { this.logger.error( this.localisationService.getText("modloader-incompatible_mod_found", { author: mod.author, @@ -633,8 +560,7 @@ export class PreSptModLoader implements IModLoader * @param modName name of mod in /mods/ to validate * @returns true if valid */ - protected validMod(modName: string): boolean - { + protected validMod(modName: string): boolean { const modPath = this.getModPath(modName); const modIsCalledBepinEx = modName.toLowerCase() === "bepinex"; @@ -644,22 +570,19 @@ export class PreSptModLoader implements IModLoader const hasBepinExFolderStructure = this.vfs.exists(`${modPath}/plugins`); const containsDll = this.vfs.getFiles(`${modPath}`).find((x) => x.includes(".dll")); - if (modIsCalledSrc || modIsCalledDb || modIsCalledUser) - { + if (modIsCalledSrc || modIsCalledDb || modIsCalledUser) { this.logger.error(this.localisationService.getText("modloader-not_correct_mod_folder", modName)); return false; } - if (modIsCalledBepinEx || hasBepinExFolderStructure || containsDll) - { + if (modIsCalledBepinEx || hasBepinExFolderStructure || containsDll) { this.logger.error(this.localisationService.getText("modloader-is_client_mod", modName)); return false; } // Check if config exists const modPackagePath = `${modPath}/package.json`; - if (!this.vfs.exists(modPackagePath)) - { + if (!this.vfs.exists(modPackagePath)) { this.logger.error(this.localisationService.getText("modloader-missing_package_json", modName)); return false; } @@ -669,10 +592,8 @@ export class PreSptModLoader implements IModLoader const checks = ["name", "author", "version", "license"]; let issue = false; - for (const check of checks) - { - if (!(check in config)) - { + for (const check of checks) { + if (!(check in config)) { this.logger.error( this.localisationService.getText("modloader-missing_package_json_property", { modName: modName, @@ -683,29 +604,24 @@ export class PreSptModLoader implements IModLoader } } - if (!valid(config.version)) - { + if (!valid(config.version)) { this.logger.error(this.localisationService.getText("modloader-invalid_version_property", modName)); issue = true; } - if ("main" in config) - { - if (config.main.split(".").pop() !== "js") - { + if ("main" in config) { + if (config.main.split(".").pop() !== "js") { // expects js file as entry this.logger.error(this.localisationService.getText("modloader-main_property_not_js", modName)); issue = true; } - if (!this.vfs.exists(`${modPath}/${config.main}`)) - { + if (!this.vfs.exists(`${modPath}/${config.main}`)) { // If TS file exists with same name, dont perform check as we'll generate JS from TS file const tsFileName = config.main.replace(".js", ".ts"); const tsFileExists = this.vfs.exists(`${modPath}/${tsFileName}`); - if (!tsFileExists) - { + if (!tsFileExists) { this.logger.error( this.localisationService.getText("modloader-main_property_points_to_nothing", modName), ); @@ -714,8 +630,7 @@ export class PreSptModLoader implements IModLoader } } - if (config.incompatibilities && !Array.isArray(config.incompatibilities)) - { + if (config.incompatibilities && !Array.isArray(config.incompatibilities)) { this.logger.error( this.localisationService.getText("modloader-incompatibilities_not_string_array", modName), ); @@ -725,10 +640,8 @@ export class PreSptModLoader implements IModLoader return !issue; } - public getContainer(): DependencyContainer - { - if (this.container) - { + public getContainer(): DependencyContainer { + if (this.container) { return this.container; } diff --git a/project/src/models/common/MinMax.ts b/project/src/models/common/MinMax.ts index 41a26ac6..bc118a89 100644 --- a/project/src/models/common/MinMax.ts +++ b/project/src/models/common/MinMax.ts @@ -1,5 +1,4 @@ -export interface MinMax -{ - max: number - min: number +export interface MinMax { + max: number; + min: number; } diff --git a/project/src/models/eft/bot/IGenerateBotsRequestData.ts b/project/src/models/eft/bot/IGenerateBotsRequestData.ts index f2181dcc..46bbc9ed 100644 --- a/project/src/models/eft/bot/IGenerateBotsRequestData.ts +++ b/project/src/models/eft/bot/IGenerateBotsRequestData.ts @@ -1,12 +1,10 @@ -export interface IGenerateBotsRequestData -{ - conditions: Condition[] +export interface IGenerateBotsRequestData { + conditions: Condition[]; } -export interface Condition -{ +export interface Condition { /** e.g. assault/pmcBot/bossKilla */ - Role: string - Limit: number - Difficulty: string + Role: string; + Limit: number; + Difficulty: string; } diff --git a/project/src/models/eft/bot/IRandomisedBotLevelResult.ts b/project/src/models/eft/bot/IRandomisedBotLevelResult.ts index ccbcd60e..75bd9365 100644 --- a/project/src/models/eft/bot/IRandomisedBotLevelResult.ts +++ b/project/src/models/eft/bot/IRandomisedBotLevelResult.ts @@ -1,5 +1,4 @@ -export interface IRandomisedBotLevelResult -{ - level: number - exp: number +export interface IRandomisedBotLevelResult { + level: number; + exp: number; } diff --git a/project/src/models/eft/builds/ISetMagazineRequest.ts b/project/src/models/eft/builds/ISetMagazineRequest.ts index 2359233e..59da486c 100644 --- a/project/src/models/eft/builds/ISetMagazineRequest.ts +++ b/project/src/models/eft/builds/ISetMagazineRequest.ts @@ -1,11 +1,10 @@ import { IMagazineTemplateAmmoItem } from "@spt/models/eft/profile/ISptProfile"; -export interface ISetMagazineRequest -{ - Id: string - Name: string - Caliber: string - Items: IMagazineTemplateAmmoItem[] - TopCount: number - BottomCount: number +export interface ISetMagazineRequest { + Id: string; + Name: string; + Caliber: string; + Items: IMagazineTemplateAmmoItem[]; + TopCount: number; + BottomCount: number; } diff --git a/project/src/models/eft/common/IEmptyRequestData.ts b/project/src/models/eft/common/IEmptyRequestData.ts index 4892c11d..52a7b126 100644 --- a/project/src/models/eft/common/IEmptyRequestData.ts +++ b/project/src/models/eft/common/IEmptyRequestData.ts @@ -1,2 +1 @@ -export interface IEmptyRequestData -{} +export type IEmptyRequestData = {}; diff --git a/project/src/models/eft/common/IGlobals.ts b/project/src/models/eft/common/IGlobals.ts index a1667aaf..5d605c53 100644 --- a/project/src/models/eft/common/IGlobals.ts +++ b/project/src/models/eft/common/IGlobals.ts @@ -1,1931 +1,1756 @@ import { Ixyz } from "@spt/models/eft/common/Ixyz"; import { Item } from "@spt/models/eft/common/tables/IItem"; -export interface IGlobals -{ - time: number - config: IConfig - bot_presets: IBotPreset[] - AudioSettings: IAudioSettings - EnvironmentSettings: IEnvironmentSettings - BotWeaponScatterings: IBotWeaponScattering[] - ItemPresets: Record -} - -export interface IConfig -{ - content: IContent - AimPunchMagnitude: number - WeaponSkillProgressRate: number - SkillAtrophy: boolean - exp: IExp - t_base_looting: number - t_base_lockpicking: number - armor: IArmor - SessionsToShowHotKeys: number - MaxBotsAliveOnMap: number - MaxBotsAliveOnMapPvE: number - SavagePlayCooldown: number - SavagePlayCooldownNdaFree: number - MarksmanAccuracy: number - SavagePlayCooldownDevelop: number - TODSkyDate: string - Mastering: IMastering[] - GlobalItemPriceModifier: number - TradingUnlimitedItems: boolean - MaxLoyaltyLevelForAll: boolean - GlobalLootChanceModifier: number - GlobalLootChanceModifierPvE: number - GraphicSettings: IGraphicSettings - TimeBeforeDeploy: number - TimeBeforeDeployLocal: number - TradingSetting: number - TradingSettings: ITradingSettings - ItemsCommonSettings: IItemsCommonSettings - LoadTimeSpeedProgress: number - BaseLoadTime: number - BaseUnloadTime: number - BaseCheckTime: number - BluntDamageReduceFromSoftArmorMod: number - BodyPartColliderSettings: IBodyPartColliderSettings - Customization: ICustomization - UncheckOnShot: boolean - BotsEnabled: boolean - BufferZone: IBufferZone - Airdrop: IAirdropGlobalSettings - ArmorMaterials: IArmorMaterials - ArenaEftTransferSettings: IArenaEftTransferSettings - LegsOverdamage: number - HandsOverdamage: number - StomachOverdamage: number - Health: IHealth - rating: IRating - tournament: ITournament - QuestSettings: IQuestSettings - RagFair: IRagFair - handbook: IHandbook - FractureCausedByFalling: IProbability - FractureCausedByBulletHit: IProbability - WAVE_COEF_LOW: number - WAVE_COEF_MID: number - WAVE_COEF_HIGH: number - WAVE_COEF_HORDE: number - Stamina: IStamina - StaminaRestoration: IStaminaRestoration - StaminaDrain: IStaminaDrain - RequirementReferences: IRequirementReferences - RestrictionsInRaid: IRestrictionsInRaid[] - SkillMinEffectiveness: number - SkillFatiguePerPoint: number - SkillFreshEffectiveness: number - SkillFreshPoints: number - SkillPointsBeforeFatigue: number - SkillFatigueReset: number - DiscardLimitsEnabled: boolean - EnvironmentSettings: IEnvironmentSetting2 - EventSettings: IEventSettings - FavoriteItemsSettings: IFavoriteItemsSettings - VaultingSettings: IVaultingSettings - BTRSettings: IBTRSettings - EventType: string[] - WalkSpeed: Ixyz - SprintSpeed: Ixyz - SquadSettings: ISquadSettings - SkillEnduranceWeightThreshold: number - TeamSearchingTimeout: number - Insurance: IInsurance - SkillExpPerLevel: number - GameSearchingTimeout: number - WallContusionAbsorption: Ixyz - WeaponFastDrawSettings: IWeaponFastDrawSettings - SkillsSettings: ISkillsSettings - AzimuthPanelShowsPlayerOrientation: boolean - Aiming: IAiming - Malfunction: IMalfunction - Overheat: IOverheat - FenceSettings: IFenceSettings - TestValue: number - Inertia: IInertia - Ballistic: IBallistic - RepairSettings: IRepairSettings -} - -export interface IEnvironmentSetting2 -{ - EnvironmentUIData: IEnvironmentUIData -} - -export interface IEnvironmentUIData -{ - TheUnheardEditionEnvironmentUiType: string[] -} - -export interface IBodyPartColliderSettings -{ - BackHead: IBodyPartColliderPart - Ears: IBodyPartColliderPart - Eyes: IBodyPartColliderPart - HeadCommon: IBodyPartColliderPart - Jaw: IBodyPartColliderPart - LeftCalf: IBodyPartColliderPart - LeftForearm: IBodyPartColliderPart - LeftSideChestDown: IBodyPartColliderPart - LeftSideChestUp: IBodyPartColliderPart - LeftThigh: IBodyPartColliderPart - LeftUpperArm: IBodyPartColliderPart - NeckBack: IBodyPartColliderPart - NeckFront: IBodyPartColliderPart - ParietalHead: IBodyPartColliderPart - Pelvis: IBodyPartColliderPart - PelvisBack: IBodyPartColliderPart - RibcageLow: IBodyPartColliderPart - RibcageUp: IBodyPartColliderPart - RightCalf: IBodyPartColliderPart - RightForearm: IBodyPartColliderPart - RightSideChestDown: IBodyPartColliderPart - RightSideChestUp: IBodyPartColliderPart - RightThigh: IBodyPartColliderPart - RightUpperArm: IBodyPartColliderPart - SpineDown: IBodyPartColliderPart - SpineTop: IBodyPartColliderPart -} - -export interface IBodyPartColliderPart -{ - PenetrationChance: number - PenetrationDamageMod: number - PenetrationLevel: number -} - -export interface IWeaponFastDrawSettings -{ - HandShakeCurveFrequency: number - HandShakeCurveIntensity: number - HandShakeMaxDuration: number - HandShakeTremorIntensity: number - WeaponFastSwitchMaxSpeedMult: number - WeaponFastSwitchMinSpeedMult: number - WeaponPistolFastSwitchMaxSpeedMult: number - WeaponPistolFastSwitchMinSpeedMult: number -} - -export interface IEventSettings -{ - EventActive: boolean - EventTime: number - EventWeather: IEventWeather - ExitTimeMultiplier: number - StaminaMultiplier: number - SummonFailedWeather: IEventWeather - SummonSuccessWeather: IEventWeather - WeatherChangeTime: number -} - -export interface IEventWeather -{ - Cloudness: number - Hour: number - Minute: number - Rain: number - RainRandomness: number - ScaterringFogDensity: number - TopWindDirection: Ixyz - Wind: number - WindDirection: number -} - -export interface IGraphicSettings -{ - ExperimentalFogInCity: boolean -} - -export interface IBufferZone -{ - CustomerAccessTime: number - CustomerCriticalTimeStart: number - CustomerKickNotifTime: number -} - -export interface IItemsCommonSettings -{ - ItemRemoveAfterInterruptionTime: number -} - -export interface ITradingSettings -{ - BuyRestrictionMaxBonus: Record - BuyoutRestrictions: IBuyoutRestrictions -} - -export interface IBuyRestrictionMaxBonus -{ - multiplier: number -} - -export interface IBuyoutRestrictions -{ - MinDurability: number - MinFoodDrinkResource: number - MinMedsResource: number -} - -export interface IContent -{ - ip: string - port: number - root: string -} - -export interface IExp -{ - heal: IHeal - match_end: IMatchEnd - kill: IKill - level: ILevel - loot_attempts: ILootAttempt[] - expForLevelOneDogtag: number - expForLockedDoorOpen: number - expForLockedDoorBreach: number - triggerMult: number -} - -export interface IHeal -{ - expForHeal: number - expForHydration: number - expForEnergy: number -} - -export interface IMatchEnd -{ - README: string - survived_exp_requirement: number - survived_seconds_requirement: number - survived_exp_reward: number - mia_exp_reward: number - runner_exp_reward: number - leftMult: number - miaMult: number - survivedMult: number - runnerMult: number - killedMult: number -} - -export interface IKill -{ - combo: ICombo[] - victimLevelExp: number - headShotMult: number - expOnDamageAllHealth: number - longShotDistance: number - bloodLossToLitre: number - botExpOnDamageAllHealth: number - botHeadShotMult: number - victimBotLevelExp: number - pmcExpOnDamageAllHealth: number - pmcHeadShotMult: number -} - -export interface ICombo -{ - percent: number -} - -export interface ILevel -{ - exp_table: IExpTable[] - trade_level: number - savage_level: number - clan_level: number - mastering1: number - mastering2: number -} - -export interface IExpTable -{ - exp: number -} - -export interface ILootAttempt -{ - k_exp: number -} - -export interface IArmor -{ - class: IClass[] -} - -export interface IClass -{ - resistance: number -} - -export interface IMastering -{ - Name: string - Templates: string[] - Level2: number - Level3: number -} - -export interface ICustomization -{ - SavageHead: ISavageHead - SavageBody: ISavageBody - SavageFeet: ISavageFeet - CustomizationVoice: ICustomizationVoice[] - BodyParts: IBodyParts -} - -export interface ISavageHead -{ - wild_head_1: IWildHead - wild_head_2: IWildHead - wild_head_3: IWildHead - Wild_Dealmaker_head: IWildHead - Wild_Killa_head: IWildHead - bear_head: IWildHead - bear_head_1: IWildHead - usec_head_1: IWildHead - Head_BOSS_Glukhar: IWildHead - Wild_Head_nonMesh: IWildHead - Head_BOSS_Sanitar: IWildHead - wild_head_drozd: IWildHead - wild_head_misha: IWildHead - head_cultist_01: IWildHead - head_cultist_02: IWildHead - head_cultist_03: IWildHead - DefaultUsecHead: IWildHead - usec_head_3: IWildHead - usec_head_4: IWildHead - usec_head_5: IWildHead -} - -export interface IWildHead -{ - head: string - isNotRandom: boolean - NotRandom: boolean -} - -export interface ISavageBody -{ - wild_body: IWildBody - wild_body_1: IWildBody - wild_body_2: IWildBody - wild_body_3: IWildBody - Wild_Dealmaker_body: IWildBody - wild_security_body_1: IWildBody - wild_security_body_2: IWildBody - wild_Killa_body: IWildBody - wild_pmcBot_body: IWildBody - wild_Shturman_body: IWildBody - wild_Gluhar_body: IWildBody - Tshirt_security_TshirtTatu_01: IWildBody - Tshirt_security_TshirtTatu_02: IWildBody - Top_security_Husky: IWildBody - Top_security_Gorka4: IWildBody - scav_kit_upper_meteor: IWildBody - wild_body_russia1: IWildBody - Top_BOSS_Sanitar: IWildBody - wild_body_motocross: IWildBody - top_cultist_01: IWildBody - top_cultist_02: IWildBody - wild_body_rainparka: IWildBody - wild_body_underarmour: IWildBody - top_boss_tagilla: IWildBody - DefaultUsecBody: IWildBody - usec_upper_acu: IWildBody - usec_upper_commando: IWildBody - usec_upper_aggressor: IWildBody - usec_upper_hoody: IWildBody - usec_upper_pcuironsight: IWildBody - usec_top_beltstaff: IWildBody - usec_upper_flexion: IWildBody - usec_upper_tier3: IWildBody - usec_upper_pcsmulticam: IWildBody - usec_upper_tier_2: IWildBody - usec_upper_infiltrator: IWildBody - user_upper_NightPatrol: IWildBody - wild_body_bomber: IWildBody - wild_top_yellowcoat: IWildBody -} - -export interface IWildBody -{ - body: string - hands: string - isNotRandom: boolean -} - -export interface ISavageFeet -{ - wild_feet: IWildFeet - wild_feet_1: IWildFeet - wild_feet_2: IWildFeet - Wild_Dealmaker_feet: IWildFeet - wild_security_feet_1: IWildFeet - Wild_Killa_feet: IWildFeet - wild_pmcBot_feet: IWildFeet - Pants_BOSS_Glukhar: IWildFeet - Pants_BOSS_Shturman: IWildFeet - Pants_security_Gorka4: IWildFeet - Pants_security_Flora: IWildFeet - scav_kit_lower_sklon: IWildFeet - Pants_BOSS_Sanitar: IWildFeet - wild_feet_sweatpants: IWildFeet - wild_feet_wasatch: IWildFeet - wild_feet_slimPants: IWildFeet - pants_cultist_01: IWildFeet - pants_cultist_02: IWildFeet - wild_feet_scavelite_taclite: IWildFeet - pants_boss_tagilla: IWildFeet - wild_feet_bomber: IWildFeet - wild_pants_yellowcoat: IWildFeet -} - -export interface IWildFeet -{ - feet: string - isNotRandom: boolean - NotRandom: boolean -} - -export interface ICustomizationVoice -{ - voice: string - side: string[] - isNotRandom: boolean -} - -export interface IBodyParts -{ - Head: string - Body: string - Feet: string - Hands: string -} - -export interface IAirdropGlobalSettings -{ - ParachuteEndOpenHeight: number - ParachuteStartOpenHeight: number - PlaneAdditionalDistance: number - PlaneAirdropDuration: number - PlaneAirdropFlareWait: number - PlaneAirdropSmoke: number - PlaneMaxFlightHeight: number - PlaneMinFlightHeight: number - PlaneSpeed: number - SmokeActivateHeight: number -} - -export interface IArenaEftTransferSettings -{ - ArenaEftTransferSettings: ArenaEftTransferSettings -} - -export interface ArenaEftTransferSettings -{ - ArenaManagerReputationTaxMultiplier: number - CharismaTaxMultiplier: number - CreditPriceTaxMultiplier: number - RubTaxMultiplier: number - TransferLimitsByGameEdition: Record - TransferLimitsSettings: Record -} - -export interface IArmorMaterials -{ - UHMWPE: IArmorType - Aramid: IArmorType - Combined: IArmorType - Titan: IArmorType - Aluminium: IArmorType - ArmoredSteel: IArmorType - Ceramic: IArmorType - Glass: IArmorType -} - -export interface IArmorType -{ - Destructibility: number - MinRepairDegradation: number - MaxRepairDegradation: number - ExplosionDestructibility: number - MinRepairKitDegradation: number - MaxRepairKitDegradation: number -} - -export interface IHealth -{ - Falling: IFalling - Effects: IEffects - HealPrice: IHealPrice - ProfileHealthSettings: IProfileHealthSettings -} - -export interface IFalling -{ - DamagePerMeter: number - SafeHeight: number -} - -export interface IEffects -{ - Existence: IExistence - Dehydration: IDehydration - BreakPart: IBreakPart - Contusion: IContusion - Disorientation: IDisorientation - Exhaustion: IExhaustion - LowEdgeHealth: ILowEdgeHealth - RadExposure: IRadExposure - Stun: IStun - Intoxication: Intoxication - Regeneration: IRegeneration - Wound: IWound - Berserk: IBerserk - Flash: IFlash - MedEffect: IMedEffect - Pain: IPain - PainKiller: IPainKiller - SandingScreen: ISandingScreen - MildMusclePain: IMusclePainEffect - SevereMusclePain: IMusclePainEffect - Stimulator: IStimulator - Tremor: ITremor - ChronicStaminaFatigue: IChronicStaminaFatigue - Fracture: IFracture - HeavyBleeding: IHeavyBleeding - LightBleeding: ILightBleeding - BodyTemperature: IBodyTemperature -} - -export interface IExistence -{ - EnergyLoopTime: number - HydrationLoopTime: number - EnergyDamage: number - HydrationDamage: number - DestroyedStomachEnergyTimeFactor: number - DestroyedStomachHydrationTimeFactor: number -} - -export interface IDehydration -{ - DefaultDelay: number - DefaultResidueTime: number - BleedingHealth: number - BleedingLoopTime: number - BleedingLifeTime: number - DamageOnStrongDehydration: number - StrongDehydrationLoopTime: number -} - -export interface IBreakPart -{ - DefaultDelay: number - DefaultResidueTime: number - HealExperience: number - OfflineDurationMin: number - OfflineDurationMax: number - RemovePrice: number - RemovedAfterDeath: boolean - BulletHitProbability: IProbability - FallingProbability: IProbability -} - -export interface IContusion -{ - Dummy: number -} - -export interface IDisorientation -{ - Dummy: number -} - -export interface IExhaustion -{ - DefaultDelay: number - DefaultResidueTime: number - Damage: number - DamageLoopTime: number -} - -export interface ILowEdgeHealth -{ - DefaultDelay: number - DefaultResidueTime: number - StartCommonHealth: number -} - -export interface IRadExposure -{ - Damage: number - DamageLoopTime: number -} - -export interface IStun -{ - Dummy: number -} - -export interface Intoxication -{ - DefaultDelay: number - DefaultResidueTime: number - DamageHealth: number - HealthLoopTime: number - OfflineDurationMin: number - OfflineDurationMax: number - RemovedAfterDeath: boolean - HealExperience: number - RemovePrice: number -} - -export interface IRegeneration -{ - LoopTime: number - MinimumHealthPercentage: number - Energy: number - Hydration: number - BodyHealth: IBodyHealth - Influences: IInfluences +export interface IGlobals { + time: number; + config: IConfig; + bot_presets: IBotPreset[]; + AudioSettings: IAudioSettings; + EnvironmentSettings: IEnvironmentSettings; + BotWeaponScatterings: IBotWeaponScattering[]; + ItemPresets: Record; +} + +export interface IConfig { + content: IContent; + AimPunchMagnitude: number; + WeaponSkillProgressRate: number; + SkillAtrophy: boolean; + exp: IExp; + t_base_looting: number; + t_base_lockpicking: number; + armor: IArmor; + SessionsToShowHotKeys: number; + MaxBotsAliveOnMap: number; + MaxBotsAliveOnMapPvE: number; + SavagePlayCooldown: number; + SavagePlayCooldownNdaFree: number; + MarksmanAccuracy: number; + SavagePlayCooldownDevelop: number; + TODSkyDate: string; + Mastering: IMastering[]; + GlobalItemPriceModifier: number; + TradingUnlimitedItems: boolean; + MaxLoyaltyLevelForAll: boolean; + GlobalLootChanceModifier: number; + GlobalLootChanceModifierPvE: number; + GraphicSettings: IGraphicSettings; + TimeBeforeDeploy: number; + TimeBeforeDeployLocal: number; + TradingSetting: number; + TradingSettings: ITradingSettings; + ItemsCommonSettings: IItemsCommonSettings; + LoadTimeSpeedProgress: number; + BaseLoadTime: number; + BaseUnloadTime: number; + BaseCheckTime: number; + BluntDamageReduceFromSoftArmorMod: number; + BodyPartColliderSettings: IBodyPartColliderSettings; + Customization: ICustomization; + UncheckOnShot: boolean; + BotsEnabled: boolean; + BufferZone: IBufferZone; + Airdrop: IAirdropGlobalSettings; + ArmorMaterials: IArmorMaterials; + ArenaEftTransferSettings: IArenaEftTransferSettings; + LegsOverdamage: number; + HandsOverdamage: number; + StomachOverdamage: number; + Health: IHealth; + rating: IRating; + tournament: ITournament; + QuestSettings: IQuestSettings; + RagFair: IRagFair; + handbook: IHandbook; + FractureCausedByFalling: IProbability; + FractureCausedByBulletHit: IProbability; + WAVE_COEF_LOW: number; + WAVE_COEF_MID: number; + WAVE_COEF_HIGH: number; + WAVE_COEF_HORDE: number; + Stamina: IStamina; + StaminaRestoration: IStaminaRestoration; + StaminaDrain: IStaminaDrain; + RequirementReferences: IRequirementReferences; + RestrictionsInRaid: IRestrictionsInRaid[]; + SkillMinEffectiveness: number; + SkillFatiguePerPoint: number; + SkillFreshEffectiveness: number; + SkillFreshPoints: number; + SkillPointsBeforeFatigue: number; + SkillFatigueReset: number; + DiscardLimitsEnabled: boolean; + EnvironmentSettings: IEnvironmentSetting2; + EventSettings: IEventSettings; + FavoriteItemsSettings: IFavoriteItemsSettings; + VaultingSettings: IVaultingSettings; + BTRSettings: IBTRSettings; + EventType: string[]; + WalkSpeed: Ixyz; + SprintSpeed: Ixyz; + SquadSettings: ISquadSettings; + SkillEnduranceWeightThreshold: number; + TeamSearchingTimeout: number; + Insurance: IInsurance; + SkillExpPerLevel: number; + GameSearchingTimeout: number; + WallContusionAbsorption: Ixyz; + WeaponFastDrawSettings: IWeaponFastDrawSettings; + SkillsSettings: ISkillsSettings; + AzimuthPanelShowsPlayerOrientation: boolean; + Aiming: IAiming; + Malfunction: IMalfunction; + Overheat: IOverheat; + FenceSettings: IFenceSettings; + TestValue: number; + Inertia: IInertia; + Ballistic: IBallistic; + RepairSettings: IRepairSettings; +} + +export interface IEnvironmentSetting2 { + EnvironmentUIData: IEnvironmentUIData; +} + +export interface IEnvironmentUIData { + TheUnheardEditionEnvironmentUiType: string[]; +} + +export interface IBodyPartColliderSettings { + BackHead: IBodyPartColliderPart; + Ears: IBodyPartColliderPart; + Eyes: IBodyPartColliderPart; + HeadCommon: IBodyPartColliderPart; + Jaw: IBodyPartColliderPart; + LeftCalf: IBodyPartColliderPart; + LeftForearm: IBodyPartColliderPart; + LeftSideChestDown: IBodyPartColliderPart; + LeftSideChestUp: IBodyPartColliderPart; + LeftThigh: IBodyPartColliderPart; + LeftUpperArm: IBodyPartColliderPart; + NeckBack: IBodyPartColliderPart; + NeckFront: IBodyPartColliderPart; + ParietalHead: IBodyPartColliderPart; + Pelvis: IBodyPartColliderPart; + PelvisBack: IBodyPartColliderPart; + RibcageLow: IBodyPartColliderPart; + RibcageUp: IBodyPartColliderPart; + RightCalf: IBodyPartColliderPart; + RightForearm: IBodyPartColliderPart; + RightSideChestDown: IBodyPartColliderPart; + RightSideChestUp: IBodyPartColliderPart; + RightThigh: IBodyPartColliderPart; + RightUpperArm: IBodyPartColliderPart; + SpineDown: IBodyPartColliderPart; + SpineTop: IBodyPartColliderPart; +} + +export interface IBodyPartColliderPart { + PenetrationChance: number; + PenetrationDamageMod: number; + PenetrationLevel: number; +} + +export interface IWeaponFastDrawSettings { + HandShakeCurveFrequency: number; + HandShakeCurveIntensity: number; + HandShakeMaxDuration: number; + HandShakeTremorIntensity: number; + WeaponFastSwitchMaxSpeedMult: number; + WeaponFastSwitchMinSpeedMult: number; + WeaponPistolFastSwitchMaxSpeedMult: number; + WeaponPistolFastSwitchMinSpeedMult: number; +} + +export interface IEventSettings { + EventActive: boolean; + EventTime: number; + EventWeather: IEventWeather; + ExitTimeMultiplier: number; + StaminaMultiplier: number; + SummonFailedWeather: IEventWeather; + SummonSuccessWeather: IEventWeather; + WeatherChangeTime: number; +} + +export interface IEventWeather { + Cloudness: number; + Hour: number; + Minute: number; + Rain: number; + RainRandomness: number; + ScaterringFogDensity: number; + TopWindDirection: Ixyz; + Wind: number; + WindDirection: number; +} + +export interface IGraphicSettings { + ExperimentalFogInCity: boolean; +} + +export interface IBufferZone { + CustomerAccessTime: number; + CustomerCriticalTimeStart: number; + CustomerKickNotifTime: number; +} + +export interface IItemsCommonSettings { + ItemRemoveAfterInterruptionTime: number; +} + +export interface ITradingSettings { + BuyRestrictionMaxBonus: Record; + BuyoutRestrictions: IBuyoutRestrictions; +} + +export interface IBuyRestrictionMaxBonus { + multiplier: number; +} + +export interface IBuyoutRestrictions { + MinDurability: number; + MinFoodDrinkResource: number; + MinMedsResource: number; +} + +export interface IContent { + ip: string; + port: number; + root: string; +} + +export interface IExp { + heal: IHeal; + match_end: IMatchEnd; + kill: IKill; + level: ILevel; + loot_attempts: ILootAttempt[]; + expForLevelOneDogtag: number; + expForLockedDoorOpen: number; + expForLockedDoorBreach: number; + triggerMult: number; +} + +export interface IHeal { + expForHeal: number; + expForHydration: number; + expForEnergy: number; +} + +export interface IMatchEnd { + README: string; + survived_exp_requirement: number; + survived_seconds_requirement: number; + survived_exp_reward: number; + mia_exp_reward: number; + runner_exp_reward: number; + leftMult: number; + miaMult: number; + survivedMult: number; + runnerMult: number; + killedMult: number; +} + +export interface IKill { + combo: ICombo[]; + victimLevelExp: number; + headShotMult: number; + expOnDamageAllHealth: number; + longShotDistance: number; + bloodLossToLitre: number; + botExpOnDamageAllHealth: number; + botHeadShotMult: number; + victimBotLevelExp: number; + pmcExpOnDamageAllHealth: number; + pmcHeadShotMult: number; +} + +export interface ICombo { + percent: number; +} + +export interface ILevel { + exp_table: IExpTable[]; + trade_level: number; + savage_level: number; + clan_level: number; + mastering1: number; + mastering2: number; +} + +export interface IExpTable { + exp: number; +} + +export interface ILootAttempt { + k_exp: number; +} + +export interface IArmor { + class: IClass[]; +} + +export interface IClass { + resistance: number; +} + +export interface IMastering { + Name: string; + Templates: string[]; + Level2: number; + Level3: number; +} + +export interface ICustomization { + SavageHead: ISavageHead; + SavageBody: ISavageBody; + SavageFeet: ISavageFeet; + CustomizationVoice: ICustomizationVoice[]; + BodyParts: IBodyParts; +} + +export interface ISavageHead { + wild_head_1: IWildHead; + wild_head_2: IWildHead; + wild_head_3: IWildHead; + Wild_Dealmaker_head: IWildHead; + Wild_Killa_head: IWildHead; + bear_head: IWildHead; + bear_head_1: IWildHead; + usec_head_1: IWildHead; + Head_BOSS_Glukhar: IWildHead; + Wild_Head_nonMesh: IWildHead; + Head_BOSS_Sanitar: IWildHead; + wild_head_drozd: IWildHead; + wild_head_misha: IWildHead; + head_cultist_01: IWildHead; + head_cultist_02: IWildHead; + head_cultist_03: IWildHead; + DefaultUsecHead: IWildHead; + usec_head_3: IWildHead; + usec_head_4: IWildHead; + usec_head_5: IWildHead; +} + +export interface IWildHead { + head: string; + isNotRandom: boolean; + NotRandom: boolean; +} + +export interface ISavageBody { + wild_body: IWildBody; + wild_body_1: IWildBody; + wild_body_2: IWildBody; + wild_body_3: IWildBody; + Wild_Dealmaker_body: IWildBody; + wild_security_body_1: IWildBody; + wild_security_body_2: IWildBody; + wild_Killa_body: IWildBody; + wild_pmcBot_body: IWildBody; + wild_Shturman_body: IWildBody; + wild_Gluhar_body: IWildBody; + Tshirt_security_TshirtTatu_01: IWildBody; + Tshirt_security_TshirtTatu_02: IWildBody; + Top_security_Husky: IWildBody; + Top_security_Gorka4: IWildBody; + scav_kit_upper_meteor: IWildBody; + wild_body_russia1: IWildBody; + Top_BOSS_Sanitar: IWildBody; + wild_body_motocross: IWildBody; + top_cultist_01: IWildBody; + top_cultist_02: IWildBody; + wild_body_rainparka: IWildBody; + wild_body_underarmour: IWildBody; + top_boss_tagilla: IWildBody; + DefaultUsecBody: IWildBody; + usec_upper_acu: IWildBody; + usec_upper_commando: IWildBody; + usec_upper_aggressor: IWildBody; + usec_upper_hoody: IWildBody; + usec_upper_pcuironsight: IWildBody; + usec_top_beltstaff: IWildBody; + usec_upper_flexion: IWildBody; + usec_upper_tier3: IWildBody; + usec_upper_pcsmulticam: IWildBody; + usec_upper_tier_2: IWildBody; + usec_upper_infiltrator: IWildBody; + user_upper_NightPatrol: IWildBody; + wild_body_bomber: IWildBody; + wild_top_yellowcoat: IWildBody; +} + +export interface IWildBody { + body: string; + hands: string; + isNotRandom: boolean; +} + +export interface ISavageFeet { + wild_feet: IWildFeet; + wild_feet_1: IWildFeet; + wild_feet_2: IWildFeet; + Wild_Dealmaker_feet: IWildFeet; + wild_security_feet_1: IWildFeet; + Wild_Killa_feet: IWildFeet; + wild_pmcBot_feet: IWildFeet; + Pants_BOSS_Glukhar: IWildFeet; + Pants_BOSS_Shturman: IWildFeet; + Pants_security_Gorka4: IWildFeet; + Pants_security_Flora: IWildFeet; + scav_kit_lower_sklon: IWildFeet; + Pants_BOSS_Sanitar: IWildFeet; + wild_feet_sweatpants: IWildFeet; + wild_feet_wasatch: IWildFeet; + wild_feet_slimPants: IWildFeet; + pants_cultist_01: IWildFeet; + pants_cultist_02: IWildFeet; + wild_feet_scavelite_taclite: IWildFeet; + pants_boss_tagilla: IWildFeet; + wild_feet_bomber: IWildFeet; + wild_pants_yellowcoat: IWildFeet; +} + +export interface IWildFeet { + feet: string; + isNotRandom: boolean; + NotRandom: boolean; +} + +export interface ICustomizationVoice { + voice: string; + side: string[]; + isNotRandom: boolean; +} + +export interface IBodyParts { + Head: string; + Body: string; + Feet: string; + Hands: string; +} + +export interface IAirdropGlobalSettings { + ParachuteEndOpenHeight: number; + ParachuteStartOpenHeight: number; + PlaneAdditionalDistance: number; + PlaneAirdropDuration: number; + PlaneAirdropFlareWait: number; + PlaneAirdropSmoke: number; + PlaneMaxFlightHeight: number; + PlaneMinFlightHeight: number; + PlaneSpeed: number; + SmokeActivateHeight: number; +} + +export interface IArenaEftTransferSettings { + ArenaEftTransferSettings: ArenaEftTransferSettings; +} + +export interface ArenaEftTransferSettings { + ArenaManagerReputationTaxMultiplier: number; + CharismaTaxMultiplier: number; + CreditPriceTaxMultiplier: number; + RubTaxMultiplier: number; + TransferLimitsByGameEdition: Record; + TransferLimitsSettings: Record; +} + +export interface IArmorMaterials { + UHMWPE: IArmorType; + Aramid: IArmorType; + Combined: IArmorType; + Titan: IArmorType; + Aluminium: IArmorType; + ArmoredSteel: IArmorType; + Ceramic: IArmorType; + Glass: IArmorType; +} + +export interface IArmorType { + Destructibility: number; + MinRepairDegradation: number; + MaxRepairDegradation: number; + ExplosionDestructibility: number; + MinRepairKitDegradation: number; + MaxRepairKitDegradation: number; +} + +export interface IHealth { + Falling: IFalling; + Effects: IEffects; + HealPrice: IHealPrice; + ProfileHealthSettings: IProfileHealthSettings; +} + +export interface IFalling { + DamagePerMeter: number; + SafeHeight: number; +} + +export interface IEffects { + Existence: IExistence; + Dehydration: IDehydration; + BreakPart: IBreakPart; + Contusion: IContusion; + Disorientation: IDisorientation; + Exhaustion: IExhaustion; + LowEdgeHealth: ILowEdgeHealth; + RadExposure: IRadExposure; + Stun: IStun; + Intoxication: Intoxication; + Regeneration: IRegeneration; + Wound: IWound; + Berserk: IBerserk; + Flash: IFlash; + MedEffect: IMedEffect; + Pain: IPain; + PainKiller: IPainKiller; + SandingScreen: ISandingScreen; + MildMusclePain: IMusclePainEffect; + SevereMusclePain: IMusclePainEffect; + Stimulator: IStimulator; + Tremor: ITremor; + ChronicStaminaFatigue: IChronicStaminaFatigue; + Fracture: IFracture; + HeavyBleeding: IHeavyBleeding; + LightBleeding: ILightBleeding; + BodyTemperature: IBodyTemperature; +} + +export interface IExistence { + EnergyLoopTime: number; + HydrationLoopTime: number; + EnergyDamage: number; + HydrationDamage: number; + DestroyedStomachEnergyTimeFactor: number; + DestroyedStomachHydrationTimeFactor: number; +} + +export interface IDehydration { + DefaultDelay: number; + DefaultResidueTime: number; + BleedingHealth: number; + BleedingLoopTime: number; + BleedingLifeTime: number; + DamageOnStrongDehydration: number; + StrongDehydrationLoopTime: number; +} + +export interface IBreakPart { + DefaultDelay: number; + DefaultResidueTime: number; + HealExperience: number; + OfflineDurationMin: number; + OfflineDurationMax: number; + RemovePrice: number; + RemovedAfterDeath: boolean; + BulletHitProbability: IProbability; + FallingProbability: IProbability; +} + +export interface IContusion { + Dummy: number; +} + +export interface IDisorientation { + Dummy: number; +} + +export interface IExhaustion { + DefaultDelay: number; + DefaultResidueTime: number; + Damage: number; + DamageLoopTime: number; +} + +export interface ILowEdgeHealth { + DefaultDelay: number; + DefaultResidueTime: number; + StartCommonHealth: number; +} + +export interface IRadExposure { + Damage: number; + DamageLoopTime: number; +} + +export interface IStun { + Dummy: number; +} + +export interface Intoxication { + DefaultDelay: number; + DefaultResidueTime: number; + DamageHealth: number; + HealthLoopTime: number; + OfflineDurationMin: number; + OfflineDurationMax: number; + RemovedAfterDeath: boolean; + HealExperience: number; + RemovePrice: number; +} + +export interface IRegeneration { + LoopTime: number; + MinimumHealthPercentage: number; + Energy: number; + Hydration: number; + BodyHealth: IBodyHealth; + Influences: IInfluences; +} + +export interface IBodyHealth { + Head: IBodyHealthValue; + Chest: IBodyHealthValue; + Stomach: IBodyHealthValue; + LeftArm: IBodyHealthValue; + RightArm: IBodyHealthValue; + LeftLeg: IBodyHealthValue; + RightLeg: IBodyHealthValue; +} + +export interface IBodyHealthValue { + Value: number; +} + +export interface IInfluences { + LightBleeding: IInfluence; + HeavyBleeding: IInfluence; + Fracture: IInfluence; + RadExposure: IInfluence; + Intoxication: IInfluence; +} + +export interface IInfluence { + HealthSlowDownPercentage: number; + EnergySlowDownPercentage: number; + HydrationSlowDownPercentage: number; +} + +export interface IWound { + WorkingTime: number; + ThresholdMin: number; + ThresholdMax: number; +} + +export interface IBerserk { + DefaultDelay: number; + WorkingTime: number; + DefaultResidueTime: number; +} + +export interface IFlash { + Dummy: number; +} + +export interface IMedEffect { + LoopTime: number; + StartDelay: number; + DrinkStartDelay: number; + FoodStartDelay: number; + DrugsStartDelay: number; + MedKitStartDelay: number; + MedicalStartDelay: number; + StimulatorStartDelay: number; +} + +export interface IPain { + TremorDelay: number; + HealExperience: number; +} + +export interface IPainKiller { + Dummy: number; +} + +export interface ISandingScreen { + Dummy: number; +} + +export interface IMusclePainEffect { + GymEffectivity: number; + OfflineDurationMax: number; + OfflineDurationMin: number; + TraumaChance: number; +} + +export interface IStimulator { + BuffLoopTime: number; + Buffs: IBuffs; +} + +export interface IBuffs { + BuffsSJ1TGLabs: IBuff[]; + BuffsSJ6TGLabs: IBuff[]; + BuffsPropital: IBuff[]; + BuffsZagustin: IBuff[]; + BuffseTGchange: IBuff[]; + BuffsAdrenaline: IBuff[]; + BuffsGoldenStarBalm: IBuff[]; + Buffs_drink_aquamari: IBuff[]; + Buffs_drink_maxenergy: IBuff[]; + Buffs_drink_milk: IBuff[]; + Buffs_drink_tarcola: IBuff[]; + Buffs_drink_hotrod: IBuff[]; + Buffs_drink_juice_army: IBuff[]; + Buffs_drink_water: IBuff[]; + Buffs_food_borodinskiye: IBuff[]; + Buffs_food_condensed_milk: IBuff[]; + Buffs_food_emelya: IBuff[]; + Buffs_food_mayonez: IBuff[]; + Buffs_food_mre: IBuff[]; + Buffs_food_sugar: IBuff[]; + Buffs_drink_vodka: IBuff[]; + Buffs_drink_jack: IBuff[]; + Buffs_drink_moonshine: IBuff[]; + Buffs_drink_purewater: IBuff[]; + Buffs_3bTG: IBuff[]; + Buffs_AHF1M: IBuff[]; + Buffs_L1: IBuff[]; + Buffs_MULE: IBuff[]; + Buffs_Meldonin: IBuff[]; + Buffs_Obdolbos: IBuff[]; + Buffs_P22: IBuff[]; + Buffs_KultistsToxin: IBuff[]; + Buffs_BodyTemperature: IBuff[]; + Buffs_Antidote: IBuff[]; + Buffs_melee_bleed: IBuff[]; + Buffs_melee_blunt: IBuff[]; + Buffs_hultafors: IBuff[]; + Buffs_drink_vodka_BAD: IBuff[]; + Buffs_food_alyonka: IBuff[]; + Buffs_food_slippers: IBuff[]; + Buffs_knife: IBuff[]; + Buffs_EndOfWinterBonfire: IBuff[]; +} + +export interface IBuff { + BuffType: string; + Chance: number; + Delay: number; + Duration: number; + Value: number; + AbsoluteValue: boolean; + SkillName: string; +} + +export interface ITremor { + DefaultDelay: number; + DefaultResidueTime: number; +} + +export interface IChronicStaminaFatigue { + EnergyRate: number; + WorkingTime: number; + TicksEvery: number; + EnergyRatePerStack: number; +} + +export interface IFracture { + DefaultDelay: number; + DefaultResidueTime: number; + HealExperience: number; + OfflineDurationMin: number; + OfflineDurationMax: number; + RemovePrice: number; + RemovedAfterDeath: boolean; + BulletHitProbability: IProbability; + FallingProbability: IProbability; +} + +export interface IHeavyBleeding { + DefaultDelay: number; + DefaultResidueTime: number; + DamageEnergy: number; + DamageHealth: number; + EnergyLoopTime: number; + HealthLoopTime: number; + DamageHealthDehydrated: number; + HealthLoopTimeDehydrated: number; + LifeTimeDehydrated: number; + EliteVitalityDuration: number; + HealExperience: number; + OfflineDurationMin: number; + OfflineDurationMax: number; + RemovePrice: number; + RemovedAfterDeath: boolean; + Probability: IProbability; +} + +export interface IProbability { + FunctionType: string; + K: number; + B: number; + Threshold: number; +} + +export interface ILightBleeding { + DefaultDelay: number; + DefaultResidueTime: number; + DamageEnergy: number; + DamageHealth: number; + EnergyLoopTime: number; + HealthLoopTime: number; + DamageHealthDehydrated: number; + HealthLoopTimeDehydrated: number; + LifeTimeDehydrated: number; + EliteVitalityDuration: number; + HealExperience: number; + OfflineDurationMin: number; + OfflineDurationMax: number; + RemovePrice: number; + RemovedAfterDeath: boolean; + Probability: IProbability; +} + +export interface IBodyTemperature { + DefaultBuildUpTime: number; + DefaultResidueTime: number; + LoopTime: number; +} + +export interface IHealPrice { + HealthPointPrice: number; + HydrationPointPrice: number; + EnergyPointPrice: number; + TrialLevels: number; + TrialRaids: number; +} + +export interface IProfileHealthSettings { + BodyPartsSettings: IBodyPartsSettings; + HealthFactorsSettings: IHealthFactorsSettings; + DefaultStimulatorBuff: string; +} + +export interface IBodyPartsSettings { + Head: IBodyPartsSetting; + Chest: IBodyPartsSetting; + Stomach: IBodyPartsSetting; + LeftArm: IBodyPartsSetting; + RightArm: IBodyPartsSetting; + LeftLeg: IBodyPartsSetting; + RightLeg: IBodyPartsSetting; +} + +export interface IBodyPartsSetting { + Minimum: number; + Maximum: number; + Default: number; + EnvironmentDamageMultiplier: number; + OverDamageReceivedMultiplier: number; +} + +export interface IHealthFactorsSettings { + Energy: IHealthFactorSetting; + Hydration: IHealthFactorSetting; + Temperature: IHealthFactorSetting; + Poisoning: IHealthFactorSetting; + Radiation: IHealthFactorSetting; +} + +export interface IHealthFactorSetting { + Minimum: number; + Maximum: number; + Default: number; +} + +export interface IRating { + levelRequired: number; + limit: number; + categories: ICategories; +} + +export interface ICategories { + experience: boolean; + kd: boolean; + surviveRatio: boolean; + avgEarnings: boolean; + pmcKills: boolean; + raidCount: boolean; + longestShot: boolean; + timeOnline: boolean; + inventoryFullCost: boolean; + ragFairStanding: boolean; +} + +export interface ITournament { + categories: ITournamentCategories; + limit: number; + levelRequired: number; +} + +export interface ITournamentCategories { + dogtags: boolean; +} + +export interface IRagFair { + enabled: boolean; + priceStabilizerEnabled: boolean; + includePveTraderSales: boolean; + priceStabilizerStartIntervalInHours: number; + minUserLevel: number; + communityTax: number; + communityItemTax: number; + communityRequirementTax: number; + offerPriorityCost: number; + offerDurationTimeInHour: number; + offerDurationTimeInHourAfterRemove: number; + priorityTimeModifier: number; + maxRenewOfferTimeInHour: number; + renewPricePerHour: number; + maxActiveOfferCount: IMaxActiveOfferCount[]; + balancerRemovePriceCoefficient: number; + balancerMinPriceCount: number; + balancerAveragePriceCoefficient: number; + delaySinceOfferAdd: number; + uniqueBuyerTimeoutInDays: number; + userRatingChangeFrequencyMultiplayer: number; + ratingSumForIncrease: number; + ratingIncreaseCount: number; + ratingSumForDecrease: number; + ratingDecreaseCount: number; + maxSumForIncreaseRatingPerOneSale: number; + maxSumForDecreaseRatingPerOneSale: number; + maxSumForRarity: IMaxSumForRarity; + ChangePriceCoef: number; + ItemRestrictions: IItemGlobalRestrictions[]; + balancerUserItemSaleCooldownEnabled: boolean; + balancerUserItemSaleCooldown: number; + youSellOfferMaxStorageTimeInHour: number; + yourOfferDidNotSellMaxStorageTimeInHour: number; + isOnlyFoundInRaidAllowed: boolean; + sellInOnePiece: number; +} + +export interface IItemGlobalRestrictions { + MaxFlea: number; + MaxFleaStacked: number; + TemplateId: string; +} + +export interface IMaxActiveOfferCount { + from: number; + to: number; + count: number; + countForSpecialEditions: number; +} + +export interface IMaxSumForRarity { + Common: IRarityMaxSum; + Rare: IRarityMaxSum; + Superrare: IRarityMaxSum; + Not_exist: IRarityMaxSum; +} + +export interface IRarityMaxSum { + value: number; +} + +export interface IHandbook { + defaultCategory: string; +} + +export interface IStamina { + Capacity: number; + SprintDrainRate: number; + BaseRestorationRate: number; + JumpConsumption: number; + GrenadeHighThrow: number; + GrenadeLowThrow: number; + AimDrainRate: number; + AimRangeFinderDrainRate: number; + OxygenCapacity: number; + OxygenRestoration: number; + WalkOverweightLimits: Ixyz; + BaseOverweightLimits: Ixyz; + SprintOverweightLimits: Ixyz; + WalkSpeedOverweightLimits: Ixyz; + CrouchConsumption: Ixyz; + WalkConsumption: Ixyz; + StandupConsumption: Ixyz; + TransitionSpeed: Ixyz; + SprintAccelerationLowerLimit: number; + SprintSpeedLowerLimit: number; + SprintSensitivityLowerLimit: number; + AimConsumptionByPose: Ixyz; + RestorationMultiplierByPose: Ixyz; + OverweightConsumptionByPose: Ixyz; + AimingSpeedMultiplier: number; + WalkVisualEffectMultiplier: number; + WeaponFastSwitchConsumption: number; + HandsCapacity: number; + HandsRestoration: number; + ProneConsumption: number; + BaseHoldBreathConsumption: number; + SoundRadius: Ixyz; + ExhaustedMeleeSpeed: number; + FatigueRestorationRate: number; + FatigueAmountToCreateEffect: number; + ExhaustedMeleeDamageMultiplier: number; + FallDamageMultiplier: number; + SafeHeightOverweight: number; + SitToStandConsumption: number; + StaminaExhaustionCausesJiggle: boolean; + StaminaExhaustionStartsBreathSound: boolean; + StaminaExhaustionRocksCamera: boolean; + HoldBreathStaminaMultiplier: Ixyz; + PoseLevelIncreaseSpeed: Ixyz; + PoseLevelDecreaseSpeed: Ixyz; + PoseLevelConsumptionPerNotch: Ixyz; +} + +export interface IStaminaRestoration { + LowerLeftPoint: number; + LowerRightPoint: number; + LeftPlatoPoint: number; + RightPlatoPoint: number; + RightLimit: number; + ZeroValue: number; +} + +export interface IStaminaDrain { + LowerLeftPoint: number; + LowerRightPoint: number; + LeftPlatoPoint: number; + RightPlatoPoint: number; + RightLimit: number; + ZeroValue: number; +} + +export interface IRequirementReferences { + Alpinist: IAlpinist[]; +} + +export interface IAlpinist { + Requirement: string; + Id: string; + Count: number; + RequiredSlot: string; + RequirementTip: string; +} + +export interface IRestrictionsInRaid { + TemplateId: string; + Value: number; +} + +export interface IFavoriteItemsSettings { + WeaponStandMaxItemsCount: number; + PlaceOfFameMaxItemsCount: number; +} + +export interface IVaultingSettings { + IsActive: boolean; + VaultingInputTime: number; + GridSettings: IVaultingGridSettings; + MovesSettings: IVaultingMovesSettings; +} + +export interface IVaultingGridSettings { + GridSizeX: number; + GridSizeY: number; + GridSizeZ: number; + SteppingLengthX: number; + SteppingLengthY: number; + SteppingLengthZ: number; + GridOffsetX: number; + GridOffsetY: number; + GridOffsetZ: number; + OffsetFactor: number; +} + +export interface IVaultingMovesSettings { + VaultSettings: IVaultingSubMoveSettings; + ClimbSettings: IVaultingSubMoveSettings; +} + +export interface IVaultingSubMoveSettings { + IsActive: boolean; + MaxWithoutHandHeight: number; + SpeedRange: Ixyz; + MoveRestrictions: IMoveRestrictions; + AutoMoveRestrictions: IMoveRestrictions; +} + +export interface IMoveRestrictions { + IsActive: boolean; + MinDistantToInteract: number; + MinHeight: number; + MaxHeight: number; + MinLength: number; + MaxLength: number; +} + +export interface IBTRSettings { + LocationsWithBTR: string[]; + BasePriceTaxi: number; + AddPriceTaxi: number; + CleanUpPrice: number; + DeliveryPrice: number; + ModDeliveryCost: number; + BearPriceMod: number; + UsecPriceMod: number; + ScavPriceMod: number; + CoefficientDiscountCharisma: number; + DeliveryMinPrice: number; + TaxiMinPrice: number; + BotCoverMinPrice: number; + MapsConfigs: Record; + DiameterWheel: number; + HeightWheel: number; + HeightWheelMaxPosLimit: number; + HeightWheelMinPosLimit: number; + SnapToSurfaceWheelsSpeed: number; + CheckSurfaceForWheelsTimer: number; + HeightWheelOffset: number; +} + +export interface IBtrMapConfig { + BtrSkin: string; + CheckSurfaceForWheelsTimer: number; + DiameterWheel: number; + HeightWheel: number; + HeightWheelMaxPosLimit: number; + HeightWheelMinPosLimit: number; + HeightWheelOffset: number; + SnapToSurfaceWheelsSpeed: number; + SuspensionDamperStiffness: number; + SuspensionRestLength: number; + SuspensionSpringStiffness: number; + SuspensionTravel: number; + SuspensionWheelRadius: number; + mapID: string; + pathsConfigurations: IPathConfig[]; +} + +export interface IPathConfig { + active: boolean; + id: string; + enterPoint: string; + exitPoint: string; + pathPoints: string[]; + once: boolean; + circle: boolean; + circleCount: number; +} + +export interface ISquadSettings { + CountOfRequestsToOnePlayer: number; + SecondsForExpiredRequest: number; + SendRequestDelaySeconds: number; +} + +export interface IInsurance { + ChangeForReturnItemsInOfflineRaid: number; + MaxStorageTimeInHour: number; + CoefOfSendingMessageTime: number; + CoefOfHavingMarkOfUnknown: number; + EditionSendingMessageTime: Record; +} + +export interface IMessageSendTImeMultipler { + multiplier: number; +} + +export interface ISkillsSettings { + SkillProgressRate: number; + WeaponSkillProgressRate: number; + WeaponSkillRecoilBonusPerLevel: number; + HideoutManagement: IHideoutManagement; + Crafting: ICrafting; + Metabolism: IMetabolism; + Immunity: Immunity; + Endurance: IEndurance; + Strength: IStrength; + Vitality: IVitality; + Health: IHealthSkillProgress; + StressResistance: IStressResistance; + Throwing: IThrowing; + RecoilControl: IRecoilControl; + Pistol: IWeaponSkills; + Revolver: IWeaponSkills; + SMG: any[]; + Assault: IWeaponSkills; + Shotgun: IWeaponSkills; + Sniper: IWeaponSkills; + LMG: any[]; + HMG: any[]; + Launcher: any[]; + AttachedLauncher: any[]; + Melee: IMeleeSkill; + DMR: IWeaponSkills; + BearAssaultoperations: any[]; + BearAuthority: any[]; + BearAksystems: any[]; + BearHeavycaliber: any[]; + BearRawpower: any[]; + UsecArsystems: any[]; + UsecDeepweaponmodding_Settings: any[]; + UsecLongrangeoptics_Settings: any[]; + UsecNegotiations: any[]; + UsecTactics: any[]; + BotReload: any[]; + CovertMovement: ICovertMovement; + FieldMedicine: any[]; + Search: ISearch; + Sniping: any[]; + ProneMovement: any[]; + FirstAid: any[]; + LightVests: IArmorSkills; + HeavyVests: IArmorSkills; + WeaponModding: any[]; + AdvancedModding: any[]; + NightOps: any[]; + SilentOps: any[]; + Lockpicking: any[]; + WeaponTreatment: IWeaponTreatment; + MagDrills: IMagDrills; + Freetrading: any[]; + Auctions: any[]; + Cleanoperations: any[]; + Barter: any[]; + Shadowconnections: any[]; + Taskperformance: any[]; + Perception: IPerception; + Intellect: Intellect; + Attention: IAttention; + Charisma: ICharisma; + Memory: IMemory; + Surgery: ISurgery; + AimDrills: IAimDrills; + BotSound: any[]; + TroubleShooting: ITroubleShooting; +} + +export interface IMeleeSkill { + BuffSettings: IBuffSettings; +} + +export interface IArmorSkills { + BuffMaxCount: number; + BuffSettings: IBuffSettings; + Counters: IArmorCounters; + MoveSpeedPenaltyReductionHVestsReducePerLevel: number; + RicochetChanceHVestsCurrentDurabilityThreshold: number; + RicochetChanceHVestsEliteLevel: number; + RicochetChanceHVestsMaxDurabilityThreshold: number; + MeleeDamageLVestsReducePerLevel: number; + MoveSpeedPenaltyReductionLVestsReducePerLevel: number; + WearAmountRepairLVestsReducePerLevel: number; + WearChanceRepairLVestsReduceEliteLevel: number; +} + +export interface IArmorCounters { + armorDurability: ISkillCounter; +} + +export interface IHideoutManagement { + SkillPointsPerAreaUpgrade: number; + SkillPointsPerCraft: number; + ConsumptionReductionPerLevel: number; + SkillBoostPercent: number; + SkillPointsRate: ISkillPointsRate; + EliteSlots: IEliteSlots; +} + +export interface ISkillPointsRate { + Generator: ISkillPointRate; + AirFilteringUnit: ISkillPointRate; + WaterCollector: ISkillPointRate; + SolarPower: ISkillPointRate; +} + +export interface ISkillPointRate { + ResourceSpent: number; + PointsGained: number; +} + +export interface IEliteSlots { + Generator: IEliteSlot; + AirFilteringUnit: IEliteSlot; + WaterCollector: IEliteSlot; + BitcoinFarm: IEliteSlot; +} + +export interface IEliteSlot { + Slots: number; + Container: number; +} + +export interface ICrafting { + PointsPerCraftingCycle: number; + CraftingCycleHours: number; + PointsPerUniqueCraftCycle: number; + UniqueCraftsPerCycle: number; + CraftTimeReductionPerLevel: number; + ProductionTimeReductionPerLevel: number; + EliteExtraProductions: number; + CraftingPointsToInteligence: number; +} + +export interface IMetabolism { + HydrationRecoveryRate: number; + EnergyRecoveryRate: number; + IncreasePositiveEffectDurationRate: number; + DecreaseNegativeEffectDurationRate: number; + DecreasePoisonDurationRate: number; +} + +export interface Immunity { + ImmunityMiscEffects: number; + ImmunityPoisonBuff: number; + ImmunityPainKiller: number; + HealthNegativeEffect: number; + StimulatorNegativeBuff: number; +} + +export interface IEndurance { + MovementAction: number; + SprintAction: number; + GainPerFatigueStack: number; + DependentSkillRatios: IDependentSkillRatio[]; + QTELevelMultipliers: Record>; } -export interface IBodyHealth -{ - Head: IBodyHealthValue - Chest: IBodyHealthValue - Stomach: IBodyHealthValue - LeftArm: IBodyHealthValue - RightArm: IBodyHealthValue - LeftLeg: IBodyHealthValue - RightLeg: IBodyHealthValue -} - -export interface IBodyHealthValue -{ - Value: number -} - -export interface IInfluences -{ - LightBleeding: IInfluence - HeavyBleeding: IInfluence - Fracture: IInfluence - RadExposure: IInfluence - Intoxication: IInfluence -} - -export interface IInfluence -{ - HealthSlowDownPercentage: number - EnergySlowDownPercentage: number - HydrationSlowDownPercentage: number -} - -export interface IWound -{ - WorkingTime: number - ThresholdMin: number - ThresholdMax: number -} - -export interface IBerserk -{ - DefaultDelay: number - WorkingTime: number - DefaultResidueTime: number -} - -export interface IFlash -{ - Dummy: number -} - -export interface IMedEffect -{ - LoopTime: number - StartDelay: number - DrinkStartDelay: number - FoodStartDelay: number - DrugsStartDelay: number - MedKitStartDelay: number - MedicalStartDelay: number - StimulatorStartDelay: number -} - -export interface IPain -{ - TremorDelay: number - HealExperience: number -} - -export interface IPainKiller -{ - Dummy: number -} - -export interface ISandingScreen -{ - Dummy: number -} - -export interface IMusclePainEffect -{ - GymEffectivity: number - OfflineDurationMax: number - OfflineDurationMin: number - TraumaChance: number -} - -export interface IStimulator -{ - BuffLoopTime: number - Buffs: IBuffs -} - -export interface IBuffs -{ - BuffsSJ1TGLabs: IBuff[] - BuffsSJ6TGLabs: IBuff[] - BuffsPropital: IBuff[] - BuffsZagustin: IBuff[] - BuffseTGchange: IBuff[] - BuffsAdrenaline: IBuff[] - BuffsGoldenStarBalm: IBuff[] - Buffs_drink_aquamari: IBuff[] - Buffs_drink_maxenergy: IBuff[] - Buffs_drink_milk: IBuff[] - Buffs_drink_tarcola: IBuff[] - Buffs_drink_hotrod: IBuff[] - Buffs_drink_juice_army: IBuff[] - Buffs_drink_water: IBuff[] - Buffs_food_borodinskiye: IBuff[] - Buffs_food_condensed_milk: IBuff[] - Buffs_food_emelya: IBuff[] - Buffs_food_mayonez: IBuff[] - Buffs_food_mre: IBuff[] - Buffs_food_sugar: IBuff[] - Buffs_drink_vodka: IBuff[] - Buffs_drink_jack: IBuff[] - Buffs_drink_moonshine: IBuff[] - Buffs_drink_purewater: IBuff[] - Buffs_3bTG: IBuff[] - Buffs_AHF1M: IBuff[] - Buffs_L1: IBuff[] - Buffs_MULE: IBuff[] - Buffs_Meldonin: IBuff[] - Buffs_Obdolbos: IBuff[] - Buffs_P22: IBuff[] - Buffs_KultistsToxin: IBuff[] - Buffs_BodyTemperature: IBuff[] - Buffs_Antidote: IBuff[] - Buffs_melee_bleed: IBuff[] - Buffs_melee_blunt: IBuff[] - Buffs_hultafors: IBuff[] - Buffs_drink_vodka_BAD: IBuff[] - Buffs_food_alyonka: IBuff[] - Buffs_food_slippers: IBuff[] - Buffs_knife: IBuff[] - Buffs_EndOfWinterBonfire: IBuff[] -} - -export interface IBuff -{ - BuffType: string - Chance: number - Delay: number - Duration: number - Value: number - AbsoluteValue: boolean - SkillName: string -} - -export interface ITremor -{ - DefaultDelay: number - DefaultResidueTime: number -} - -export interface IChronicStaminaFatigue -{ - EnergyRate: number - WorkingTime: number - TicksEvery: number - EnergyRatePerStack: number -} - -export interface IFracture -{ - DefaultDelay: number - DefaultResidueTime: number - HealExperience: number - OfflineDurationMin: number - OfflineDurationMax: number - RemovePrice: number - RemovedAfterDeath: boolean - BulletHitProbability: IProbability - FallingProbability: IProbability -} - -export interface IHeavyBleeding -{ - DefaultDelay: number - DefaultResidueTime: number - DamageEnergy: number - DamageHealth: number - EnergyLoopTime: number - HealthLoopTime: number - DamageHealthDehydrated: number - HealthLoopTimeDehydrated: number - LifeTimeDehydrated: number - EliteVitalityDuration: number - HealExperience: number - OfflineDurationMin: number - OfflineDurationMax: number - RemovePrice: number - RemovedAfterDeath: boolean - Probability: IProbability -} - -export interface IProbability -{ - FunctionType: string - K: number - B: number - Threshold: number -} - -export interface ILightBleeding -{ - DefaultDelay: number - DefaultResidueTime: number - DamageEnergy: number - DamageHealth: number - EnergyLoopTime: number - HealthLoopTime: number - DamageHealthDehydrated: number - HealthLoopTimeDehydrated: number - LifeTimeDehydrated: number - EliteVitalityDuration: number - HealExperience: number - OfflineDurationMin: number - OfflineDurationMax: number - RemovePrice: number - RemovedAfterDeath: boolean - Probability: IProbability -} - -export interface IBodyTemperature -{ - DefaultBuildUpTime: number - DefaultResidueTime: number - LoopTime: number -} - -export interface IHealPrice -{ - HealthPointPrice: number - HydrationPointPrice: number - EnergyPointPrice: number - TrialLevels: number - TrialRaids: number -} - -export interface IProfileHealthSettings -{ - BodyPartsSettings: IBodyPartsSettings - HealthFactorsSettings: IHealthFactorsSettings - DefaultStimulatorBuff: string -} - -export interface IBodyPartsSettings -{ - Head: IBodyPartsSetting - Chest: IBodyPartsSetting - Stomach: IBodyPartsSetting - LeftArm: IBodyPartsSetting - RightArm: IBodyPartsSetting - LeftLeg: IBodyPartsSetting - RightLeg: IBodyPartsSetting -} - -export interface IBodyPartsSetting -{ - Minimum: number - Maximum: number - Default: number - EnvironmentDamageMultiplier: number - OverDamageReceivedMultiplier: number -} - -export interface IHealthFactorsSettings -{ - Energy: IHealthFactorSetting - Hydration: IHealthFactorSetting - Temperature: IHealthFactorSetting - Poisoning: IHealthFactorSetting - Radiation: IHealthFactorSetting -} - -export interface IHealthFactorSetting -{ - Minimum: number - Maximum: number - Default: number -} - -export interface IRating -{ - levelRequired: number - limit: number - categories: ICategories -} - -export interface ICategories -{ - experience: boolean - kd: boolean - surviveRatio: boolean - avgEarnings: boolean - pmcKills: boolean - raidCount: boolean - longestShot: boolean - timeOnline: boolean - inventoryFullCost: boolean - ragFairStanding: boolean -} - -export interface ITournament -{ - categories: ITournamentCategories - limit: number - levelRequired: number -} - -export interface ITournamentCategories -{ - dogtags: boolean -} - -export interface IRagFair -{ - enabled: boolean - priceStabilizerEnabled: boolean - includePveTraderSales: boolean - priceStabilizerStartIntervalInHours: number - minUserLevel: number - communityTax: number - communityItemTax: number - communityRequirementTax: number - offerPriorityCost: number - offerDurationTimeInHour: number - offerDurationTimeInHourAfterRemove: number - priorityTimeModifier: number - maxRenewOfferTimeInHour: number - renewPricePerHour: number - maxActiveOfferCount: IMaxActiveOfferCount[] - balancerRemovePriceCoefficient: number - balancerMinPriceCount: number - balancerAveragePriceCoefficient: number - delaySinceOfferAdd: number - uniqueBuyerTimeoutInDays: number - userRatingChangeFrequencyMultiplayer: number - ratingSumForIncrease: number - ratingIncreaseCount: number - ratingSumForDecrease: number - ratingDecreaseCount: number - maxSumForIncreaseRatingPerOneSale: number - maxSumForDecreaseRatingPerOneSale: number - maxSumForRarity: IMaxSumForRarity - ChangePriceCoef: number - ItemRestrictions: IItemGlobalRestrictions[] - balancerUserItemSaleCooldownEnabled: boolean - balancerUserItemSaleCooldown: number - youSellOfferMaxStorageTimeInHour: number - yourOfferDidNotSellMaxStorageTimeInHour: number - isOnlyFoundInRaidAllowed: boolean - sellInOnePiece: number -} - -export interface IItemGlobalRestrictions -{ - MaxFlea: number - MaxFleaStacked: number - TemplateId: string - -} - -export interface IMaxActiveOfferCount -{ - from: number - to: number - count: number - countForSpecialEditions: number -} - -export interface IMaxSumForRarity -{ - Common: IRarityMaxSum - Rare: IRarityMaxSum - Superrare: IRarityMaxSum - Not_exist: IRarityMaxSum -} - -export interface IRarityMaxSum -{ - value: number -} - -export interface IHandbook -{ - defaultCategory: string -} - -export interface IStamina -{ - Capacity: number - SprintDrainRate: number - BaseRestorationRate: number - JumpConsumption: number - GrenadeHighThrow: number - GrenadeLowThrow: number - AimDrainRate: number - AimRangeFinderDrainRate: number - OxygenCapacity: number - OxygenRestoration: number - WalkOverweightLimits: Ixyz - BaseOverweightLimits: Ixyz - SprintOverweightLimits: Ixyz - WalkSpeedOverweightLimits: Ixyz - CrouchConsumption: Ixyz - WalkConsumption: Ixyz - StandupConsumption: Ixyz - TransitionSpeed: Ixyz - SprintAccelerationLowerLimit: number - SprintSpeedLowerLimit: number - SprintSensitivityLowerLimit: number - AimConsumptionByPose: Ixyz - RestorationMultiplierByPose: Ixyz - OverweightConsumptionByPose: Ixyz - AimingSpeedMultiplier: number - WalkVisualEffectMultiplier: number - WeaponFastSwitchConsumption: number - HandsCapacity: number - HandsRestoration: number - ProneConsumption: number - BaseHoldBreathConsumption: number - SoundRadius: Ixyz - ExhaustedMeleeSpeed: number - FatigueRestorationRate: number - FatigueAmountToCreateEffect: number - ExhaustedMeleeDamageMultiplier: number - FallDamageMultiplier: number - SafeHeightOverweight: number - SitToStandConsumption: number - StaminaExhaustionCausesJiggle: boolean - StaminaExhaustionStartsBreathSound: boolean - StaminaExhaustionRocksCamera: boolean - HoldBreathStaminaMultiplier: Ixyz - PoseLevelIncreaseSpeed: Ixyz - PoseLevelDecreaseSpeed: Ixyz - PoseLevelConsumptionPerNotch: Ixyz -} - -export interface IStaminaRestoration -{ - LowerLeftPoint: number - LowerRightPoint: number - LeftPlatoPoint: number - RightPlatoPoint: number - RightLimit: number - ZeroValue: number -} - -export interface IStaminaDrain -{ - LowerLeftPoint: number - LowerRightPoint: number - LeftPlatoPoint: number - RightPlatoPoint: number - RightLimit: number - ZeroValue: number -} - -export interface IRequirementReferences -{ - Alpinist: IAlpinist[] -} - -export interface IAlpinist -{ - Requirement: string - Id: string - Count: number - RequiredSlot: string - RequirementTip: string -} - -export interface IRestrictionsInRaid -{ - TemplateId: string - Value: number -} - -export interface IFavoriteItemsSettings -{ - WeaponStandMaxItemsCount: number - PlaceOfFameMaxItemsCount: number -} - -export interface IVaultingSettings -{ - IsActive: boolean - VaultingInputTime: number - GridSettings: IVaultingGridSettings - MovesSettings: IVaultingMovesSettings -} - -export interface IVaultingGridSettings -{ - GridSizeX: number - GridSizeY: number - GridSizeZ: number - SteppingLengthX: number - SteppingLengthY: number - SteppingLengthZ: number - GridOffsetX: number - GridOffsetY: number - GridOffsetZ: number - OffsetFactor: number -} - -export interface IVaultingMovesSettings -{ - VaultSettings: IVaultingSubMoveSettings - ClimbSettings: IVaultingSubMoveSettings -} - -export interface IVaultingSubMoveSettings -{ - IsActive: boolean - MaxWithoutHandHeight: number - SpeedRange: Ixyz - MoveRestrictions: IMoveRestrictions - AutoMoveRestrictions: IMoveRestrictions -} - -export interface IMoveRestrictions -{ - IsActive: boolean - MinDistantToInteract: number - MinHeight: number - MaxHeight: number - MinLength: number - MaxLength: number -} - -export interface IBTRSettings -{ - LocationsWithBTR: string[] - BasePriceTaxi: number - AddPriceTaxi: number - CleanUpPrice: number - DeliveryPrice: number - ModDeliveryCost: number - BearPriceMod: number - UsecPriceMod: number - ScavPriceMod: number - CoefficientDiscountCharisma: number - DeliveryMinPrice: number - TaxiMinPrice: number - BotCoverMinPrice: number - MapsConfigs: Record - DiameterWheel: number - HeightWheel: number - HeightWheelMaxPosLimit: number - HeightWheelMinPosLimit: number - SnapToSurfaceWheelsSpeed: number - CheckSurfaceForWheelsTimer: number - HeightWheelOffset: number -} - -export interface IBtrMapConfig -{ - BtrSkin: string - CheckSurfaceForWheelsTimer: number - DiameterWheel: number - HeightWheel: number - HeightWheelMaxPosLimit: number - HeightWheelMinPosLimit: number - HeightWheelOffset: number - SnapToSurfaceWheelsSpeed: number - SuspensionDamperStiffness: number - SuspensionRestLength: number - SuspensionSpringStiffness: number - SuspensionTravel: number - SuspensionWheelRadius: number - mapID: string - pathsConfigurations: IPathConfig[] -} - -export interface IPathConfig -{ - active: boolean - id: string - enterPoint: string - exitPoint: string - pathPoints: string[] - once: boolean - circle: boolean - circleCount: number -} - -export interface ISquadSettings -{ - CountOfRequestsToOnePlayer: number - SecondsForExpiredRequest: number - SendRequestDelaySeconds: number -} - -export interface IInsurance -{ - ChangeForReturnItemsInOfflineRaid: number - MaxStorageTimeInHour: number - CoefOfSendingMessageTime: number - CoefOfHavingMarkOfUnknown: number - EditionSendingMessageTime: Record -} - -export interface IMessageSendTImeMultipler -{ - multiplier: number -} - -export interface ISkillsSettings -{ - SkillProgressRate: number - WeaponSkillProgressRate: number - WeaponSkillRecoilBonusPerLevel: number - HideoutManagement: IHideoutManagement - Crafting: ICrafting - Metabolism: IMetabolism - Immunity: Immunity - Endurance: IEndurance - Strength: IStrength - Vitality: IVitality - Health: IHealthSkillProgress - StressResistance: IStressResistance - Throwing: IThrowing - RecoilControl: IRecoilControl - Pistol: IWeaponSkills - Revolver: IWeaponSkills - SMG: any[] - Assault: IWeaponSkills - Shotgun: IWeaponSkills - Sniper: IWeaponSkills - LMG: any[] - HMG: any[] - Launcher: any[] - AttachedLauncher: any[] - Melee: IMeleeSkill - DMR: IWeaponSkills - BearAssaultoperations: any[] - BearAuthority: any[] - BearAksystems: any[] - BearHeavycaliber: any[] - BearRawpower: any[] - UsecArsystems: any[] - UsecDeepweaponmodding_Settings: any[] - UsecLongrangeoptics_Settings: any[] - UsecNegotiations: any[] - UsecTactics: any[] - BotReload: any[] - CovertMovement: ICovertMovement - FieldMedicine: any[] - Search: ISearch - Sniping: any[] - ProneMovement: any[] - FirstAid: any[] - LightVests: IArmorSkills - HeavyVests: IArmorSkills - WeaponModding: any[] - AdvancedModding: any[] - NightOps: any[] - SilentOps: any[] - Lockpicking: any[] - WeaponTreatment: IWeaponTreatment - MagDrills: IMagDrills - Freetrading: any[] - Auctions: any[] - Cleanoperations: any[] - Barter: any[] - Shadowconnections: any[] - Taskperformance: any[] - Perception: IPerception - Intellect: Intellect - Attention: IAttention - Charisma: ICharisma - Memory: IMemory - Surgery: ISurgery - AimDrills: IAimDrills - BotSound: any[] - TroubleShooting: ITroubleShooting -} - -export interface IMeleeSkill -{ - BuffSettings: IBuffSettings -} - -export interface IArmorSkills -{ - BuffMaxCount: number - BuffSettings: IBuffSettings - Counters: IArmorCounters - MoveSpeedPenaltyReductionHVestsReducePerLevel: number - RicochetChanceHVestsCurrentDurabilityThreshold: number - RicochetChanceHVestsEliteLevel: number - RicochetChanceHVestsMaxDurabilityThreshold: number - MeleeDamageLVestsReducePerLevel: number - MoveSpeedPenaltyReductionLVestsReducePerLevel: number - WearAmountRepairLVestsReducePerLevel: number - WearChanceRepairLVestsReduceEliteLevel: number -} - -export interface IArmorCounters -{ - armorDurability: ISkillCounter -} - -export interface IHideoutManagement -{ - SkillPointsPerAreaUpgrade: number - SkillPointsPerCraft: number - ConsumptionReductionPerLevel: number - SkillBoostPercent: number - SkillPointsRate: ISkillPointsRate - EliteSlots: IEliteSlots -} - -export interface ISkillPointsRate -{ - Generator: ISkillPointRate - AirFilteringUnit: ISkillPointRate - WaterCollector: ISkillPointRate - SolarPower: ISkillPointRate -} - -export interface ISkillPointRate -{ - ResourceSpent: number - PointsGained: number -} - -export interface IEliteSlots -{ - Generator: IEliteSlot - AirFilteringUnit: IEliteSlot - WaterCollector: IEliteSlot - BitcoinFarm: IEliteSlot -} - -export interface IEliteSlot -{ - Slots: number - Container: number -} - -export interface ICrafting -{ - PointsPerCraftingCycle: number - CraftingCycleHours: number - PointsPerUniqueCraftCycle: number - UniqueCraftsPerCycle: number - CraftTimeReductionPerLevel: number - ProductionTimeReductionPerLevel: number - EliteExtraProductions: number - CraftingPointsToInteligence: number -} - -export interface IMetabolism -{ - HydrationRecoveryRate: number - EnergyRecoveryRate: number - IncreasePositiveEffectDurationRate: number - DecreaseNegativeEffectDurationRate: number - DecreasePoisonDurationRate: number -} - -export interface Immunity -{ - ImmunityMiscEffects: number - ImmunityPoisonBuff: number - ImmunityPainKiller: number - HealthNegativeEffect: number - StimulatorNegativeBuff: number +export interface IStrength { + DependentSkillRatios: IDependentSkillRatio[]; + SprintActionMin: number; + SprintActionMax: number; + MovementActionMin: number; + MovementActionMax: number; + PushUpMin: number; + PushUpMax: number; + QTELevelMultipliers: IQTELevelMultiplier[]; + FistfightAction: number; + ThrowAction: number; } -export interface IEndurance -{ - MovementAction: number - SprintAction: number - GainPerFatigueStack: number - DependentSkillRatios: IDependentSkillRatio[] - QTELevelMultipliers: Record> +export interface IDependentSkillRatio { + Ratio: number; + SkillId: string; } -export interface IStrength -{ - DependentSkillRatios: IDependentSkillRatio[] - SprintActionMin: number - SprintActionMax: number - MovementActionMin: number - MovementActionMax: number - PushUpMin: number - PushUpMax: number - QTELevelMultipliers: IQTELevelMultiplier[] - FistfightAction: number - ThrowAction: number +export interface IQTELevelMultiplier { + Level: number; + Multiplier: number; } -export interface IDependentSkillRatio -{ - Ratio: number - SkillId: string +export interface IVitality { + DamageTakenAction: number; + HealthNegativeEffect: number; } -export interface IQTELevelMultiplier -{ - Level: number - Multiplier: number +export interface IHealthSkillProgress { + SkillProgress: number; } -export interface IVitality -{ - DamageTakenAction: number - HealthNegativeEffect: number +export interface IStressResistance { + HealthNegativeEffect: number; + LowHPDuration: number; } -export interface IHealthSkillProgress -{ - SkillProgress: number +export interface IThrowing { + ThrowAction: number; } -export interface IStressResistance -{ - HealthNegativeEffect: number - LowHPDuration: number +export interface IRecoilControl { + RecoilAction: number; + RecoilBonusPerLevel: number; } -export interface IThrowing -{ - ThrowAction: number +export interface IWeaponSkills { + WeaponReloadAction: number; + WeaponShotAction: number; + WeaponFixAction: number; + WeaponChamberAction: number; } -export interface IRecoilControl -{ - RecoilAction: number - RecoilBonusPerLevel: number +export interface ICovertMovement { + MovementAction: number; } -export interface IWeaponSkills -{ - WeaponReloadAction: number - WeaponShotAction: number - WeaponFixAction: number - WeaponChamberAction: number +export interface ISearch { + SearchAction: number; + FindAction: number; } -export interface ICovertMovement -{ - MovementAction: number +export interface IWeaponTreatment { + BuffMaxCount: number; + BuffSettings: IBuffSettings; + Counters: IWeaponTreatmentCounters; + DurLossReducePerLevel: number; + SkillPointsPerRepair: number; + Filter: any[]; + WearAmountRepairGunsReducePerLevel: number; + WearChanceRepairGunsReduceEliteLevel: number; } -export interface ISearch -{ - SearchAction: number - FindAction: number +export interface IWeaponTreatmentCounters { + firearmsDurability: ISkillCounter; } -export interface IWeaponTreatment -{ - BuffMaxCount: number - BuffSettings: IBuffSettings - Counters: IWeaponTreatmentCounters - DurLossReducePerLevel: number - SkillPointsPerRepair: number - Filter: any[] - WearAmountRepairGunsReducePerLevel: number - WearChanceRepairGunsReduceEliteLevel: number +export interface IBuffSettings { + CommonBuffChanceLevelBonus: number; + CommonBuffMinChanceValue: number; + CurrentDurabilityLossToRemoveBuff?: number; + MaxDurabilityLossToRemoveBuff?: number; + RareBuffChanceCoff: number; + ReceivedDurabilityMaxPercent: number; } -export interface IWeaponTreatmentCounters -{ - firearmsDurability: ISkillCounter +export interface IMagDrills { + RaidLoadedAmmoAction: number; + RaidUnloadedAmmoAction: number; + MagazineCheckAction: number; } -export interface IBuffSettings -{ - CommonBuffChanceLevelBonus: number - CommonBuffMinChanceValue: number - CurrentDurabilityLossToRemoveBuff?: number - MaxDurabilityLossToRemoveBuff?: number - RareBuffChanceCoff: number - ReceivedDurabilityMaxPercent: number +export interface IPerception { + DependentSkillRatios: ISkillRatio[]; + OnlineAction: number; + UniqueLoot: number; } -export interface IMagDrills -{ - RaidLoadedAmmoAction: number - RaidUnloadedAmmoAction: number - MagazineCheckAction: number +export interface ISkillRatio { + Ratio: number; + SkillId: string; } -export interface IPerception -{ - DependentSkillRatios: ISkillRatio[] - OnlineAction: number - UniqueLoot: number +export interface Intellect { + Counters: IIntellectCounters; + ExamineAction: number; + SkillProgress: number; + RepairAction: number; + WearAmountReducePerLevel: number; + WearChanceReduceEliteLevel: number; + RepairPointsCostReduction: number; } -export interface ISkillRatio -{ - Ratio: number - SkillId: string +export interface IIntellectCounters { + armorDurability: ISkillCounter; + firearmsDurability: ISkillCounter; + meleeWeaponDurability: ISkillCounter; } -export interface Intellect -{ - Counters: IIntellectCounters - ExamineAction: number - SkillProgress: number - RepairAction: number - WearAmountReducePerLevel: number - WearChanceReduceEliteLevel: number - RepairPointsCostReduction: number +export interface ISkillCounter { + divisor: number; + points: number; } -export interface IIntellectCounters -{ - armorDurability: ISkillCounter - firearmsDurability: ISkillCounter - meleeWeaponDurability: ISkillCounter +export interface IAttention { + DependentSkillRatios: ISkillRatio[]; + ExamineWithInstruction: number; + FindActionFalse: number; + FindActionTrue: number; } -export interface ISkillCounter -{ - divisor: number - points: number +export interface ICharisma { + BonusSettings: IBonusSettings; + Counters: ICharismaSkillCounters; + SkillProgressInt: number; + SkillProgressAtn: number; + SkillProgressPer: number; } -export interface IAttention -{ - DependentSkillRatios: ISkillRatio[] - ExamineWithInstruction: number - FindActionFalse: number - FindActionTrue: number -} - -export interface ICharisma -{ - BonusSettings: IBonusSettings - Counters: ICharismaSkillCounters - SkillProgressInt: number - SkillProgressAtn: number - SkillProgressPer: number -} - -export interface ICharismaSkillCounters -{ - insuranceCost: ISkillCounter - repairCost: ISkillCounter - repeatableQuestCompleteCount: ISkillCounter - restoredHealthCost: ISkillCounter - scavCaseCost: ISkillCounter -} - -export interface IBonusSettings -{ - EliteBonusSettings: IEliteBonusSettings - LevelBonusSettings: ILevelBonusSettings -} - -export interface IEliteBonusSettings -{ - FenceStandingLossDiscount: number - RepeatableQuestExtraCount: number - ScavCaseDiscount: number -} - -export interface ILevelBonusSettings -{ - HealthRestoreDiscount: number - HealthRestoreTraderDiscount: number - InsuranceDiscount: number - InsuranceTraderDiscount: number - PaidExitDiscount: number - RepeatableQuestChangeDiscount: number -} - -export interface IMemory -{ - AnySkillUp: number - SkillProgress: number -} - -export interface ISurgery -{ - SurgeryAction: number - SkillProgress: number -} - -export interface IAimDrills -{ - WeaponShotAction: number -} - -export interface ITroubleShooting -{ - MalfRepairSpeedBonusPerLevel: number - SkillPointsPerMalfFix: number - EliteDurabilityChanceReduceMult: number - EliteAmmoChanceReduceMult: number - EliteMagChanceReduceMult: number -} - -export interface IAiming -{ - ProceduralIntensityByPose: Ixyz - AimProceduralIntensity: number - HeavyWeight: number - LightWeight: number - MaxTimeHeavy: number - MinTimeHeavy: number - MaxTimeLight: number - MinTimeLight: number - RecoilScaling: number - RecoilDamping: number - CameraSnapGlobalMult: number - RecoilXIntensityByPose: Ixyz - RecoilYIntensityByPose: Ixyz - RecoilZIntensityByPose: Ixyz - RecoilCrank: boolean - RecoilHandDamping: number - RecoilConvergenceMult: number - RecoilVertBonus: number - RecoilBackBonus: number -} - -export interface IMalfunction -{ - AmmoMalfChanceMult: number - MagazineMalfChanceMult: number - MalfRepairHardSlideMult: number - MalfRepairOneHandBrokenMult: number - MalfRepairTwoHandsBrokenMult: number - AllowMalfForBots: boolean - ShowGlowAttemptsCount: number - OutToIdleSpeedMultForPistol: number - IdleToOutSpeedMultOnMalf: number - TimeToQuickdrawPistol: number - DurRangeToIgnoreMalfs: Ixyz - DurFeedWt: number - DurMisfireWt: number - DurJamWt: number - DurSoftSlideWt: number - DurHardSlideMinWt: number - DurHardSlideMaxWt: number - AmmoMisfireWt: number - AmmoFeedWt: number - AmmoJamWt: number - OverheatFeedWt: number - OverheatJamWt: number - OverheatSoftSlideWt: number - OverheatHardSlideMinWt: number - OverheatHardSlideMaxWt: number -} - -export interface IOverheat -{ - MinOverheat: number - MaxOverheat: number - OverheatProblemsStart: number - ModHeatFactor: number - ModCoolFactor: number - MinWearOnOverheat: number - MaxWearOnOverheat: number - MinWearOnMaxOverheat: number - MaxWearOnMaxOverheat: number - OverheatWearLimit: number - MaxCOIIncreaseMult: number - MinMalfChance: number - MaxMalfChance: number - DurReduceMinMult: number - DurReduceMaxMult: number - BarrelMoveRndDuration: number - BarrelMoveMaxMult: number - FireratePitchMult: number - FirerateReduceMinMult: number - FirerateReduceMaxMult: number - FirerateOverheatBorder: number - EnableSlideOnMaxOverheat: boolean - StartSlideOverheat: number - FixSlideOverheat: number - AutoshotMinOverheat: number - AutoshotChance: number - AutoshotPossibilityDuration: number - MaxOverheatCoolCoef: number -} - -export interface IFenceSettings -{ - FenceId: string - Levels: Record - paidExitStandingNumerator: number -} - -export interface IFenceLevel -{ - ReachOnMarkOnUnknowns: boolean - SavageCooldownModifier: number - ScavCaseTimeModifier: number - PaidExitCostModifier: number - BotFollowChance: number - ScavEquipmentSpawnChanceModifier: number - PriceModifier: number - HostileBosses: boolean - HostileScavs: boolean - ScavAttackSupport: boolean - ExfiltrationPriceModifier: number - AvailableExits: number - BotApplySilenceChance: number - BotGetInCoverChance: number - BotHelpChance: number - BotSpreadoutChance: number - BotStopChance: number - PriceModTaxi: number - PriceModDelivery: number - PriceModCleanUp: number - ReactOnMarkOnUnknowns: boolean - ReactOnMarkOnUnknownsPVE: boolean - DeliveryGridSize: Ixyz - CanInteractWithBtr: boolean -} - -export interface IInertia -{ - InertiaLimits: Ixyz - InertiaLimitsStep: number - ExitMovementStateSpeedThreshold: Ixyz - WalkInertia: Ixyz - FallThreshold: number - SpeedLimitAfterFallMin: Ixyz - SpeedLimitAfterFallMax: Ixyz - SpeedLimitDurationMin: Ixyz - SpeedLimitDurationMax: Ixyz - SpeedInertiaAfterJump: Ixyz - BaseJumpPenaltyDuration: number - DurationPower: number - BaseJumpPenalty: number - PenaltyPower: number - InertiaTiltCurveMin: Ixyz - InertiaTiltCurveMax: Ixyz - InertiaBackwardCoef: Ixyz - TiltInertiaMaxSpeed: Ixyz - TiltStartSideBackSpeed: Ixyz - TiltMaxSideBackSpeed: Ixyz - TiltAcceleration: Ixyz - AverageRotationFrameSpan: number - SprintSpeedInertiaCurveMin: Ixyz - SprintSpeedInertiaCurveMax: Ixyz - SprintBrakeInertia: Ixyz - SprintTransitionMotionPreservation: Ixyz - WeaponFlipSpeed: Ixyz - PreSprintAccelerationLimits: Ixyz - SprintAccelerationLimits: Ixyz - SideTime: Ixyz - DiagonalTime: Ixyz - MaxTimeWithoutInput: Ixyz - MinDirectionBlendTime: number - MoveTimeRange: Ixyz - ProneDirectionAccelerationRange: Ixyz - ProneSpeedAccelerationRange: Ixyz - MinMovementAccelerationRangeRight: Ixyz - MaxMovementAccelerationRangeRight: Ixyz -} - -export interface IBallistic -{ - GlobalDamageDegradationCoefficient: number -} - -export interface IRepairSettings -{ - ItemEnhancementSettings: IItemEnhancementSettings - MinimumLevelToApplyBuff: number - RepairStrategies: IRepairStrategies - armorClassDivisor: number - durabilityPointCostArmor: number - durabilityPointCostGuns: number -} - -export interface IItemEnhancementSettings -{ - DamageReduction: IPriceModifier - MalfunctionProtections: IPriceModifier - WeaponSpread: IPriceModifier -} - -export interface IPriceModifier -{ - PriceModifier: number -} - -export interface IRepairStrategies -{ - Armor: IRepairStrategy - Firearms: IRepairStrategy -} - -export interface IRepairStrategy -{ - BuffTypes: string[] - Filter: string[] -} - -export interface IBotPreset -{ - UseThis: boolean - Role: string - BotDifficulty: string - VisibleAngle: number - VisibleDistance: number - ScatteringPerMeter: number - HearingSense: number - SCATTERING_DIST_MODIF: number - MAX_AIMING_UPGRADE_BY_TIME: number - FIRST_CONTACT_ADD_SEC: number - COEF_IF_MOVE: number -} - -export interface IAudioSettings -{ - AudioGroupPresets: IAudioGroupPreset[] -} - -export interface IAudioGroupPreset -{ - AngleToAllowBinaural: number - DisabledBinauralByDistance: boolean - DistanceToAllowBinaural: number - GroupType: number - HeightToAllowBinaural: number - Name: string - OcclusionEnabled: boolean - OcclusionIntensity: number - OverallVolume: number -} - -export interface IEnvironmentSettings -{ - SnowStepsVolumeMultiplier: number - SurfaceMultipliers: ISurfaceMultiplier[] -} - -export interface ISurfaceMultiplier -{ - SurfaceType: string - VolumeMult: number -} - -export interface IBotWeaponScattering -{ - Name: string - PriorityScatter1meter: number - PriorityScatter10meter: number - PriorityScatter100meter: number -} - -export interface IPreset -{ - _id: string - _type: string - _changeWeaponName: boolean - _name: string - _parent: string - _items: Item[] +export interface ICharismaSkillCounters { + insuranceCost: ISkillCounter; + repairCost: ISkillCounter; + repeatableQuestCompleteCount: ISkillCounter; + restoredHealthCost: ISkillCounter; + scavCaseCost: ISkillCounter; +} + +export interface IBonusSettings { + EliteBonusSettings: IEliteBonusSettings; + LevelBonusSettings: ILevelBonusSettings; +} + +export interface IEliteBonusSettings { + FenceStandingLossDiscount: number; + RepeatableQuestExtraCount: number; + ScavCaseDiscount: number; +} + +export interface ILevelBonusSettings { + HealthRestoreDiscount: number; + HealthRestoreTraderDiscount: number; + InsuranceDiscount: number; + InsuranceTraderDiscount: number; + PaidExitDiscount: number; + RepeatableQuestChangeDiscount: number; +} + +export interface IMemory { + AnySkillUp: number; + SkillProgress: number; +} + +export interface ISurgery { + SurgeryAction: number; + SkillProgress: number; +} + +export interface IAimDrills { + WeaponShotAction: number; +} + +export interface ITroubleShooting { + MalfRepairSpeedBonusPerLevel: number; + SkillPointsPerMalfFix: number; + EliteDurabilityChanceReduceMult: number; + EliteAmmoChanceReduceMult: number; + EliteMagChanceReduceMult: number; +} + +export interface IAiming { + ProceduralIntensityByPose: Ixyz; + AimProceduralIntensity: number; + HeavyWeight: number; + LightWeight: number; + MaxTimeHeavy: number; + MinTimeHeavy: number; + MaxTimeLight: number; + MinTimeLight: number; + RecoilScaling: number; + RecoilDamping: number; + CameraSnapGlobalMult: number; + RecoilXIntensityByPose: Ixyz; + RecoilYIntensityByPose: Ixyz; + RecoilZIntensityByPose: Ixyz; + RecoilCrank: boolean; + RecoilHandDamping: number; + RecoilConvergenceMult: number; + RecoilVertBonus: number; + RecoilBackBonus: number; +} + +export interface IMalfunction { + AmmoMalfChanceMult: number; + MagazineMalfChanceMult: number; + MalfRepairHardSlideMult: number; + MalfRepairOneHandBrokenMult: number; + MalfRepairTwoHandsBrokenMult: number; + AllowMalfForBots: boolean; + ShowGlowAttemptsCount: number; + OutToIdleSpeedMultForPistol: number; + IdleToOutSpeedMultOnMalf: number; + TimeToQuickdrawPistol: number; + DurRangeToIgnoreMalfs: Ixyz; + DurFeedWt: number; + DurMisfireWt: number; + DurJamWt: number; + DurSoftSlideWt: number; + DurHardSlideMinWt: number; + DurHardSlideMaxWt: number; + AmmoMisfireWt: number; + AmmoFeedWt: number; + AmmoJamWt: number; + OverheatFeedWt: number; + OverheatJamWt: number; + OverheatSoftSlideWt: number; + OverheatHardSlideMinWt: number; + OverheatHardSlideMaxWt: number; +} + +export interface IOverheat { + MinOverheat: number; + MaxOverheat: number; + OverheatProblemsStart: number; + ModHeatFactor: number; + ModCoolFactor: number; + MinWearOnOverheat: number; + MaxWearOnOverheat: number; + MinWearOnMaxOverheat: number; + MaxWearOnMaxOverheat: number; + OverheatWearLimit: number; + MaxCOIIncreaseMult: number; + MinMalfChance: number; + MaxMalfChance: number; + DurReduceMinMult: number; + DurReduceMaxMult: number; + BarrelMoveRndDuration: number; + BarrelMoveMaxMult: number; + FireratePitchMult: number; + FirerateReduceMinMult: number; + FirerateReduceMaxMult: number; + FirerateOverheatBorder: number; + EnableSlideOnMaxOverheat: boolean; + StartSlideOverheat: number; + FixSlideOverheat: number; + AutoshotMinOverheat: number; + AutoshotChance: number; + AutoshotPossibilityDuration: number; + MaxOverheatCoolCoef: number; +} + +export interface IFenceSettings { + FenceId: string; + Levels: Record; + paidExitStandingNumerator: number; +} + +export interface IFenceLevel { + ReachOnMarkOnUnknowns: boolean; + SavageCooldownModifier: number; + ScavCaseTimeModifier: number; + PaidExitCostModifier: number; + BotFollowChance: number; + ScavEquipmentSpawnChanceModifier: number; + PriceModifier: number; + HostileBosses: boolean; + HostileScavs: boolean; + ScavAttackSupport: boolean; + ExfiltrationPriceModifier: number; + AvailableExits: number; + BotApplySilenceChance: number; + BotGetInCoverChance: number; + BotHelpChance: number; + BotSpreadoutChance: number; + BotStopChance: number; + PriceModTaxi: number; + PriceModDelivery: number; + PriceModCleanUp: number; + ReactOnMarkOnUnknowns: boolean; + ReactOnMarkOnUnknownsPVE: boolean; + DeliveryGridSize: Ixyz; + CanInteractWithBtr: boolean; +} + +export interface IInertia { + InertiaLimits: Ixyz; + InertiaLimitsStep: number; + ExitMovementStateSpeedThreshold: Ixyz; + WalkInertia: Ixyz; + FallThreshold: number; + SpeedLimitAfterFallMin: Ixyz; + SpeedLimitAfterFallMax: Ixyz; + SpeedLimitDurationMin: Ixyz; + SpeedLimitDurationMax: Ixyz; + SpeedInertiaAfterJump: Ixyz; + BaseJumpPenaltyDuration: number; + DurationPower: number; + BaseJumpPenalty: number; + PenaltyPower: number; + InertiaTiltCurveMin: Ixyz; + InertiaTiltCurveMax: Ixyz; + InertiaBackwardCoef: Ixyz; + TiltInertiaMaxSpeed: Ixyz; + TiltStartSideBackSpeed: Ixyz; + TiltMaxSideBackSpeed: Ixyz; + TiltAcceleration: Ixyz; + AverageRotationFrameSpan: number; + SprintSpeedInertiaCurveMin: Ixyz; + SprintSpeedInertiaCurveMax: Ixyz; + SprintBrakeInertia: Ixyz; + SprintTransitionMotionPreservation: Ixyz; + WeaponFlipSpeed: Ixyz; + PreSprintAccelerationLimits: Ixyz; + SprintAccelerationLimits: Ixyz; + SideTime: Ixyz; + DiagonalTime: Ixyz; + MaxTimeWithoutInput: Ixyz; + MinDirectionBlendTime: number; + MoveTimeRange: Ixyz; + ProneDirectionAccelerationRange: Ixyz; + ProneSpeedAccelerationRange: Ixyz; + MinMovementAccelerationRangeRight: Ixyz; + MaxMovementAccelerationRangeRight: Ixyz; +} + +export interface IBallistic { + GlobalDamageDegradationCoefficient: number; +} + +export interface IRepairSettings { + ItemEnhancementSettings: IItemEnhancementSettings; + MinimumLevelToApplyBuff: number; + RepairStrategies: IRepairStrategies; + armorClassDivisor: number; + durabilityPointCostArmor: number; + durabilityPointCostGuns: number; +} + +export interface IItemEnhancementSettings { + DamageReduction: IPriceModifier; + MalfunctionProtections: IPriceModifier; + WeaponSpread: IPriceModifier; +} + +export interface IPriceModifier { + PriceModifier: number; +} + +export interface IRepairStrategies { + Armor: IRepairStrategy; + Firearms: IRepairStrategy; +} + +export interface IRepairStrategy { + BuffTypes: string[]; + Filter: string[]; +} + +export interface IBotPreset { + UseThis: boolean; + Role: string; + BotDifficulty: string; + VisibleAngle: number; + VisibleDistance: number; + ScatteringPerMeter: number; + HearingSense: number; + SCATTERING_DIST_MODIF: number; + MAX_AIMING_UPGRADE_BY_TIME: number; + FIRST_CONTACT_ADD_SEC: number; + COEF_IF_MOVE: number; +} + +export interface IAudioSettings { + AudioGroupPresets: IAudioGroupPreset[]; +} + +export interface IAudioGroupPreset { + AngleToAllowBinaural: number; + DisabledBinauralByDistance: boolean; + DistanceToAllowBinaural: number; + GroupType: number; + HeightToAllowBinaural: number; + Name: string; + OcclusionEnabled: boolean; + OcclusionIntensity: number; + OverallVolume: number; +} + +export interface IEnvironmentSettings { + SnowStepsVolumeMultiplier: number; + SurfaceMultipliers: ISurfaceMultiplier[]; +} + +export interface ISurfaceMultiplier { + SurfaceType: string; + VolumeMult: number; +} + +export interface IBotWeaponScattering { + Name: string; + PriorityScatter1meter: number; + PriorityScatter10meter: number; + PriorityScatter100meter: number; +} + +export interface IPreset { + _id: string; + _type: string; + _changeWeaponName: boolean; + _name: string; + _parent: string; + _items: Item[]; /** Default presets have this property */ - _encyclopedia?: string + _encyclopedia?: string; } -export interface IQuestSettings -{ - GlobalRewardRepModifierDailyQuestPvE: number - GlobalRewardRepModifierQuestPvE: number +export interface IQuestSettings { + GlobalRewardRepModifierDailyQuestPvE: number; + GlobalRewardRepModifierQuestPvE: number; } diff --git a/project/src/models/eft/common/ILocation.ts b/project/src/models/eft/common/ILocation.ts index 6cab55a5..f56a00a0 100644 --- a/project/src/models/eft/common/ILocation.ts +++ b/project/src/models/eft/common/ILocation.ts @@ -3,112 +3,97 @@ import { ILooseLoot } from "@spt/models/eft/common/ILooseLoot"; import { Ixyz } from "@spt/models/eft/common/Ixyz"; import { Item } from "@spt/models/eft/common/tables/IItem"; -export interface ILocation -{ +export interface ILocation { /** Map meta-data */ - base: ILocationBase + base: ILocationBase; /** Loose loot postions and item weights */ - looseLoot: ILooseLoot + looseLoot: ILooseLoot; /** Static loot item weights */ - staticLoot: Record + staticLoot: Record; /** Static container postions and item weights */ - staticContainers: IStaticContainerDetails - staticAmmo: Record + staticContainers: IStaticContainerDetails; + staticAmmo: Record; /** All possible static containers on map + their assign groupings */ - statics: IStaticContainer + statics: IStaticContainer; /** All possible map extracts */ - allExtracts: Exit[] + allExtracts: Exit[]; } -export interface IStaticContainer -{ - containersGroups: Record - containers: Record +export interface IStaticContainer { + containersGroups: Record; + containers: Record; } -export interface IContainerMinMax -{ - minContainers: number - maxContainers: number - current?: number - chosenCount?: number +export interface IContainerMinMax { + minContainers: number; + maxContainers: number; + current?: number; + chosenCount?: number; } -export interface IContainerData -{ - groupId: string +export interface IContainerData { + groupId: string; } -export interface IStaticLootDetails -{ - itemcountDistribution: ItemCountDistribution[] - itemDistribution: ItemDistribution[] +export interface IStaticLootDetails { + itemcountDistribution: ItemCountDistribution[]; + itemDistribution: ItemDistribution[]; } -export interface ItemCountDistribution -{ - count: number - relativeProbability: number +export interface ItemCountDistribution { + count: number; + relativeProbability: number; } -export interface ItemDistribution -{ - tpl: string - relativeProbability: number +export interface ItemDistribution { + tpl: string; + relativeProbability: number; } -export interface IStaticPropsBase -{ - Id: string - IsContainer: boolean - useGravity: boolean - randomRotation: boolean - Position: Ixyz - Rotation: Ixyz - IsGroupPosition: boolean - IsAlwaysSpawn: boolean - GroupPositions: any[] - Root: string - Items: any[] +export interface IStaticPropsBase { + Id: string; + IsContainer: boolean; + useGravity: boolean; + randomRotation: boolean; + Position: Ixyz; + Rotation: Ixyz; + IsGroupPosition: boolean; + IsAlwaysSpawn: boolean; + GroupPositions: any[]; + Root: string; + Items: any[]; } -export interface IStaticWeaponProps extends IStaticPropsBase -{ - Items: Item[] +export interface IStaticWeaponProps extends IStaticPropsBase { + Items: Item[]; } -export interface IStaticContainerDetails -{ - staticWeapons: IStaticWeaponProps[] - staticContainers: IStaticContainerData[] - staticForced: IStaticForcedProps[] +export interface IStaticContainerDetails { + staticWeapons: IStaticWeaponProps[]; + staticContainers: IStaticContainerData[]; + staticForced: IStaticForcedProps[]; } -export interface IStaticContainerData -{ - probability: number - template: IStaticContainerProps +export interface IStaticContainerData { + probability: number; + template: IStaticContainerProps; } -export interface IStaticAmmoDetails -{ - tpl: string - relativeProbability: number +export interface IStaticAmmoDetails { + tpl: string; + relativeProbability: number; } -export interface IStaticForcedProps -{ - containerId: string - itemTpl: string +export interface IStaticForcedProps { + containerId: string; + itemTpl: string; } -export interface IStaticContainerProps extends IStaticPropsBase -{ - Items: StaticItem[] +export interface IStaticContainerProps extends IStaticPropsBase { + Items: StaticItem[]; } -export interface StaticItem -{ - _id: string - _tpl: string +export interface StaticItem { + _id: string; + _tpl: string; } diff --git a/project/src/models/eft/common/ILocationBase.ts b/project/src/models/eft/common/ILocationBase.ts index 28c21d81..795e45af 100644 --- a/project/src/models/eft/common/ILocationBase.ts +++ b/project/src/models/eft/common/ILocationBase.ts @@ -1,287 +1,267 @@ import { MinMax } from "@spt/models/common/MinMax"; import { Ixyz } from "@spt/models/eft/common/Ixyz"; -export interface ILocationBase -{ - AccessKeys: string[] - AirdropParameters: AirdropParameter[] - Area: number - AveragePlayTime: number - AveragePlayerLevel: number - Banners: Banner[] - BossLocationSpawn: BossLocationSpawn[] - BotAssault: number - BotEasy: number - BotHard: number - BotImpossible: number - BotLocationModifier: BotLocationModifier - BotMarksman: number - BotMax: number - BotMaxPlayer: number - BotMaxTimePlayer: number - BotMaxPvE: number - BotNormal: number - BotSpawnCountStep: number - BotSpawnPeriodCheck: number - BotSpawnTimeOffMax: number - BotSpawnTimeOffMin: number - BotSpawnTimeOnMax: number - BotSpawnTimeOnMin: number - BotStart: number - BotStop: number - Description: string - DisabledForScav: boolean - DisabledScavExits: string - Enabled: boolean - EnableCoop: boolean - GlobalLootChanceModifier: number - GlobalLootChanceModifierPvE: number - GlobalContainerChanceModifier: number - IconX: number - IconY: number - Id: string - Insurance: boolean - IsSecret: boolean - Locked: boolean - Loot: any[] - MatchMakerMinPlayersByWaitTime: MinPlayerWaitTime[] - MaxBotPerZone: number - MaxDistToFreePoint: number - MaxPlayers: number - MinDistToExitPoint: number - MinDistToFreePoint: number - MinMaxBots: MinMaxBot[] - MinPlayers: number - MaxCoopGroup: number - Name: string - NonWaveGroupScenario: INonWaveGroupScenario - NewSpawn: boolean - OcculsionCullingEnabled: boolean - OldSpawn: boolean - OpenZones: string - Preview: Preview - PlayersRequestCount: number - RequiredPlayerLevel?: number - RequiredPlayerLevelMin?: number - RequiredPlayerLevelMax?: number - MinPlayerLvlAccessKeys: number - PmcMaxPlayersInGroup: number - ScavMaxPlayersInGroup: number - Rules: string - SafeLocation: boolean - Scene: Scene - SpawnPointParams: SpawnPointParam[] - UnixDateTime: number - _Id: string - doors: any[] - EscapeTimeLimit: number - EscapeTimeLimitCoop: number - EscapeTimeLimitPVE: number - exit_access_time: number - ForceOnlineRaidInPVE: boolean - exit_count: number - exit_time: number - exits: Exit[] - filter_ex: string[] - limits: ILimit[] - matching_min_seconds: number - GenerateLocalLootCache: boolean - maxItemCountInLocation: MaxItemCountInLocation[] - sav_summon_seconds: number - tmp_location_field_remove_me: number - users_gather_seconds: number - users_spawn_seconds_n: number - users_spawn_seconds_n2: number - users_summon_seconds: number - waves: Wave[] +export interface ILocationBase { + AccessKeys: string[]; + AirdropParameters: AirdropParameter[]; + Area: number; + AveragePlayTime: number; + AveragePlayerLevel: number; + Banners: Banner[]; + BossLocationSpawn: BossLocationSpawn[]; + BotAssault: number; + BotEasy: number; + BotHard: number; + BotImpossible: number; + BotLocationModifier: BotLocationModifier; + BotMarksman: number; + BotMax: number; + BotMaxPlayer: number; + BotMaxTimePlayer: number; + BotMaxPvE: number; + BotNormal: number; + BotSpawnCountStep: number; + BotSpawnPeriodCheck: number; + BotSpawnTimeOffMax: number; + BotSpawnTimeOffMin: number; + BotSpawnTimeOnMax: number; + BotSpawnTimeOnMin: number; + BotStart: number; + BotStop: number; + Description: string; + DisabledForScav: boolean; + DisabledScavExits: string; + Enabled: boolean; + EnableCoop: boolean; + GlobalLootChanceModifier: number; + GlobalLootChanceModifierPvE: number; + GlobalContainerChanceModifier: number; + IconX: number; + IconY: number; + Id: string; + Insurance: boolean; + IsSecret: boolean; + Locked: boolean; + Loot: any[]; + MatchMakerMinPlayersByWaitTime: MinPlayerWaitTime[]; + MaxBotPerZone: number; + MaxDistToFreePoint: number; + MaxPlayers: number; + MinDistToExitPoint: number; + MinDistToFreePoint: number; + MinMaxBots: MinMaxBot[]; + MinPlayers: number; + MaxCoopGroup: number; + Name: string; + NonWaveGroupScenario: INonWaveGroupScenario; + NewSpawn: boolean; + OcculsionCullingEnabled: boolean; + OldSpawn: boolean; + OpenZones: string; + Preview: Preview; + PlayersRequestCount: number; + RequiredPlayerLevel?: number; + RequiredPlayerLevelMin?: number; + RequiredPlayerLevelMax?: number; + MinPlayerLvlAccessKeys: number; + PmcMaxPlayersInGroup: number; + ScavMaxPlayersInGroup: number; + Rules: string; + SafeLocation: boolean; + Scene: Scene; + SpawnPointParams: SpawnPointParam[]; + UnixDateTime: number; + _Id: string; + doors: any[]; + EscapeTimeLimit: number; + EscapeTimeLimitCoop: number; + EscapeTimeLimitPVE: number; + exit_access_time: number; + ForceOnlineRaidInPVE: boolean; + exit_count: number; + exit_time: number; + exits: Exit[]; + filter_ex: string[]; + limits: ILimit[]; + matching_min_seconds: number; + GenerateLocalLootCache: boolean; + maxItemCountInLocation: MaxItemCountInLocation[]; + sav_summon_seconds: number; + tmp_location_field_remove_me: number; + users_gather_seconds: number; + users_spawn_seconds_n: number; + users_spawn_seconds_n2: number; + users_summon_seconds: number; + waves: Wave[]; } -export interface INonWaveGroupScenario -{ - Chance: number - Enabled: boolean - MaxToBeGroup: number - MinToBeGroup: number +export interface INonWaveGroupScenario { + Chance: number; + Enabled: boolean; + MaxToBeGroup: number; + MinToBeGroup: number; } -export interface ILimit extends MinMax -{ - items: any[] +export interface ILimit extends MinMax { + items: any[]; } -export interface AirdropParameter -{ - AirdropPointDeactivateDistance: number - MinPlayersCountToSpawnAirdrop: number - PlaneAirdropChance: number - PlaneAirdropCooldownMax: number - PlaneAirdropCooldownMin: number - PlaneAirdropEnd: number - PlaneAirdropMax: number - PlaneAirdropStartMax: number - PlaneAirdropStartMin: number - UnsuccessfulTryPenalty: number +export interface AirdropParameter { + AirdropPointDeactivateDistance: number; + MinPlayersCountToSpawnAirdrop: number; + PlaneAirdropChance: number; + PlaneAirdropCooldownMax: number; + PlaneAirdropCooldownMin: number; + PlaneAirdropEnd: number; + PlaneAirdropMax: number; + PlaneAirdropStartMax: number; + PlaneAirdropStartMin: number; + UnsuccessfulTryPenalty: number; } -export interface Banner -{ - id: string - pic: Pic +export interface Banner { + id: string; + pic: Pic; } -export interface Pic -{ - path: string - rcid: string +export interface Pic { + path: string; + rcid: string; } -export interface BossLocationSpawn -{ - BossChance: number - BossDifficult: string - BossEscortAmount: string - BossEscortDifficult: string - BossEscortType: string - BossName: string - BossPlayer: boolean - BossZone: string - RandomTimeSpawn: boolean - Time: number - TriggerId: string - TriggerName: string - Delay?: number - ForceSpawn?: boolean - IgnoreMaxBots?: boolean - Supports?: BossSupport[] - sptId?: string - spawnMode: string[] +export interface BossLocationSpawn { + BossChance: number; + BossDifficult: string; + BossEscortAmount: string; + BossEscortDifficult: string; + BossEscortType: string; + BossName: string; + BossPlayer: boolean; + BossZone: string; + RandomTimeSpawn: boolean; + Time: number; + TriggerId: string; + TriggerName: string; + Delay?: number; + ForceSpawn?: boolean; + IgnoreMaxBots?: boolean; + Supports?: BossSupport[]; + sptId?: string; + spawnMode: string[]; } -export interface BossSupport -{ - BossEscortAmount: string - BossEscortDifficult: string[] - BossEscortType: string +export interface BossSupport { + BossEscortAmount: string; + BossEscortDifficult: string[]; + BossEscortType: string; } -export interface BotLocationModifier -{ - AccuracySpeed: number - DistToActivate: number - DistToActivatePvE: number - DistToPersueAxemanCoef: number - DistToSleep: number - DistToSleepPvE: number - GainSight: number - KhorovodChance: number - MagnetPower: number - MarksmanAccuratyCoef: number - Scattering: number - VisibleDistance: number - MaxExfiltrationTime: number - MinExfiltrationTime: number +export interface BotLocationModifier { + AccuracySpeed: number; + DistToActivate: number; + DistToActivatePvE: number; + DistToPersueAxemanCoef: number; + DistToSleep: number; + DistToSleepPvE: number; + GainSight: number; + KhorovodChance: number; + MagnetPower: number; + MarksmanAccuratyCoef: number; + Scattering: number; + VisibleDistance: number; + MaxExfiltrationTime: number; + MinExfiltrationTime: number; } -export interface MinMaxBot extends MinMax -{ - WildSpawnType: WildSpawnType | string +export interface MinMaxBot extends MinMax { + WildSpawnType: WildSpawnType | string; } -export interface MinPlayerWaitTime -{ - minPlayers: number - time: number +export interface MinPlayerWaitTime { + minPlayers: number; + time: number; } -export interface Preview -{ - path: string - rcid: string +export interface Preview { + path: string; + rcid: string; } -export interface Scene -{ - path: string - rcid: string +export interface Scene { + path: string; + rcid: string; } -export interface SpawnPointParam -{ - BotZoneName: string - Categories: string[] - ColliderParams: ColliderParams - CorePointId: number - DelayToCanSpawnSec: number - Id: string - Infiltration: string - Position: Ixyz - Rotation: number - Sides: string[] +export interface SpawnPointParam { + BotZoneName: string; + Categories: string[]; + ColliderParams: ColliderParams; + CorePointId: number; + DelayToCanSpawnSec: number; + Id: string; + Infiltration: string; + Position: Ixyz; + Rotation: number; + Sides: string[]; } -export interface ColliderParams -{ - _parent: string - _props: Props +export interface ColliderParams { + _parent: string; + _props: Props; } -export interface Props -{ - Center: Ixyz - Radius: number +export interface Props { + Center: Ixyz; + Radius: number; } -export interface Exit -{ +export interface Exit { /** % Chance out of 100 exit will appear in raid */ - Chance: number - ChancePVE: number - Count: number - CountPVE: number - EntryPoints: string - EventAvailable: boolean - ExfiltrationTime: number - ExfiltrationTimePVE: number - ExfiltrationType: string - RequiredSlot?: string - Id: string - MaxTime: number - MaxTimePVE: number - MinTime: number - MinTimePVE: number - Name: string - PassageRequirement: string - PlayersCount: number - PlayersCountPVE: number - RequirementTip: string - Side?: string + Chance: number; + ChancePVE: number; + Count: number; + CountPVE: number; + EntryPoints: string; + EventAvailable: boolean; + ExfiltrationTime: number; + ExfiltrationTimePVE: number; + ExfiltrationType: string; + RequiredSlot?: string; + Id: string; + MaxTime: number; + MaxTimePVE: number; + MinTime: number; + MinTimePVE: number; + Name: string; + PassageRequirement: string; + PlayersCount: number; + PlayersCountPVE: number; + RequirementTip: string; + Side?: string; } -export interface MaxItemCountInLocation -{ - TemplateId: string - Value: number +export interface MaxItemCountInLocation { + TemplateId: string; + Value: number; } -export interface Wave -{ - BotPreset: string - BotSide: string - SpawnPoints: string - WildSpawnType: WildSpawnType - isPlayers: boolean - number: number - slots_max: number - slots_min: number - time_max: number - time_min: number - sptId?: string - ChanceGroup?: number - SpawnMode: string[] +export interface Wave { + BotPreset: string; + BotSide: string; + SpawnPoints: string; + WildSpawnType: WildSpawnType; + isPlayers: boolean; + number: number; + slots_max: number; + slots_min: number; + time_max: number; + time_min: number; + sptId?: string; + ChanceGroup?: number; + SpawnMode: string[]; } -export enum WildSpawnType -{ +export enum WildSpawnType { ASSAULT = "assault", MARKSMAN = "marksman", PMCBOT = "pmcbot", diff --git a/project/src/models/eft/common/ILocationsSourceDestinationBase.ts b/project/src/models/eft/common/ILocationsSourceDestinationBase.ts index 60f43d89..79234e89 100644 --- a/project/src/models/eft/common/ILocationsSourceDestinationBase.ts +++ b/project/src/models/eft/common/ILocationsSourceDestinationBase.ts @@ -1,13 +1,11 @@ import { ILocations } from "@spt/models/spt/server/ILocations"; -export interface ILocationsGenerateAllResponse -{ - locations: ILocations - paths: Path[] +export interface ILocationsGenerateAllResponse { + locations: ILocations; + paths: Path[]; } -export interface Path -{ - Source: string - Destination: string +export interface Path { + Source: string; + Destination: string; } diff --git a/project/src/models/eft/common/ILooseLoot.ts b/project/src/models/eft/common/ILooseLoot.ts index 61441726..aa04f73c 100644 --- a/project/src/models/eft/common/ILooseLoot.ts +++ b/project/src/models/eft/common/ILooseLoot.ts @@ -1,56 +1,49 @@ import { Ixyz } from "@spt/models/eft/common/Ixyz"; import { Item } from "@spt/models/eft/common/tables/IItem"; -export interface ILooseLoot -{ - spawnpointCount: SpawnpointCount - spawnpointsForced: SpawnpointsForced[] - spawnpoints: Spawnpoint[] +export interface ILooseLoot { + spawnpointCount: SpawnpointCount; + spawnpointsForced: SpawnpointsForced[]; + spawnpoints: Spawnpoint[]; } -export interface SpawnpointCount -{ - mean: number - std: number +export interface SpawnpointCount { + mean: number; + std: number; } -export interface SpawnpointsForced -{ - locationId: string - probability: number - template: SpawnpointTemplate +export interface SpawnpointsForced { + locationId: string; + probability: number; + template: SpawnpointTemplate; } -export interface SpawnpointTemplate -{ - Id: string - IsContainer: boolean - useGravity: boolean - randomRotation: boolean - Position: Ixyz - Rotation: Ixyz - IsAlwaysSpawn: boolean - IsGroupPosition: boolean - GroupPositions: any[] - Root: string - Items: Item[] +export interface SpawnpointTemplate { + Id: string; + IsContainer: boolean; + useGravity: boolean; + randomRotation: boolean; + Position: Ixyz; + Rotation: Ixyz; + IsAlwaysSpawn: boolean; + IsGroupPosition: boolean; + GroupPositions: any[]; + Root: string; + Items: Item[]; } -export interface Spawnpoint -{ - locationId: string - probability: number - template: SpawnpointTemplate - itemDistribution: ItemDistribution[] +export interface Spawnpoint { + locationId: string; + probability: number; + template: SpawnpointTemplate; + itemDistribution: ItemDistribution[]; } -export interface ItemDistribution -{ - composedKey: ComposedKey - relativeProbability: number +export interface ItemDistribution { + composedKey: ComposedKey; + relativeProbability: number; } -export interface ComposedKey -{ - key: string +export interface ComposedKey { + key: string; } diff --git a/project/src/models/eft/common/IMetricsTableData.ts b/project/src/models/eft/common/IMetricsTableData.ts index fb78ca07..873ef824 100644 --- a/project/src/models/eft/common/IMetricsTableData.ts +++ b/project/src/models/eft/common/IMetricsTableData.ts @@ -1,8 +1,7 @@ -export interface IMetricsTableData -{ - Keys: number[] - NetProcessingBins: number[] - RenderBins: number[] - GameUpdateBins: number[] - MemoryMeasureInterval: number +export interface IMetricsTableData { + Keys: number[]; + NetProcessingBins: number[]; + RenderBins: number[]; + GameUpdateBins: number[]; + MemoryMeasureInterval: number; } diff --git a/project/src/models/eft/common/IPmcData.ts b/project/src/models/eft/common/IPmcData.ts index a0373418..1e566f8f 100644 --- a/project/src/models/eft/common/IPmcData.ts +++ b/project/src/models/eft/common/IPmcData.ts @@ -1,16 +1,13 @@ import { IBotBase, IEftStats } from "@spt/models/eft/common/tables/IBotBase"; -export interface IPmcData extends IBotBase -{} +export interface IPmcData extends IBotBase {} -export interface IPostRaidPmcData extends IBotBase -{ - Stats: IPostRaidStats +export interface IPostRaidPmcData extends IBotBase { + Stats: IPostRaidStats; } -export interface IPostRaidStats -{ - Eft: IEftStats +export interface IPostRaidStats { + Eft: IEftStats; /** Only found in profile we get from client post raid */ - Arena: IEftStats + Arena: IEftStats; } diff --git a/project/src/models/eft/common/Ixyz.ts b/project/src/models/eft/common/Ixyz.ts index 58719f6c..612dae10 100644 --- a/project/src/models/eft/common/Ixyz.ts +++ b/project/src/models/eft/common/Ixyz.ts @@ -1,6 +1,5 @@ -export interface Ixyz -{ - x: number - y: number - z: number +export interface Ixyz { + x: number; + y: number; + z: number; } diff --git a/project/src/models/eft/common/request/IBaseInteractionRequestData.ts b/project/src/models/eft/common/request/IBaseInteractionRequestData.ts index 0fa1fe47..c6011cea 100644 --- a/project/src/models/eft/common/request/IBaseInteractionRequestData.ts +++ b/project/src/models/eft/common/request/IBaseInteractionRequestData.ts @@ -1,12 +1,10 @@ -export interface IBaseInteractionRequestData -{ - Action: string - fromOwner?: OwnerInfo - toOwner?: OwnerInfo +export interface IBaseInteractionRequestData { + Action: string; + fromOwner?: OwnerInfo; + toOwner?: OwnerInfo; } -export interface OwnerInfo -{ - id: string - type: string +export interface OwnerInfo { + id: string; + type: string; } diff --git a/project/src/models/eft/common/request/IUIDRequestData.ts b/project/src/models/eft/common/request/IUIDRequestData.ts index cd775f49..d905ad77 100644 --- a/project/src/models/eft/common/request/IUIDRequestData.ts +++ b/project/src/models/eft/common/request/IUIDRequestData.ts @@ -1,4 +1,3 @@ -export interface IUIDRequestData -{ - uid: string +export interface IUIDRequestData { + uid: string; } diff --git a/project/src/models/eft/common/tables/IAchievement.ts b/project/src/models/eft/common/tables/IAchievement.ts index a87e33b0..5ea9c66e 100644 --- a/project/src/models/eft/common/tables/IAchievement.ts +++ b/project/src/models/eft/common/tables/IAchievement.ts @@ -1,20 +1,19 @@ import { IQuestConditionTypes, IQuestRewards } from "@spt/models/eft/common/tables/IQuest"; -export interface IAchievement -{ - id: string - imageUrl: string - assetPath: string - rewards: IQuestRewards - conditions: IQuestConditionTypes - instantComplete: boolean - showNotificationsInGame: boolean - showProgress: boolean - prefab: string - rarity: string - hidden: boolean - showConditions: boolean - progressBarEnabled: boolean - side: string - index: number +export interface IAchievement { + id: string; + imageUrl: string; + assetPath: string; + rewards: IQuestRewards; + conditions: IQuestConditionTypes; + instantComplete: boolean; + showNotificationsInGame: boolean; + showProgress: boolean; + prefab: string; + rarity: string; + hidden: boolean; + showConditions: boolean; + progressBarEnabled: boolean; + side: string; + index: number; } diff --git a/project/src/models/eft/common/tables/IBotBase.ts b/project/src/models/eft/common/tables/IBotBase.ts index 7c916801..9354d7d0 100644 --- a/project/src/models/eft/common/tables/IBotBase.ts +++ b/project/src/models/eft/common/tables/IBotBase.ts @@ -7,113 +7,105 @@ import { HideoutAreas } from "@spt/models/enums/HideoutAreas"; import { MemberCategory } from "@spt/models/enums/MemberCategory"; import { QuestStatus } from "@spt/models/enums/QuestStatus"; -export interface IBotBase -{ - _id: string - aid: number +export interface IBotBase { + _id: string; + aid: number; /** SPT property - use to store player id - TODO - move to AID ( account id as guid of choice) */ - sessionId: string - savage?: string - Info: Info - Customization: Customization - Health: Health - Inventory: Inventory - Skills: Skills - Stats: Stats - Encyclopedia: Record - TaskConditionCounters: Record - InsuredItems: IInsuredItem[] - Hideout: Hideout - Quests: IQuestStatus[] - TradersInfo: Record - UnlockedInfo: IUnlockedInfo - RagfairInfo: RagfairInfo + sessionId: string; + savage?: string; + Info: Info; + Customization: Customization; + Health: Health; + Inventory: Inventory; + Skills: Skills; + Stats: Stats; + Encyclopedia: Record; + TaskConditionCounters: Record; + InsuredItems: IInsuredItem[]; + Hideout: Hideout; + Quests: IQuestStatus[]; + TradersInfo: Record; + UnlockedInfo: IUnlockedInfo; + RagfairInfo: RagfairInfo; /** Achievement id and timestamp */ - Achievements: Record - RepeatableQuests: IPmcDataRepeatableQuest[] - Bonuses: Bonus[] - Notes: Notes - CarExtractCounts: Record - CoopExtractCounts: Record - SurvivorClass: SurvivorClass - WishList: Record - moneyTransferLimitData: IMoneyTransferLimits + Achievements: Record; + RepeatableQuests: IPmcDataRepeatableQuest[]; + Bonuses: Bonus[]; + Notes: Notes; + CarExtractCounts: Record; + CoopExtractCounts: Record; + SurvivorClass: SurvivorClass; + WishList: Record; + moneyTransferLimitData: IMoneyTransferLimits; /** SPT specific property used during bot generation in raid */ - sptIsPmc?: boolean + sptIsPmc?: boolean; } -export interface IMoneyTransferLimits -{ +export interface IMoneyTransferLimits { // Resets every 24 hours in live /** TODO: Implement */ - nextResetTime: number - remainingLimit: number - totalLimit: number - resetInterval: number + nextResetTime: number; + remainingLimit: number; + totalLimit: number; + resetInterval: number; } -export interface ITaskConditionCounter -{ - id: string - type: string - value: number +export interface ITaskConditionCounter { + id: string; + type: string; + value: number; /** Quest id */ - sourceId: string + sourceId: string; } -export interface IUnlockedInfo -{ - unlockedProductionRecipe: string[] +export interface IUnlockedInfo { + unlockedProductionRecipe: string[]; } -export interface Info -{ - EntryPoint: string - Nickname: string - LowerNickname: string - Side: string - SquadInviteRestriction: boolean - HasCoopExtension: boolean - Voice: string - Level: number - Experience: number - RegistrationDate: number - GameVersion: string - AccountType: number - MemberCategory: MemberCategory - SelectedMemberCategory: MemberCategory - lockedMoveCommands: boolean - SavageLockTime: number - LastTimePlayedAsSavage: number - Settings: Settings - NicknameChangeDate: number - NeedWipeOptions: any[] - lastCompletedWipe: LastCompleted - Bans: IBan[] - BannedState: boolean - BannedUntil: number - IsStreamerModeAvailable: boolean - lastCompletedEvent?: LastCompleted - isMigratedSkills: boolean +export interface Info { + EntryPoint: string; + Nickname: string; + LowerNickname: string; + Side: string; + SquadInviteRestriction: boolean; + HasCoopExtension: boolean; + Voice: string; + Level: number; + Experience: number; + RegistrationDate: number; + GameVersion: string; + AccountType: number; + MemberCategory: MemberCategory; + SelectedMemberCategory: MemberCategory; + lockedMoveCommands: boolean; + SavageLockTime: number; + LastTimePlayedAsSavage: number; + Settings: Settings; + NicknameChangeDate: number; + NeedWipeOptions: any[]; + lastCompletedWipe: LastCompleted; + Bans: IBan[]; + BannedState: boolean; + BannedUntil: number; + IsStreamerModeAvailable: boolean; + lastCompletedEvent?: LastCompleted; + isMigratedSkills: boolean; } -export interface Settings -{ - Role: string - BotDifficulty: string - Experience: number - StandingForKill: number - AggressorBonus: number +export interface Settings { + Role: string; + BotDifficulty: string; + Experience: number; + StandingForKill: number; + AggressorBonus: number; } -export interface IBan -{ - banType: BanType - dateTime: number +export interface IBan { + banType: BanType; + dateTime: number; } -export enum BanType -{ +export enum BanType { CHAT = 0, RAGFAIR = 1, VOIP = 2, @@ -123,360 +115,317 @@ export enum BanType CHANGE_NICKNAME = 6, } -export interface Customization -{ - Head: string - Body: string - Feet: string - Hands: string +export interface Customization { + Head: string; + Body: string; + Feet: string; + Hands: string; } -export interface Health -{ - Hydration: CurrentMax - Energy: CurrentMax - Temperature: CurrentMax - BodyParts: BodyPartsHealth - UpdateTime: number - Immortal?: boolean +export interface Health { + Hydration: CurrentMax; + Energy: CurrentMax; + Temperature: CurrentMax; + BodyParts: BodyPartsHealth; + UpdateTime: number; + Immortal?: boolean; } -export interface BodyPartsHealth -{ - Head: BodyPartHealth - Chest: BodyPartHealth - Stomach: BodyPartHealth - LeftArm: BodyPartHealth - RightArm: BodyPartHealth - LeftLeg: BodyPartHealth - RightLeg: BodyPartHealth +export interface BodyPartsHealth { + Head: BodyPartHealth; + Chest: BodyPartHealth; + Stomach: BodyPartHealth; + LeftArm: BodyPartHealth; + RightArm: BodyPartHealth; + LeftLeg: BodyPartHealth; + RightLeg: BodyPartHealth; } -export interface BodyPartHealth -{ - Health: CurrentMax - Effects?: Record +export interface BodyPartHealth { + Health: CurrentMax; + Effects?: Record; } -export interface BodyPartEffectProperties -{ - Time: number +export interface BodyPartEffectProperties { + Time: number; } -export interface CurrentMax -{ - Current: number - Maximum: number +export interface CurrentMax { + Current: number; + Maximum: number; } -export interface Inventory -{ - items: Item[] - equipment: string - stash: string - sortingTable: string - questRaidItems: string - questStashItems: string +export interface Inventory { + items: Item[]; + equipment: string; + stash: string; + sortingTable: string; + questRaidItems: string; + questStashItems: string; /** Key is hideout area enum numeric as string e.g. "24", value is area _id */ - hideoutAreaStashes: Record - fastPanel: Record - favoriteItems: string[] + hideoutAreaStashes: Record; + fastPanel: Record; + favoriteItems: string[]; } -export interface IBaseJsonSkills -{ - Common: Record - Mastering: Record - Points: number +export interface IBaseJsonSkills { + Common: Record; + Mastering: Record; + Points: number; } -export interface Skills -{ - Common: Common[] - Mastering: Mastering[] - Points: number +export interface Skills { + Common: Common[]; + Mastering: Mastering[]; + Points: number; } -export interface IBaseSkill -{ - Id: string - Progress: number - max?: number - min?: number +export interface IBaseSkill { + Id: string; + Progress: number; + max?: number; + min?: number; } -export interface Common extends IBaseSkill -{ - PointsEarnedDuringSession?: number - LastAccess?: number +export interface Common extends IBaseSkill { + PointsEarnedDuringSession?: number; + LastAccess?: number; } -export interface Mastering extends IBaseSkill -{} +export interface Mastering extends IBaseSkill {} -export interface Stats -{ - Eft?: IEftStats +export interface Stats { + Eft?: IEftStats; } -export interface IEftStats -{ - CarriedQuestItems: string[] - Victims: Victim[] - TotalSessionExperience: number - LastSessionDate: number - SessionCounters: SessionCounters - OverallCounters: OverallCounters - SessionExperienceMult?: number - ExperienceBonusMult?: number - Aggressor?: Aggressor - DroppedItems?: IDroppedItem[] - FoundInRaidItems?: FoundInRaidItem[] - DamageHistory?: DamageHistory - DeathCause?: DeathCause - LastPlayerState?: LastPlayerState - TotalInGameTime: number - SurvivorClass?: string - sptLastRaidFenceRepChange?: number +export interface IEftStats { + CarriedQuestItems: string[]; + Victims: Victim[]; + TotalSessionExperience: number; + LastSessionDate: number; + SessionCounters: SessionCounters; + OverallCounters: OverallCounters; + SessionExperienceMult?: number; + ExperienceBonusMult?: number; + Aggressor?: Aggressor; + DroppedItems?: IDroppedItem[]; + FoundInRaidItems?: FoundInRaidItem[]; + DamageHistory?: DamageHistory; + DeathCause?: DeathCause; + LastPlayerState?: LastPlayerState; + TotalInGameTime: number; + SurvivorClass?: string; + sptLastRaidFenceRepChange?: number; } -export interface IDroppedItem -{ - QuestId: string - ItemId: string - ZoneId: string +export interface IDroppedItem { + QuestId: string; + ItemId: string; + ZoneId: string; } -export interface FoundInRaidItem -{ - QuestId: string - ItemId: string +export interface FoundInRaidItem { + QuestId: string; + ItemId: string; } -export interface Victim -{ - AccountId: string - ProfileId: string - Name: string - Side: string - BodyPart: string - Time: string - Distance: number - Level: number - Weapon: string - Role: string +export interface Victim { + AccountId: string; + ProfileId: string; + Name: string; + Side: string; + BodyPart: string; + Time: string; + Distance: number; + Level: number; + Weapon: string; + Role: string; } -export interface SessionCounters -{ - Items: CounterKeyValue[] +export interface SessionCounters { + Items: CounterKeyValue[]; } -export interface OverallCounters -{ - Items: CounterKeyValue[] +export interface OverallCounters { + Items: CounterKeyValue[]; } -export interface CounterKeyValue -{ - Key: string[] - Value: number +export interface CounterKeyValue { + Key: string[]; + Value: number; } -export interface Aggressor -{ - AccountId: string - ProfileId: string - MainProfileNickname: string - Name: string - Side: string - BodyPart: string - HeadSegment: string - WeaponName: string - Category: string +export interface Aggressor { + AccountId: string; + ProfileId: string; + MainProfileNickname: string; + Name: string; + Side: string; + BodyPart: string; + HeadSegment: string; + WeaponName: string; + Category: string; } -export interface DamageHistory -{ - LethalDamagePart: string - LethalDamage: LethalDamage - BodyParts: BodyPartsDamageHistory +export interface DamageHistory { + LethalDamagePart: string; + LethalDamage: LethalDamage; + BodyParts: BodyPartsDamageHistory; } -export interface LethalDamage -{ - Amount: number - Type: string - SourceId: string - OverDamageFrom: string - Blunt: boolean - ImpactsCount: number +export interface LethalDamage { + Amount: number; + Type: string; + SourceId: string; + OverDamageFrom: string; + Blunt: boolean; + ImpactsCount: number; } -export interface BodyPartsDamageHistory -{ - Head: DamageStats[] - Chest: DamageStats[] - Stomach: DamageStats[] - LeftArm: DamageStats[] - RightArm: DamageStats[] - LeftLeg: DamageStats[] - RightLeg: DamageStats[] - Common: DamageStats[] +export interface BodyPartsDamageHistory { + Head: DamageStats[]; + Chest: DamageStats[]; + Stomach: DamageStats[]; + LeftArm: DamageStats[]; + RightArm: DamageStats[]; + LeftLeg: DamageStats[]; + RightLeg: DamageStats[]; + Common: DamageStats[]; } -export interface DamageStats -{ - Amount: number - Type: string - SourceId: string - OverDamageFrom: string - Blunt: boolean - ImpactsCount: number +export interface DamageStats { + Amount: number; + Type: string; + SourceId: string; + OverDamageFrom: string; + Blunt: boolean; + ImpactsCount: number; } -export interface DeathCause -{ - DamageType: string - Side: string - Role: string - WeaponId: string +export interface DeathCause { + DamageType: string; + Side: string; + Role: string; + WeaponId: string; } -export interface LastPlayerState -{ - Info: LastPlayerStateInfo - Customization: Record - Equipment: any +export interface LastPlayerState { + Info: LastPlayerStateInfo; + Customization: Record; + Equipment: any; } -export interface LastPlayerStateInfo -{ - Nickname: string - Side: string - Level: number - MemberCategory: MemberCategory +export interface LastPlayerStateInfo { + Nickname: string; + Side: string; + Level: number; + MemberCategory: MemberCategory; } -export interface BackendCounter -{ - id: string - qid?: string - value: number +export interface BackendCounter { + id: string; + qid?: string; + value: number; } -export interface IInsuredItem -{ +export interface IInsuredItem { /** Trader Id item was insured by */ - tid: string - itemId: string + tid: string; + itemId: string; } -export interface Hideout -{ - Production: Record - Areas: HideoutArea[] - Improvement: Record - Seed: number - sptUpdateLastRunTimestamp: number +export interface Hideout { + Production: Record; + Areas: HideoutArea[]; + Improvement: Record; + Seed: number; + sptUpdateLastRunTimestamp: number; } -export interface IHideoutImprovement -{ - completed: boolean - improveCompleteTimestamp: number +export interface IHideoutImprovement { + completed: boolean; + improveCompleteTimestamp: number; } -export interface Productive -{ - Products: Product[] +export interface Productive { + Products: Product[]; /** Seconds passed of production */ - Progress?: number + Progress?: number; /** Is craft in some state of being worked on by client (crafting/ready to pick up) */ - inProgress?: boolean - StartTimestamp?: number - SkipTime?: number + inProgress?: boolean; + StartTimestamp?: number; + SkipTime?: number; /** Seconds needed to fully craft */ - ProductionTime?: number - GivenItemsInStart?: string[] - Interrupted?: boolean - Code?: string - Decoded?: boolean - AvailableForFinish?: boolean + ProductionTime?: number; + GivenItemsInStart?: string[]; + Interrupted?: boolean; + Code?: string; + Decoded?: boolean; + AvailableForFinish?: boolean; /** Used in hideout production.json */ - needFuelForAllProductionTime?: boolean + needFuelForAllProductionTime?: boolean; /** Used when sending data to client */ - NeedFuelForAllProductionTime?: boolean - sptIsScavCase?: boolean + NeedFuelForAllProductionTime?: boolean; + sptIsScavCase?: boolean; /** Some crafts are always inProgress, but need to be reset, e.g. water collector */ - sptIsComplete?: boolean + sptIsComplete?: boolean; /** Is the craft a Continuous, e.g bitcoins/water collector */ - sptIsContinuous?: boolean + sptIsContinuous?: boolean; /** Stores a list of tools used in this craft and whether they're FiR, to give back once the craft is done */ - sptRequiredTools?: Item[] + sptRequiredTools?: Item[]; } -export interface Production extends Productive -{ - RecipeId: string - SkipTime: number - ProductionTime: number +export interface Production extends Productive { + RecipeId: string; + SkipTime: number; + ProductionTime: number; } -export interface ScavCase extends Productive -{ - RecipeId: string +export interface ScavCase extends Productive { + RecipeId: string; } -export interface Product -{ - _id: string - _tpl: string - upd?: Upd +export interface Product { + _id: string; + _tpl: string; + upd?: Upd; } -export interface HideoutArea -{ - type: HideoutAreas - level: number - active: boolean - passiveBonusesEnabled: boolean +export interface HideoutArea { + type: HideoutAreas; + level: number; + active: boolean; + passiveBonusesEnabled: boolean; /** Must be integer */ - completeTime: number - constructing: boolean - slots: HideoutSlot[] - lastRecipe: string + completeTime: number; + constructing: boolean; + slots: HideoutSlot[]; + lastRecipe: string; } -export interface HideoutSlot -{ +export interface HideoutSlot { /** SPT specific value to keep track of what index this slot is (0,1,2,3 etc) */ - locationIndex: number - item?: HideoutItem[] + locationIndex: number; + item?: HideoutItem[]; } -export interface HideoutItem -{ - _id: string - _tpl: string - upd?: Upd +export interface HideoutItem { + _id: string; + _tpl: string; + upd?: Upd; } -export interface LastCompleted -{ - $oid: string +export interface LastCompleted { + $oid: string; } -export interface Notes -{ - Notes: Note[] +export interface Notes { + Notes: Note[]; } -export interface CarExtractCounts -{} +export type CarExtractCounts = {}; -export enum SurvivorClass -{ +export enum SurvivorClass { UNKNOWN = 0, NEUTRALIZER = 1, MARAUDER = 2, @@ -484,50 +433,45 @@ export enum SurvivorClass SURVIVOR = 4, } -export interface IQuestStatus -{ - qid: string - startTime: number - status: QuestStatus - statusTimers?: Record +export interface IQuestStatus { + qid: string; + startTime: number; + status: QuestStatus; + statusTimers?: Record; /** Property does not exist in live profile data, but is used by ProfileChanges.questsStatus when sent to client */ - completedConditions?: string[] - availableAfter?: number + completedConditions?: string[]; + availableAfter?: number; } -export interface TraderInfo -{ - loyaltyLevel: number - salesSum: number - standing: number - nextResupply: number - unlocked: boolean - disabled: boolean +export interface TraderInfo { + loyaltyLevel: number; + salesSum: number; + standing: number; + nextResupply: number; + unlocked: boolean; + disabled: boolean; } -export interface RagfairInfo -{ - rating: number - isRatingGrowing: boolean - offers: IRagfairOffer[] +export interface RagfairInfo { + rating: number; + isRatingGrowing: boolean; + offers: IRagfairOffer[]; } -export interface Bonus -{ - id?: string - type: BonusType - templateId?: string - passive?: boolean - production?: boolean - visible?: boolean - value?: number - icon?: string - filter?: string[] - skillType?: BonusSkillType +export interface Bonus { + id?: string; + type: BonusType; + templateId?: string; + passive?: boolean; + production?: boolean; + visible?: boolean; + value?: number; + icon?: string; + filter?: string[]; + skillType?: BonusSkillType; } -export interface Note -{ - Time: number - Text: string +export interface Note { + Time: number; + Text: string; } diff --git a/project/src/models/eft/common/tables/IBotCore.ts b/project/src/models/eft/common/tables/IBotCore.ts index 9e9859e5..16a782de 100644 --- a/project/src/models/eft/common/tables/IBotCore.ts +++ b/project/src/models/eft/common/tables/IBotCore.ts @@ -1,134 +1,133 @@ -export interface IBotCore -{ - SAVAGE_KILL_DIST: number - SOUND_DOOR_BREACH_METERS: number - SOUND_DOOR_OPEN_METERS: number - STEP_NOISE_DELTA: number - JUMP_NOISE_DELTA: number - GUNSHOT_SPREAD: number - GUNSHOT_SPREAD_SILENCE: number - BASE_WALK_SPEREAD2: number - MOVE_SPEED_COEF_MAX: number - SPEED_SERV_SOUND_COEF_A: number - SPEED_SERV_SOUND_COEF_B: number - G: number - STAY_COEF: number - SIT_COEF: number - LAY_COEF: number - MAX_ITERATIONS: number - START_DIST_TO_COV: number - MAX_DIST_TO_COV: number - STAY_HEIGHT: number - CLOSE_POINTS: number - COUNT_TURNS: number - SIMPLE_POINT_LIFE_TIME_SEC: number - DANGER_POINT_LIFE_TIME_SEC: number - DANGER_POWER: number - COVER_DIST_CLOSE: number - GOOD_DIST_TO_POINT: number - COVER_TOOFAR_FROM_BOSS: number - COVER_TOOFAR_FROM_BOSS_SQRT: number - MAX_Y_DIFF_TO_PROTECT: number - FLARE_POWER: number - MOVE_COEF: number - PRONE_POSE: number - LOWER_POSE: number - MAX_POSE: number - FLARE_TIME: number - MAX_REQUESTS__PER_GROUP: number - UPDATE_GOAL_TIMER_SEC: number - DIST_NOT_TO_GROUP: number - DIST_NOT_TO_GROUP_SQR: number - LAST_SEEN_POS_LIFETIME: number - DELTA_GRENADE_START_TIME: number - DELTA_GRENADE_END_TIME: number - DELTA_GRENADE_RUN_DIST: number - DELTA_GRENADE_RUN_DIST_SQRT: number - PATROL_MIN_LIGHT_DIST: number - HOLD_MIN_LIGHT_DIST: number - STANDART_BOT_PAUSE_DOOR: number - ARMOR_CLASS_COEF: number - SHOTGUN_POWER: number - RIFLE_POWER: number - PISTOL_POWER: number - SMG_POWER: number - SNIPE_POWER: number - GESTUS_PERIOD_SEC: number - GESTUS_AIMING_DELAY: number - GESTUS_REQUEST_LIFETIME: number - GESTUS_FIRST_STAGE_MAX_TIME: number - GESTUS_SECOND_STAGE_MAX_TIME: number - GESTUS_MAX_ANSWERS: number - GESTUS_FUCK_TO_SHOOT: number - GESTUS_DIST_ANSWERS: number - GESTUS_DIST_ANSWERS_SQRT: number - GESTUS_ANYWAY_CHANCE: number - TALK_DELAY: number - CAN_SHOOT_TO_HEAD: boolean - CAN_TILT: boolean - TILT_CHANCE: number - MIN_BLOCK_DIST: number - MIN_BLOCK_TIME: number - COVER_SECONDS_AFTER_LOSE_VISION: number - MIN_ARG_COEF: number - MAX_ARG_COEF: number - DEAD_AGR_DIST: number - MAX_DANGER_CARE_DIST_SQRT: number - MAX_DANGER_CARE_DIST: number - MIN_MAX_PERSON_SEARCH: number - PERCENT_PERSON_SEARCH: number - LOOK_ANYSIDE_BY_WALL_SEC_OF_ENEMY: number - CLOSE_TO_WALL_ROTATE_BY_WALL_SQRT: number - SHOOT_TO_CHANGE_RND_PART_MIN: number - SHOOT_TO_CHANGE_RND_PART_MAX: number - SHOOT_TO_CHANGE_RND_PART_DELTA: number - FORMUL_COEF_DELTA_DIST: number - FORMUL_COEF_DELTA_SHOOT: number - FORMUL_COEF_DELTA_FRIEND_COVER: number - SUSPETION_POINT_DIST_CHECK: number - MAX_BASE_REQUESTS_PER_PLAYER: number - MAX_HOLD_REQUESTS_PER_PLAYER: number - MAX_GO_TO_REQUESTS_PER_PLAYER: number - MAX_COME_WITH_ME_REQUESTS_PER_PLAYER: number - CORE_POINT_MAX_VALUE: number - CORE_POINTS_MAX: number - CORE_POINTS_MIN: number - BORN_POISTS_FREE_ONLY_FAREST_BOT: boolean - BORN_POINSTS_FREE_ONLY_FAREST_PLAYER: boolean - SCAV_GROUPS_TOGETHER: boolean - LAY_DOWN_ANG_SHOOT: number - HOLD_REQUEST_TIME_SEC: number - TRIGGERS_DOWN_TO_RUN_WHEN_MOVE: number - MIN_DIST_TO_RUN_WHILE_ATTACK_MOVING: number - MIN_DIST_TO_RUN_WHILE_ATTACK_MOVING_OTHER_ENEMIS: number - MIN_DIST_TO_STOP_RUN: number - JUMP_SPREAD_DIST: number - LOOK_TIMES_TO_KILL: number - COME_INSIDE_TIMES: number - TOTAL_TIME_KILL: number - TOTAL_TIME_KILL_AFTER_WARN: number - MOVING_AIM_COEF: number - VERTICAL_DIST_TO_IGNORE_SOUND: number - DEFENCE_LEVEL_SHIFT: number - MIN_DIST_CLOSE_DEF: number - USE_ID_PRIOR_WHO_GO: boolean - SMOKE_GRENADE_RADIUS_COEF: number - GRENADE_PRECISION: number - MAX_WARNS_BEFORE_KILL: number - CARE_ENEMY_ONLY_TIME: number - MIDDLE_POINT_COEF: number - MAIN_TACTIC_ONLY_ATTACK: boolean - LAST_DAMAGE_ACTIVE: number - SHALL_DIE_IF_NOT_INITED: boolean - CHECK_BOT_INIT_TIME_SEC: number - WEAPON_ROOT_Y_OFFSET: number - DELTA_SUPRESS_DISTANCE_SQRT: number - DELTA_SUPRESS_DISTANCE: number - WAVE_COEF_LOW: number - WAVE_COEF_MID: number - WAVE_COEF_HIGH: number - WAVE_COEF_HORDE: number - WAVE_ONLY_AS_ONLINE: boolean - LOCAL_BOTS_COUNT: number - AXE_MAN_KILLS_END: number +export interface IBotCore { + SAVAGE_KILL_DIST: number; + SOUND_DOOR_BREACH_METERS: number; + SOUND_DOOR_OPEN_METERS: number; + STEP_NOISE_DELTA: number; + JUMP_NOISE_DELTA: number; + GUNSHOT_SPREAD: number; + GUNSHOT_SPREAD_SILENCE: number; + BASE_WALK_SPEREAD2: number; + MOVE_SPEED_COEF_MAX: number; + SPEED_SERV_SOUND_COEF_A: number; + SPEED_SERV_SOUND_COEF_B: number; + G: number; + STAY_COEF: number; + SIT_COEF: number; + LAY_COEF: number; + MAX_ITERATIONS: number; + START_DIST_TO_COV: number; + MAX_DIST_TO_COV: number; + STAY_HEIGHT: number; + CLOSE_POINTS: number; + COUNT_TURNS: number; + SIMPLE_POINT_LIFE_TIME_SEC: number; + DANGER_POINT_LIFE_TIME_SEC: number; + DANGER_POWER: number; + COVER_DIST_CLOSE: number; + GOOD_DIST_TO_POINT: number; + COVER_TOOFAR_FROM_BOSS: number; + COVER_TOOFAR_FROM_BOSS_SQRT: number; + MAX_Y_DIFF_TO_PROTECT: number; + FLARE_POWER: number; + MOVE_COEF: number; + PRONE_POSE: number; + LOWER_POSE: number; + MAX_POSE: number; + FLARE_TIME: number; + MAX_REQUESTS__PER_GROUP: number; + UPDATE_GOAL_TIMER_SEC: number; + DIST_NOT_TO_GROUP: number; + DIST_NOT_TO_GROUP_SQR: number; + LAST_SEEN_POS_LIFETIME: number; + DELTA_GRENADE_START_TIME: number; + DELTA_GRENADE_END_TIME: number; + DELTA_GRENADE_RUN_DIST: number; + DELTA_GRENADE_RUN_DIST_SQRT: number; + PATROL_MIN_LIGHT_DIST: number; + HOLD_MIN_LIGHT_DIST: number; + STANDART_BOT_PAUSE_DOOR: number; + ARMOR_CLASS_COEF: number; + SHOTGUN_POWER: number; + RIFLE_POWER: number; + PISTOL_POWER: number; + SMG_POWER: number; + SNIPE_POWER: number; + GESTUS_PERIOD_SEC: number; + GESTUS_AIMING_DELAY: number; + GESTUS_REQUEST_LIFETIME: number; + GESTUS_FIRST_STAGE_MAX_TIME: number; + GESTUS_SECOND_STAGE_MAX_TIME: number; + GESTUS_MAX_ANSWERS: number; + GESTUS_FUCK_TO_SHOOT: number; + GESTUS_DIST_ANSWERS: number; + GESTUS_DIST_ANSWERS_SQRT: number; + GESTUS_ANYWAY_CHANCE: number; + TALK_DELAY: number; + CAN_SHOOT_TO_HEAD: boolean; + CAN_TILT: boolean; + TILT_CHANCE: number; + MIN_BLOCK_DIST: number; + MIN_BLOCK_TIME: number; + COVER_SECONDS_AFTER_LOSE_VISION: number; + MIN_ARG_COEF: number; + MAX_ARG_COEF: number; + DEAD_AGR_DIST: number; + MAX_DANGER_CARE_DIST_SQRT: number; + MAX_DANGER_CARE_DIST: number; + MIN_MAX_PERSON_SEARCH: number; + PERCENT_PERSON_SEARCH: number; + LOOK_ANYSIDE_BY_WALL_SEC_OF_ENEMY: number; + CLOSE_TO_WALL_ROTATE_BY_WALL_SQRT: number; + SHOOT_TO_CHANGE_RND_PART_MIN: number; + SHOOT_TO_CHANGE_RND_PART_MAX: number; + SHOOT_TO_CHANGE_RND_PART_DELTA: number; + FORMUL_COEF_DELTA_DIST: number; + FORMUL_COEF_DELTA_SHOOT: number; + FORMUL_COEF_DELTA_FRIEND_COVER: number; + SUSPETION_POINT_DIST_CHECK: number; + MAX_BASE_REQUESTS_PER_PLAYER: number; + MAX_HOLD_REQUESTS_PER_PLAYER: number; + MAX_GO_TO_REQUESTS_PER_PLAYER: number; + MAX_COME_WITH_ME_REQUESTS_PER_PLAYER: number; + CORE_POINT_MAX_VALUE: number; + CORE_POINTS_MAX: number; + CORE_POINTS_MIN: number; + BORN_POISTS_FREE_ONLY_FAREST_BOT: boolean; + BORN_POINSTS_FREE_ONLY_FAREST_PLAYER: boolean; + SCAV_GROUPS_TOGETHER: boolean; + LAY_DOWN_ANG_SHOOT: number; + HOLD_REQUEST_TIME_SEC: number; + TRIGGERS_DOWN_TO_RUN_WHEN_MOVE: number; + MIN_DIST_TO_RUN_WHILE_ATTACK_MOVING: number; + MIN_DIST_TO_RUN_WHILE_ATTACK_MOVING_OTHER_ENEMIS: number; + MIN_DIST_TO_STOP_RUN: number; + JUMP_SPREAD_DIST: number; + LOOK_TIMES_TO_KILL: number; + COME_INSIDE_TIMES: number; + TOTAL_TIME_KILL: number; + TOTAL_TIME_KILL_AFTER_WARN: number; + MOVING_AIM_COEF: number; + VERTICAL_DIST_TO_IGNORE_SOUND: number; + DEFENCE_LEVEL_SHIFT: number; + MIN_DIST_CLOSE_DEF: number; + USE_ID_PRIOR_WHO_GO: boolean; + SMOKE_GRENADE_RADIUS_COEF: number; + GRENADE_PRECISION: number; + MAX_WARNS_BEFORE_KILL: number; + CARE_ENEMY_ONLY_TIME: number; + MIDDLE_POINT_COEF: number; + MAIN_TACTIC_ONLY_ATTACK: boolean; + LAST_DAMAGE_ACTIVE: number; + SHALL_DIE_IF_NOT_INITED: boolean; + CHECK_BOT_INIT_TIME_SEC: number; + WEAPON_ROOT_Y_OFFSET: number; + DELTA_SUPRESS_DISTANCE_SQRT: number; + DELTA_SUPRESS_DISTANCE: number; + WAVE_COEF_LOW: number; + WAVE_COEF_MID: number; + WAVE_COEF_HIGH: number; + WAVE_COEF_HORDE: number; + WAVE_ONLY_AS_ONLINE: boolean; + LOCAL_BOTS_COUNT: number; + AXE_MAN_KILLS_END: number; } diff --git a/project/src/models/eft/common/tables/IBotType.ts b/project/src/models/eft/common/tables/IBotType.ts index ec70e495..0bed40a8 100644 --- a/project/src/models/eft/common/tables/IBotType.ts +++ b/project/src/models/eft/common/tables/IBotType.ts @@ -1,205 +1,189 @@ import { MinMax } from "@spt/models/common/MinMax"; import { Skills } from "@spt/models/eft/common/tables/IBotBase"; -export interface IBotType -{ - appearance: Appearance - chances: Chances - difficulty: Difficulties - experience: Experience - firstName: string[] - generation: Generation - health: Health - inventory: Inventory - lastName: string[] - skills: Skills +export interface IBotType { + appearance: Appearance; + chances: Chances; + difficulty: Difficulties; + experience: Experience; + firstName: string[]; + generation: Generation; + health: Health; + inventory: Inventory; + lastName: string[]; + skills: Skills; } -export interface Appearance -{ - body: Record - feet: Record - hands: Record - head: Record - voice: Record +export interface Appearance { + body: Record; + feet: Record; + hands: Record; + head: Record; + voice: Record; } -export interface Chances -{ - equipment: EquipmentChances - weaponMods: ModsChances - equipmentMods: ModsChances +export interface Chances { + equipment: EquipmentChances; + weaponMods: ModsChances; + equipmentMods: ModsChances; } -export interface EquipmentChances -{ - ArmBand: number - ArmorVest: number - Backpack: number - Earpiece: number - Eyewear: number - FaceCover: number - FirstPrimaryWeapon: number - Headwear: number - Holster: number - Pockets: number - Scabbard: number - SecondPrimaryWeapon: number - SecuredContainer: number - TacticalVest: number +export interface EquipmentChances { + ArmBand: number; + ArmorVest: number; + Backpack: number; + Earpiece: number; + Eyewear: number; + FaceCover: number; + FirstPrimaryWeapon: number; + Headwear: number; + Holster: number; + Pockets: number; + Scabbard: number; + SecondPrimaryWeapon: number; + SecuredContainer: number; + TacticalVest: number; } -export interface ModsChances -{ - mod_charge: number - mod_equipment: number - mod_equipment_000: number - mod_equipment_001: number - mod_equipment_002: number - mod_flashlight: number - mod_foregrip: number - mod_launcher: number - mod_magazine: number - mod_mount: number - mod_mount_000: number - mod_mount_001: number - mod_muzzle: number - mod_nvg: number - mod_pistol_grip: number - mod_reciever: number - mod_scope: number - mod_scope_000: number - mod_scope_001: number - mod_scope_002: number - mod_scope_003: number - mod_sight_front: number - mod_sight_rear: number - mod_stock: number - mod_stock_000: number - mod_stock_akms: number - mod_tactical: number - mod_tactical_000: number - mod_tactical_001: number - mod_tactical_002: number - mod_tactical_003: number - mod_handguard: number +export interface ModsChances { + mod_charge: number; + mod_equipment: number; + mod_equipment_000: number; + mod_equipment_001: number; + mod_equipment_002: number; + mod_flashlight: number; + mod_foregrip: number; + mod_launcher: number; + mod_magazine: number; + mod_mount: number; + mod_mount_000: number; + mod_mount_001: number; + mod_muzzle: number; + mod_nvg: number; + mod_pistol_grip: number; + mod_reciever: number; + mod_scope: number; + mod_scope_000: number; + mod_scope_001: number; + mod_scope_002: number; + mod_scope_003: number; + mod_sight_front: number; + mod_sight_rear: number; + mod_stock: number; + mod_stock_000: number; + mod_stock_akms: number; + mod_tactical: number; + mod_tactical_000: number; + mod_tactical_001: number; + mod_tactical_002: number; + mod_tactical_003: number; + mod_handguard: number; } -export interface Difficulties -{ - easy: Difficulty - normal: Difficulty - hard: Difficulty - impossible: Difficulty +export interface Difficulties { + easy: Difficulty; + normal: Difficulty; + hard: Difficulty; + impossible: Difficulty; } -export interface Difficulty -{ - Aiming: Record - Boss: Record - Change: Record - Core: Record - Cover: Record - Grenade: Record - Hearing: Record - Lay: Record - Look: Record - Mind: Record - Move: Record - Patrol: Record - Scattering: Record - Shoot: Record +export interface Difficulty { + Aiming: Record; + Boss: Record; + Change: Record; + Core: Record; + Cover: Record; + Grenade: Record; + Hearing: Record; + Lay: Record; + Look: Record; + Mind: Record; + Move: Record; + Patrol: Record; + Scattering: Record; + Shoot: Record; } -export interface Experience -{ - aggressorBonus: number - level: MinMax - reward: MinMax - standingForKill: number +export interface Experience { + aggressorBonus: number; + level: MinMax; + reward: MinMax; + standingForKill: number; } -export interface Generation -{ - items: GenerationWeightingItems +export interface Generation { + items: GenerationWeightingItems; } -export interface GenerationWeightingItems -{ - grenades: GenerationData - healing: GenerationData - drugs: GenerationData - food: GenerationData - drink: GenerationData - currency: GenerationData - stims: GenerationData - backpackLoot: GenerationData - pocketLoot: GenerationData - vestLoot: GenerationData - magazines: GenerationData - specialItems: GenerationData +export interface GenerationWeightingItems { + grenades: GenerationData; + healing: GenerationData; + drugs: GenerationData; + food: GenerationData; + drink: GenerationData; + currency: GenerationData; + stims: GenerationData; + backpackLoot: GenerationData; + pocketLoot: GenerationData; + vestLoot: GenerationData; + magazines: GenerationData; + specialItems: GenerationData; } -export interface GenerationData -{ +export interface GenerationData { /** key: number of items, value: weighting */ - weights: Record + weights: Record; /** Array of item tpls */ - whitelist: Record + whitelist: Record; } -export interface Health -{ - BodyParts: BodyPart[] - Energy: MinMax - Hydration: MinMax - Temperature: MinMax +export interface Health { + BodyParts: BodyPart[]; + Energy: MinMax; + Hydration: MinMax; + Temperature: MinMax; } -export interface BodyPart -{ - Chest: MinMax - Head: MinMax - LeftArm: MinMax - LeftLeg: MinMax - RightArm: MinMax - RightLeg: MinMax - Stomach: MinMax +export interface BodyPart { + Chest: MinMax; + Head: MinMax; + LeftArm: MinMax; + LeftLeg: MinMax; + RightArm: MinMax; + RightLeg: MinMax; + Stomach: MinMax; } -export interface Inventory -{ - equipment: Equipment - Ammo: Record> - items: Items - mods: Mods +export interface Inventory { + equipment: Equipment; + Ammo: Record>; + items: Items; + mods: Mods; } -export interface Equipment -{ - ArmBand: Record - ArmorVest: Record - Backpack: Record - Earpiece: Record - Eyewear: Record - FaceCover: Record - FirstPrimaryWeapon: Record - Headwear: Record - Holster: Record - Pockets: Record - Scabbard: Record - SecondPrimaryWeapon: Record - SecuredContainer: Record - TacticalVest: Record +export interface Equipment { + ArmBand: Record; + ArmorVest: Record; + Backpack: Record; + Earpiece: Record; + Eyewear: Record; + FaceCover: Record; + FirstPrimaryWeapon: Record; + Headwear: Record; + Holster: Record; + Pockets: Record; + Scabbard: Record; + SecondPrimaryWeapon: Record; + SecuredContainer: Record; + TacticalVest: Record; } -export interface Items -{ - Backpack: Record - Pockets: Record - SecuredContainer: Record - SpecialLoot: Record - TacticalVest: Record +export interface Items { + Backpack: Record; + Pockets: Record; + SecuredContainer: Record; + SpecialLoot: Record; + TacticalVest: Record; } export type Mods = Record>; diff --git a/project/src/models/eft/common/tables/ICustomizationItem.ts b/project/src/models/eft/common/tables/ICustomizationItem.ts index 1adda1fb..446d8800 100644 --- a/project/src/models/eft/common/tables/ICustomizationItem.ts +++ b/project/src/models/eft/common/tables/ICustomizationItem.ts @@ -1,35 +1,32 @@ import { Ixyz } from "@spt/models/eft/common/Ixyz"; -export interface ICustomizationItem -{ - _id: string - _name: string - _parent: string - _type: string - _props: Props - _proto: string +export interface ICustomizationItem { + _id: string; + _name: string; + _parent: string; + _type: string; + _props: Props; + _proto: string; } -export interface Props -{ - Name: string - ShortName: string - Description: string - Side: string[] - BodyPart: string - AvailableAsDefault?: boolean - Body: string - Hands: string - Feet: string - Prefab: Prefab - WatchPrefab: Prefab - IntegratedArmorVest: boolean - WatchPosition: Ixyz - WatchRotation: Ixyz +export interface Props { + Name: string; + ShortName: string; + Description: string; + Side: string[]; + BodyPart: string; + AvailableAsDefault?: boolean; + Body: string; + Hands: string; + Feet: string; + Prefab: Prefab; + WatchPrefab: Prefab; + IntegratedArmorVest: boolean; + WatchPosition: Ixyz; + WatchRotation: Ixyz; } -export interface Prefab -{ - path: string - rcid: string +export interface Prefab { + path: string; + rcid: string; } diff --git a/project/src/models/eft/common/tables/IHandbookBase.ts b/project/src/models/eft/common/tables/IHandbookBase.ts index 3fa61d42..d1b20fd8 100644 --- a/project/src/models/eft/common/tables/IHandbookBase.ts +++ b/project/src/models/eft/common/tables/IHandbookBase.ts @@ -1,21 +1,18 @@ -export interface IHandbookBase -{ - Categories: Category[] - Items: HandbookItem[] +export interface IHandbookBase { + Categories: Category[]; + Items: HandbookItem[]; } -export interface Category -{ - Id: string - ParentId?: string - Icon: string - Color: string - Order: string +export interface Category { + Id: string; + ParentId?: string; + Icon: string; + Color: string; + Order: string; } -export interface HandbookItem -{ - Id: string - ParentId: string - Price: number +export interface HandbookItem { + Id: string; + ParentId: string; + Price: number; } diff --git a/project/src/models/eft/common/tables/IItem.ts b/project/src/models/eft/common/tables/IItem.ts index 395748b5..ef6d7578 100644 --- a/project/src/models/eft/common/tables/IItem.ts +++ b/project/src/models/eft/common/tables/IItem.ts @@ -1,170 +1,147 @@ -export interface Item -{ - _id: string - _tpl: string - parentId?: string - slotId?: string - location?: Location | number - upd?: Upd +export interface Item { + _id: string; + _tpl: string; + parentId?: string; + slotId?: string; + location?: Location | number; + upd?: Upd; } -export interface Upd -{ - Buff?: Buff - OriginalStackObjectsCount?: number - Togglable?: Togglable - Map?: Map - Tag?: Tag +export interface Upd { + Buff?: Buff; + OriginalStackObjectsCount?: number; + Togglable?: Togglable; + Map?: Map; + Tag?: Tag; /** SPT specific property, not made by BSG */ - sptPresetId?: string - FaceShield?: FaceShield - StackObjectsCount?: number - UnlimitedCount?: boolean - Repairable?: Repairable - RecodableComponent?: RecodableComponent - FireMode?: FireMode - SpawnedInSession?: boolean - Light?: Light - Key?: Key - Resource?: Resource - Sight?: Sight - MedKit?: MedKit - FoodDrink?: FoodDrink - Dogtag?: Dogtag - BuyRestrictionMax?: number - BuyRestrictionCurrent?: number - Foldable?: Foldable - SideEffect?: SideEffect - RepairKit?: RepairKit - CultistAmulet?: ICultistAmulet + sptPresetId?: string; + FaceShield?: FaceShield; + StackObjectsCount?: number; + UnlimitedCount?: boolean; + Repairable?: Repairable; + RecodableComponent?: RecodableComponent; + FireMode?: FireMode; + SpawnedInSession?: boolean; + Light?: Light; + Key?: Key; + Resource?: Resource; + Sight?: Sight; + MedKit?: MedKit; + FoodDrink?: FoodDrink; + Dogtag?: Dogtag; + BuyRestrictionMax?: number; + BuyRestrictionCurrent?: number; + Foldable?: Foldable; + SideEffect?: SideEffect; + RepairKit?: RepairKit; + CultistAmulet?: ICultistAmulet; } -export interface Buff -{ - rarity: string - buffType: string - value: number - thresholdDurability?: number +export interface Buff { + rarity: string; + buffType: string; + value: number; + thresholdDurability?: number; } -export interface Togglable -{ - On: boolean +export interface Togglable { + On: boolean; } -export interface Map -{ - Markers: MapMarker[] +export interface Map { + Markers: MapMarker[]; } -export interface MapMarker -{ - X: number - Y: number +export interface MapMarker { + X: number; + Y: number; } -export interface Tag -{ - Color: number - Name: string +export interface Tag { + Color: number; + Name: string; } -export interface FaceShield -{ - Hits: number +export interface FaceShield { + Hits: number; } -export interface Repairable -{ - Durability: number - MaxDurability: number +export interface Repairable { + Durability: number; + MaxDurability: number; } -export interface RecodableComponent -{ - IsEncoded: boolean +export interface RecodableComponent { + IsEncoded: boolean; } -export interface MedKit -{ - HpResource: number +export interface MedKit { + HpResource: number; } -export interface Sight -{ - ScopesCurrentCalibPointIndexes: number[] - ScopesSelectedModes: number[] - SelectedScope: number +export interface Sight { + ScopesCurrentCalibPointIndexes: number[]; + ScopesSelectedModes: number[]; + SelectedScope: number; } -export interface Foldable -{ - Folded: boolean +export interface Foldable { + Folded: boolean; } -export interface FireMode -{ - FireMode: string +export interface FireMode { + FireMode: string; } -export interface FoodDrink -{ - HpPercent: number +export interface FoodDrink { + HpPercent: number; } -export interface Key -{ - NumberOfUsages: number +export interface Key { + NumberOfUsages: number; } -export interface Resource -{ - Value: number - UnitsConsumed: number +export interface Resource { + Value: number; + UnitsConsumed: number; } -export interface Light -{ - IsActive: boolean - SelectedMode: number +export interface Light { + IsActive: boolean; + SelectedMode: number; } -export interface Dogtag -{ - AccountId: string - ProfileId: string - Nickname: string - Side: string - Level: number - Time: string - Status: string - KillerAccountId: string - KillerProfileId: string - KillerName: string - WeaponName: string +export interface Dogtag { + AccountId: string; + ProfileId: string; + Nickname: string; + Side: string; + Level: number; + Time: string; + Status: string; + KillerAccountId: string; + KillerProfileId: string; + KillerName: string; + WeaponName: string; } -export interface Location -{ - x: number - y: number - r: string | number - isSearched?: boolean +export interface Location { + x: number; + y: number; + r: string | number; + isSearched?: boolean; /** SPT property? */ - rotation?: string | boolean + rotation?: string | boolean; } -export interface SideEffect -{ - Value: number +export interface SideEffect { + Value: number; } -export interface RepairKit -{ - Resource: number +export interface RepairKit { + Resource: number; } -export interface ICultistAmulet -{ - NumberOfUsages: number +export interface ICultistAmulet { + NumberOfUsages: number; } diff --git a/project/src/models/eft/common/tables/ILocationServices.ts b/project/src/models/eft/common/tables/ILocationServices.ts index 3cb8438b..0e0d48d4 100644 --- a/project/src/models/eft/common/tables/ILocationServices.ts +++ b/project/src/models/eft/common/tables/ILocationServices.ts @@ -1,90 +1,80 @@ import { Ixyz } from "@spt/models/eft/common/Ixyz"; -export interface ILocationServices -{ - TraderServerSettings: ITraderServerSettings - BTRServerSettings: IBtrServerSettings +export interface ILocationServices { + TraderServerSettings: ITraderServerSettings; + BTRServerSettings: IBtrServerSettings; } -export interface ITraderServerSettings -{ - TraderServices: TraderServices +export interface ITraderServerSettings { + TraderServices: TraderServices; } -export interface TraderServices -{ - ExUsecLoyalty: ITraderService - ZryachiyAid: ITraderService - CultistsAid: ITraderService - PlayerTaxi: ITraderService - BtrItemsDelivery: ITraderService - BtrBotCover: ITraderService +export interface TraderServices { + ExUsecLoyalty: ITraderService; + ZryachiyAid: ITraderService; + CultistsAid: ITraderService; + PlayerTaxi: ITraderService; + BtrItemsDelivery: ITraderService; + BtrBotCover: ITraderService; } -export interface ITraderService -{ - TraderId: string - TraderServiceType: string - Requirements: IServiceRequirements - ServiceItemCost: Record - UniqueItems: string[] +export interface ITraderService { + TraderId: string; + TraderServiceType: string; + Requirements: IServiceRequirements; + ServiceItemCost: Record; + UniqueItems: string[]; } -export interface IServiceRequirements -{ - CompletedQuests: ICompletedQuest[] - Standings: Record +export interface IServiceRequirements { + CompletedQuests: ICompletedQuest[]; + Standings: Record; } -export interface ICompletedQuest -{ - QuestId: string +export interface ICompletedQuest { + QuestId: string; } -export interface IStandingRequirement -{ - Value: number +export interface IStandingRequirement { + Value: number; } -export interface IServiceItemCostDetails -{ - Count: number +export interface IServiceItemCostDetails { + Count: number; } -export interface IBtrServerSettings -{ - ChanceSpawn: number - SpawnPeriod: Ixyz - MoveSpeed: number - ReadyToDepartureTime: number - CheckTurnDistanceTime: number - TurnCheckSensitivity: number - DecreaseSpeedOnTurnLimit: number - EndSplineDecelerationDistance: number - AccelerationSpeed: number - DecelerationSpeed: number - PauseDurationRange: Ixyz - BodySwingReturnSpeed: number - BodySwingDamping: number - BodySwingIntensity: number - ServerMapBTRSettings: Record +export interface IBtrServerSettings { + ChanceSpawn: number; + SpawnPeriod: Ixyz; + MoveSpeed: number; + ReadyToDepartureTime: number; + CheckTurnDistanceTime: number; + TurnCheckSensitivity: number; + DecreaseSpeedOnTurnLimit: number; + EndSplineDecelerationDistance: number; + AccelerationSpeed: number; + DecelerationSpeed: number; + PauseDurationRange: Ixyz; + BodySwingReturnSpeed: number; + BodySwingDamping: number; + BodySwingIntensity: number; + ServerMapBTRSettings: Record; } -export interface IServerMapBtrsettings -{ - MapID: string - ChanceSpawn: number - SpawnPeriod: Ixyz - MoveSpeed: number - ReadyToDepartureTime: number - CheckTurnDistanceTime: number - TurnCheckSensitivity: number - DecreaseSpeedOnTurnLimit: number - EndSplineDecelerationDistance: number - AccelerationSpeed: number - DecelerationSpeed: number - PauseDurationRange: Ixyz - BodySwingReturnSpeed: number - BodySwingDamping: number - BodySwingIntensity: number +export interface IServerMapBtrsettings { + MapID: string; + ChanceSpawn: number; + SpawnPeriod: Ixyz; + MoveSpeed: number; + ReadyToDepartureTime: number; + CheckTurnDistanceTime: number; + TurnCheckSensitivity: number; + DecreaseSpeedOnTurnLimit: number; + EndSplineDecelerationDistance: number; + AccelerationSpeed: number; + DecelerationSpeed: number; + PauseDurationRange: Ixyz; + BodySwingReturnSpeed: number; + BodySwingDamping: number; + BodySwingIntensity: number; } diff --git a/project/src/models/eft/common/tables/ILocationsBase.ts b/project/src/models/eft/common/tables/ILocationsBase.ts index 7cd95a3b..5e62c99e 100644 --- a/project/src/models/eft/common/tables/ILocationsBase.ts +++ b/project/src/models/eft/common/tables/ILocationsBase.ts @@ -1,14 +1,11 @@ -export interface ILocationsBase -{ - locations: Locations - paths: Path[] +export interface ILocationsBase { + locations: Locations; + paths: Path[]; } -export interface Locations -{} +export type Locations = {}; -export interface Path -{ - Source: string - Destination: string +export interface Path { + Source: string; + Destination: string; } diff --git a/project/src/models/eft/common/tables/IMatch.ts b/project/src/models/eft/common/tables/IMatch.ts index 9521a23e..cc8719ee 100644 --- a/project/src/models/eft/common/tables/IMatch.ts +++ b/project/src/models/eft/common/tables/IMatch.ts @@ -1,14 +1,12 @@ -export interface IMatch -{ - metrics: Metrics +export interface IMatch { + metrics: Metrics; } -export interface Metrics -{ - Keys: number[] - NetProcessingBins: number[] - RenderBins: number[] - GameUpdateBins: number[] - MemoryMeasureInterval: number - PauseReasons: number[] +export interface Metrics { + Keys: number[]; + NetProcessingBins: number[]; + RenderBins: number[]; + GameUpdateBins: number[]; + MemoryMeasureInterval: number; + PauseReasons: number[]; } diff --git a/project/src/models/eft/common/tables/IProfileTemplate.ts b/project/src/models/eft/common/tables/IProfileTemplate.ts index e0b13774..23feb25c 100644 --- a/project/src/models/eft/common/tables/IProfileTemplate.ts +++ b/project/src/models/eft/common/tables/IProfileTemplate.ts @@ -1,47 +1,43 @@ import { IPmcData } from "@spt/models/eft/common/IPmcData"; import { Dialogue, IUserBuilds } from "@spt/models/eft/profile/ISptProfile"; -export interface IProfileTemplates -{ - "Standard": IProfileSides - "Left Behind": IProfileSides - "Prepare To Escape": IProfileSides - "Edge Of Darkness": IProfileSides - "Unheard": IProfileSides - "Tournament": IProfileSides - "SPT Developer": IProfileSides - "SPT Easy start": IProfileSides - "SPT Zero to hero": IProfileSides +export interface IProfileTemplates { + Standard: IProfileSides; + "Left Behind": IProfileSides; + "Prepare To Escape": IProfileSides; + "Edge Of Darkness": IProfileSides; + Unheard: IProfileSides; + Tournament: IProfileSides; + "SPT Developer": IProfileSides; + "SPT Easy start": IProfileSides; + "SPT Zero to hero": IProfileSides; } -export interface IProfileSides -{ - descriptionLocaleKey: string - usec: ITemplateSide - bear: ITemplateSide +export interface IProfileSides { + descriptionLocaleKey: string; + usec: ITemplateSide; + bear: ITemplateSide; } -export interface ITemplateSide -{ - character: IPmcData - suits: string[] - dialogues: Record - userbuilds: IUserBuilds - trader: ProfileTraderTemplate +export interface ITemplateSide { + character: IPmcData; + suits: string[]; + dialogues: Record; + userbuilds: IUserBuilds; + trader: ProfileTraderTemplate; } -export interface ProfileTraderTemplate -{ - initialLoyaltyLevel: Record - initialStanding: Record - setQuestsAvailableForStart?: boolean - setQuestsAvailableForFinish?: boolean - initialSalesSum: number - jaegerUnlocked: boolean +export interface ProfileTraderTemplate { + initialLoyaltyLevel: Record; + initialStanding: Record; + setQuestsAvailableForStart?: boolean; + setQuestsAvailableForFinish?: boolean; + initialSalesSum: number; + jaegerUnlocked: boolean; /** How many days is usage of the flea blocked for upon profile creation */ - fleaBlockedDays?: number + fleaBlockedDays?: number; /** What traders default to being locked on profile creation */ - lockedByDefaultOverride?: string[] + lockedByDefaultOverride?: string[]; /** What traders should have their clothing unlocked/purchased on creation */ - purchaseAllClothingByDefaultForTrader?: string[] + purchaseAllClothingByDefaultForTrader?: string[]; } diff --git a/project/src/models/eft/common/tables/IQuest.ts b/project/src/models/eft/common/tables/IQuest.ts index dcaff424..d349f6e7 100644 --- a/project/src/models/eft/common/tables/IQuest.ts +++ b/project/src/models/eft/common/tables/IQuest.ts @@ -3,174 +3,162 @@ import { QuestRewardType } from "@spt/models/enums/QuestRewardType"; import { QuestStatus } from "@spt/models/enums/QuestStatus"; import { QuestTypeEnum } from "@spt/models/enums/QuestTypeEnum"; -export interface IQuest -{ +export interface IQuest { /** SPT addition - human readable quest name */ - QuestName?: string - _id: string - canShowNotificationsInGame: boolean - conditions: IQuestConditionTypes - description: string - failMessageText: string - name: string - note: string - traderId: string - location: string - image: string - type: QuestTypeEnum - isKey: boolean + QuestName?: string; + _id: string; + canShowNotificationsInGame: boolean; + conditions: IQuestConditionTypes; + description: string; + failMessageText: string; + name: string; + note: string; + traderId: string; + location: string; + image: string; + type: QuestTypeEnum; + isKey: boolean; /** @deprecated - Likely not used, use 'status' instead */ - questStatus: QuestStatus - restartable: boolean - instantComplete: boolean - secretQuest: boolean - startedMessageText: string - successMessageText: string - acceptPlayerMessage: string - declinePlayerMessage: string - completePlayerMessage: string - templateId: string - rewards: IQuestRewards + questStatus: QuestStatus; + restartable: boolean; + instantComplete: boolean; + secretQuest: boolean; + startedMessageText: string; + successMessageText: string; + acceptPlayerMessage: string; + declinePlayerMessage: string; + completePlayerMessage: string; + templateId: string; + rewards: IQuestRewards; /** Becomes 'AppearStatus' inside client */ - status: string | number - KeyQuest: boolean - changeQuestMessageText: string + status: string | number; + KeyQuest: boolean; + changeQuestMessageText: string; /** "Pmc" or "Scav" */ - side: string + side: string; /** Status of quest to player */ - sptStatus?: QuestStatus + sptStatus?: QuestStatus; } -export interface IQuestConditionTypes -{ - Started: IQuestCondition[] - AvailableForFinish: IQuestCondition[] - AvailableForStart: IQuestCondition[] - Success: IQuestCondition[] - Fail: IQuestCondition[] +export interface IQuestConditionTypes { + Started: IQuestCondition[]; + AvailableForFinish: IQuestCondition[]; + AvailableForStart: IQuestCondition[]; + Success: IQuestCondition[]; + Fail: IQuestCondition[]; } -export interface IQuestCondition -{ - id: string - index?: number - compareMethod?: string - dynamicLocale: boolean - visibilityConditions?: VisibilityCondition[] - globalQuestCounterId?: string - parentId?: string - target: string[] | string - value?: string | number - type?: boolean - status?: QuestStatus[] - availableAfter?: number - dispersion?: number - onlyFoundInRaid?: boolean - oneSessionOnly?: boolean - doNotResetIfCounterCompleted?: boolean - dogtagLevel?: number - maxDurability?: number - minDurability?: number - counter?: IQuestConditionCounter - plantTime?: number - zoneId?: string - countInRaid?: boolean - completeInSeconds?: number - isEncoded?: boolean - conditionType?: string +export interface IQuestCondition { + id: string; + index?: number; + compareMethod?: string; + dynamicLocale: boolean; + visibilityConditions?: VisibilityCondition[]; + globalQuestCounterId?: string; + parentId?: string; + target: string[] | string; + value?: string | number; + type?: boolean; + status?: QuestStatus[]; + availableAfter?: number; + dispersion?: number; + onlyFoundInRaid?: boolean; + oneSessionOnly?: boolean; + doNotResetIfCounterCompleted?: boolean; + dogtagLevel?: number; + maxDurability?: number; + minDurability?: number; + counter?: IQuestConditionCounter; + plantTime?: number; + zoneId?: string; + countInRaid?: boolean; + completeInSeconds?: number; + isEncoded?: boolean; + conditionType?: string; } -export interface IQuestConditionCounter -{ - id: string - conditions: IQuestConditionCounterCondition[] +export interface IQuestConditionCounter { + id: string; + conditions: IQuestConditionCounterCondition[]; } -export interface IQuestConditionCounterCondition -{ - id: string - dynamicLocale: boolean - target?: string[] | string // TODO: some objects have an array and some are just strings, thanks bsg very cool - completeInSeconds?: number - energy?: IValueCompare - exitName?: string - hydration?: IValueCompare - time?: IValueCompare - compareMethod?: string - value?: number - weapon?: string[] - distance?: ICounterConditionDistance - equipmentInclusive?: string[][] - weaponModsInclusive?: string[][] - weaponModsExclusive?: string[][] - enemyEquipmentInclusive?: string[][] - enemyEquipmentExclusive?: string[][] - weaponCaliber?: string[] - savageRole?: string[] - status?: string[] - bodyPart?: string[] - daytime?: IDaytimeCounter - conditionType?: string - enemyHealthEffects?: IEnemyHealthEffect[] - resetOnSessionEnd?: boolean +export interface IQuestConditionCounterCondition { + id: string; + dynamicLocale: boolean; + target?: string[] | string; // TODO: some objects have an array and some are just strings, thanks bsg very cool + completeInSeconds?: number; + energy?: IValueCompare; + exitName?: string; + hydration?: IValueCompare; + time?: IValueCompare; + compareMethod?: string; + value?: number; + weapon?: string[]; + distance?: ICounterConditionDistance; + equipmentInclusive?: string[][]; + weaponModsInclusive?: string[][]; + weaponModsExclusive?: string[][]; + enemyEquipmentInclusive?: string[][]; + enemyEquipmentExclusive?: string[][]; + weaponCaliber?: string[]; + savageRole?: string[]; + status?: string[]; + bodyPart?: string[]; + daytime?: IDaytimeCounter; + conditionType?: string; + enemyHealthEffects?: IEnemyHealthEffect[]; + resetOnSessionEnd?: boolean; } -export interface IEnemyHealthEffect -{ - bodyParts: string[] - effects: string[] +export interface IEnemyHealthEffect { + bodyParts: string[]; + effects: string[]; } -export interface IValueCompare -{ - compareMethod: string - value: number +export interface IValueCompare { + compareMethod: string; + value: number; } -export interface ICounterConditionDistance -{ - value: number - compareMethod: string +export interface ICounterConditionDistance { + value: number; + compareMethod: string; } -export interface IDaytimeCounter -{ - from: number - to: number +export interface IDaytimeCounter { + from: number; + to: number; } -export interface VisibilityCondition -{ - id: string - target: string - value?: number - dynamicLocale?: boolean - oneSessionOnly: boolean - conditionType: string +export interface VisibilityCondition { + id: string; + target: string; + value?: number; + dynamicLocale?: boolean; + oneSessionOnly: boolean; + conditionType: string; } -export interface IQuestRewards -{ - AvailableForStart?: IQuestReward[] - AvailableForFinish?: IQuestReward[] - Started?: IQuestReward[] - Success?: IQuestReward[] - Fail?: IQuestReward[] - FailRestartable?: IQuestReward[] - Expired?: IQuestReward[] +export interface IQuestRewards { + AvailableForStart?: IQuestReward[]; + AvailableForFinish?: IQuestReward[]; + Started?: IQuestReward[]; + Success?: IQuestReward[]; + Fail?: IQuestReward[]; + FailRestartable?: IQuestReward[]; + Expired?: IQuestReward[]; } -export interface IQuestReward -{ - value?: string | number - id?: string - type: QuestRewardType - index: number - target?: string - items?: Item[] - loyaltyLevel?: number +export interface IQuestReward { + value?: string | number; + id?: string; + type: QuestRewardType; + index: number; + target?: string; + items?: Item[]; + loyaltyLevel?: number; /** Hideout area id */ - traderId?: string - unknown?: boolean - findInRaid?: boolean + traderId?: string; + unknown?: boolean; + findInRaid?: boolean; } diff --git a/project/src/models/eft/common/tables/IRepeatableQuests.ts b/project/src/models/eft/common/tables/IRepeatableQuests.ts index 8c694339..666011a1 100644 --- a/project/src/models/eft/common/tables/IRepeatableQuests.ts +++ b/project/src/models/eft/common/tables/IRepeatableQuests.ts @@ -1,101 +1,89 @@ import { IQuest, IQuestConditionTypes, IQuestRewards } from "@spt/models/eft/common/tables/IQuest"; -export interface IRepeatableQuest extends IQuest -{ - changeCost: IChangeCost[] - changeStandingCost: number - sptRepatableGroupName: string +export interface IRepeatableQuest extends IQuest { + changeCost: IChangeCost[]; + changeStandingCost: number; + sptRepatableGroupName: string; } -export interface IRepeatableQuestDatabase -{ - templates: IRepeatableTemplates - rewards: IRewardOptions - data: IOptions - samples: ISampleQuests[] +export interface IRepeatableQuestDatabase { + templates: IRepeatableTemplates; + rewards: IRewardOptions; + data: IOptions; + samples: ISampleQuests[]; } -export interface IRepeatableTemplates -{ - Elimination: IQuest - Completion: IQuest - Exploration: IQuest +export interface IRepeatableTemplates { + Elimination: IQuest; + Completion: IQuest; + Exploration: IQuest; } -export interface IPmcDataRepeatableQuest -{ - id?: string - name: string - unavailableTime?: string - activeQuests: IRepeatableQuest[] - inactiveQuests: IRepeatableQuest[] - endTime: number - changeRequirement: Record // What it costs to reset redundant to change requirements within IRepeatableQuest - freeChanges: number - freeChangesAvailable: number +export interface IPmcDataRepeatableQuest { + id?: string; + name: string; + unavailableTime?: string; + activeQuests: IRepeatableQuest[]; + inactiveQuests: IRepeatableQuest[]; + endTime: number; + changeRequirement: Record; // What it costs to reset redundant to change requirements within IRepeatableQuest + freeChanges: number; + freeChangesAvailable: number; } -export interface IChangeRequirement -{ - changeCost: IChangeCost[] - changeStandingCost: number +export interface IChangeRequirement { + changeCost: IChangeCost[]; + changeStandingCost: number; } -export interface IChangeCost -{ - templateId: string // what item it will take to reset daily - count: number // amount of item needed to reset +export interface IChangeCost { + templateId: string; // what item it will take to reset daily + count: number; // amount of item needed to reset } // Config Options -export interface IRewardOptions -{ - itemsBlacklist: string[] +export interface IRewardOptions { + itemsBlacklist: string[]; } -export interface IOptions -{ - Completion: ICompletionFilter +export interface IOptions { + Completion: ICompletionFilter; } -export interface ICompletionFilter -{ - itemsBlacklist: ItemsBlacklist[] - itemsWhitelist: ItemsWhitelist[] +export interface ICompletionFilter { + itemsBlacklist: ItemsBlacklist[]; + itemsWhitelist: ItemsWhitelist[]; } -export interface ItemsBlacklist -{ - minPlayerLevel: number - itemIds: string[] +export interface ItemsBlacklist { + minPlayerLevel: number; + itemIds: string[]; } -export interface ItemsWhitelist -{ - minPlayerLevel: number - itemIds: string[] +export interface ItemsWhitelist { + minPlayerLevel: number; + itemIds: string[]; } -export interface ISampleQuests -{ - _id: string - traderId: string - location: string - image: string - type: string - isKey: boolean - restartable: boolean - instantComplete: boolean - secretQuest: boolean - canShowNotificationsInGame: boolean - rewards: IQuestRewards - conditions: IQuestConditionTypes - name: string - note: string - description: string - successMessageText: string - failMessageText: string - startedMessageText: string - templateId: string +export interface ISampleQuests { + _id: string; + traderId: string; + location: string; + image: string; + type: string; + isKey: boolean; + restartable: boolean; + instantComplete: boolean; + secretQuest: boolean; + canShowNotificationsInGame: boolean; + rewards: IQuestRewards; + conditions: IQuestConditionTypes; + name: string; + note: string; + description: string; + successMessageText: string; + failMessageText: string; + startedMessageText: string; + templateId: string; } diff --git a/project/src/models/eft/common/tables/ITemplateItem.ts b/project/src/models/eft/common/tables/ITemplateItem.ts index 283f3ebc..ea3d0165 100644 --- a/project/src/models/eft/common/tables/ITemplateItem.ts +++ b/project/src/models/eft/common/tables/ITemplateItem.ts @@ -1,585 +1,564 @@ import { Ixyz } from "@spt/models/eft/common/Ixyz"; -export interface ITemplateItem -{ - _id: string - _name: string - _parent: string - _type: ItemType - _props: Props - _proto?: string +export interface ITemplateItem { + _id: string; + _name: string; + _parent: string; + _type: ItemType; + _props: Props; + _proto?: string; } -export interface Props -{ - AllowSpawnOnLocations?: any[] - BeltMagazineRefreshCount?: number - ChangePriceCoef?: number - FixedPrice?: boolean - SendToClient?: boolean - Name?: string - ShortName?: string - Description?: string - Weight?: number - BackgroundColor?: string - Width?: number - Height?: number - StackMaxSize?: number - Rarity?: string - SpawnChance?: number - CreditsPrice?: number - ItemSound?: string - Prefab?: Prefab - UsePrefab?: Prefab - StackObjectsCount?: number - NotShownInSlot?: boolean - ExaminedByDefault?: boolean - ExamineTime?: number - IsUndiscardable?: boolean - IsUnsaleable?: boolean - IsUnbuyable?: boolean - IsUngivable?: boolean - IsUnremovable?: boolean - IsLockedafterEquip?: boolean - IsRagfairCurrency?: boolean - IsSpecialSlotOnly?: boolean - IsStationaryWeapon?: boolean - QuestItem?: boolean - QuestStashMaxCount?: number - LootExperience?: number - ExamineExperience?: number - HideEntrails?: boolean - InsuranceDisabled?: boolean - RepairCost?: number - RepairSpeed?: number - ExtraSizeLeft?: number - ExtraSizeRight?: number - ExtraSizeUp?: number - ExtraSizeDown?: number - ExtraSizeForceAdd?: boolean - MergesWithChildren?: boolean - CanSellOnRagfair?: boolean - CanRequireOnRagfair?: boolean - ConflictingItems?: string[] - Unlootable?: boolean - UnlootableFromSlot?: string - UnlootableFromSide?: string[] - AnimationVariantsNumber?: number - DiscardingBlock?: boolean - DropSoundType?: string - RagFairCommissionModifier?: number - RarityPvE?: string - IsAlwaysAvailableForInsurance?: boolean - DiscardLimit?: number - MaxResource?: number - Resource?: number - DogTagQualities?: boolean - Grids?: Grid[] - Slots?: Slot[] - CanPutIntoDuringTheRaid?: boolean - CantRemoveFromSlotsDuringRaid?: string[] - KeyIds?: string[] - TagColor?: number - TagName?: string - Durability?: number - Accuracy?: number - Recoil?: number - Loudness?: number - EffectiveDistance?: number - Ergonomics?: number - Velocity?: number - WithAnimatorAiming?: boolean - RaidModdable?: boolean - ToolModdable?: boolean - UniqueAnimationModID?: number - BlocksFolding?: boolean - BlocksCollapsible?: boolean - IsAnimated?: boolean - HasShoulderContact?: boolean - SightingRange?: number - DoubleActionAccuracyPenaltyMult?: number - ModesCount?: any - DurabilityBurnModificator?: number - HeatFactor?: number - CoolFactor?: number - muzzleModType?: string - CustomAimPlane?: string - sightModType?: string - aimingSensitivity?: number - SightModesCount?: number - OpticCalibrationDistances?: number[] - ScopesCount?: number - AimSensitivity?: number | number[][] - Zooms?: number[][] - CalibrationDistances?: number[][] - Intensity?: number - Mask?: string - MaskSize?: number - IsMagazineForStationaryWeapon?: boolean - NoiseIntensity?: number - NoiseScale?: number - Color?: IColor - DiffuseIntensity?: number - MagazineWithBelt?: boolean - HasHinge?: boolean - RampPalette?: string - DepthFade?: number - RoughnessCoef?: number - SpecularCoef?: number - MainTexColorCoef?: number - MinimumTemperatureValue?: number - RampShift?: number - HeatMin?: number - ColdMax?: number - IsNoisy?: boolean - IsFpsStuck?: boolean - IsGlitch?: boolean - IsMotionBlurred?: boolean - IsPixelated?: boolean - PixelationBlockCount?: number - ShiftsAimCamera?: number - magAnimationIndex?: number - Cartridges?: Slot[] - CanFast?: boolean - CanHit?: boolean - CanAdmin?: boolean - LoadUnloadModifier?: number - CheckTimeModifier?: number - CheckOverride?: number - ReloadMagType?: string - VisibleAmmoRangesString?: string - MalfunctionChance?: number - IsShoulderContact?: boolean - Foldable?: boolean - Retractable?: boolean - SizeReduceRight?: number - CenterOfImpact?: number - ShotgunDispersion?: number - IsSilencer?: boolean - DeviationCurve?: number - DeviationMax?: number - SearchSound?: string - BlocksArmorVest?: boolean - speedPenaltyPercent?: number - GridLayoutName?: string - ContainerSpawnChanceModifier?: number - SpawnExcludedFilter?: string[] - SpawnFilter?: any[] - containType?: any[] - sizeWidth?: number - sizeHeight?: number - isSecured?: boolean - spawnTypes?: string - lootFilter?: any[] - spawnRarity?: string - minCountSpawn?: number - maxCountSpawn?: number - openedByKeyID?: any[] - RigLayoutName?: string - MaxDurability?: number - armorZone?: string[] - armorClass?: string | number - armorColliders?: string[] - armorPlateColliders?: string[] - bluntDamageReduceFromSoftArmor?: boolean - mousePenalty?: number - weaponErgonomicPenalty?: number - BluntThroughput?: number - ArmorMaterial?: string - ArmorType?: string - weapClass?: string - weapUseType?: string - ammoCaliber?: string - OperatingResource?: number - PostRecoilHorizontalRangeHandRotation?: Ixyz - PostRecoilVerticalRangeHandRotation?: Ixyz - ProgressRecoilAngleOnStable?: Ixyz - RepairComplexity?: number - durabSpawnMin?: number - durabSpawnMax?: number - isFastReload?: boolean - RecoilForceUp?: number - RecoilForceBack?: number - RecoilAngle?: number - RecoilCamera?: number - weapFireType?: string[] - RecolDispersion?: number - SingleFireRate?: number - CanQueueSecondShot?: boolean - bFirerate?: number - bEffDist?: number - bHearDist?: number - blockLeftStance?: boolean - isChamberLoad?: boolean - chamberAmmoCount?: number - isBoltCatch?: boolean - defMagType?: string - defAmmo?: string - AdjustCollimatorsToTrajectory?: boolean - shotgunDispersion?: number - Chambers?: Slot[] - CameraSnap?: number - CameraToWeaponAngleSpeedRange?: Ixyz - CameraToWeaponAngleStep?: number - ReloadMode?: string - AimPlane?: number - TacticalReloadStiffnes?: Ixyz - TacticalReloadFixation?: number - RecoilCenter?: Ixyz - RotationCenter?: Ixyz - RotationCenterNoStock?: Ixyz - ShotsGroupSettings?: IShotsGroupSettings[] - FoldedSlot?: string - CompactHandling?: boolean - MinRepairDegradation?: number - MaxRepairDegradation?: number - IronSightRange?: number - IsBeltMachineGun?: boolean - IsFlareGun?: boolean - IsGrenadeLauncher?: boolean - IsOneoff?: boolean - MustBoltBeOpennedForExternalReload?: boolean - MustBoltBeOpennedForInternalReload?: boolean - NoFiremodeOnBoltcatch?: boolean - BoltAction?: boolean - HipAccuracyRestorationDelay?: number - HipAccuracyRestorationSpeed?: number - HipInnaccuracyGain?: number - ManualBoltCatch?: boolean - BurstShotsCount?: number - BaseMalfunctionChance?: number - AllowJam?: boolean - AllowFeed?: boolean - AllowMisfire?: boolean - AllowSlide?: boolean - DurabilityBurnRatio?: number - HeatFactorGun?: number - CoolFactorGun?: number - CoolFactorGunMods?: number - HeatFactorByShot?: number - AllowOverheat?: boolean - DoubleActionAccuracyPenalty?: number - RecoilPosZMult?: number - RecoilReturnPathDampingHandRotation?: number - RecoilReturnPathOffsetHandRotation?: number - RecoilReturnSpeedHandRotation?: number - RecoilStableAngleIncreaseStep?: number - RecoilStableIndexShot?: number - MinRepairKitDegradation?: number - MaxRepairKitDegradation?: number - BlocksEarpiece?: boolean - BlocksEyewear?: boolean - BlocksHeadwear?: boolean - BlocksFaceCover?: boolean - Indestructibility?: number - headSegments?: string[] - FaceShieldComponent?: boolean - FaceShieldMask?: string - MaterialType?: string - RicochetParams?: Ixyz - DeafStrength?: string - BlindnessProtection?: number - Distortion?: number - CompressorTreshold?: number - CompressorAttack?: number - CompressorRelease?: number - CompressorGain?: number - CutoffFreq?: number - Resonance?: number - RolloffMultiplier?: number - ReverbVolume?: number - CompressorVolume?: number - AmbientVolume?: number - DryVolume?: number - HighFrequenciesGain?: number - foodUseTime?: number - foodEffectType?: string - StimulatorBuffs?: string - effects_health?: IHealthEffect[] | Record> - effects_damage?: Record - MaximumNumberOfUsage?: number - knifeHitDelay?: number - knifeHitSlashRate?: number - knifeHitStabRate?: number - knifeHitRadius?: number - knifeHitSlashDam?: number - knifeHitStabDam?: number - knifeDurab?: number - PrimaryDistance?: number - SecondryDistance?: number - SlashPenetration?: number - StabPenetration?: number - PrimaryConsumption?: number - SecondryConsumption?: number - DeflectionConsumption?: number - AppliedTrunkRotation?: Ixyz - AppliedHeadRotation?: Ixyz - DisplayOnModel?: boolean - AdditionalAnimationLayer?: number - StaminaBurnRate?: number - ColliderScaleMultiplier?: Ixyz - ConfigPathStr?: string - MaxMarkersCount?: number - scaleMin?: number - scaleMax?: number - medUseTime?: number - medEffectType?: string - MaxHpResource?: number - hpResourceRate?: number - apResource?: number - krResource?: number - MaxOpticZoom?: number - MaxRepairResource?: number - TargetItemFilter?: string[] - RepairQuality?: number - RepairType?: string - StackMinRandom?: number - StackMaxRandom?: number - ammoType?: string - InitialSpeed?: number - BallisticCoeficient?: number - BulletMassGram?: number - BulletDiameterMilimeters?: number - Damage?: number - ammoAccr?: number - ammoRec?: number - ammoDist?: number - buckshotBullets?: number - PenetrationPower?: number - PenetrationPowerDiviation?: number - ammoHear?: number - ammoSfx?: string - MisfireChance?: number - MinFragmentsCount?: number - MaxFragmentsCount?: number - ammoShiftChance?: number - casingName?: string - casingEjectPower?: number - casingMass?: number - casingSounds?: string - ProjectileCount?: number - PenetrationChanceObstacle?: number - PenetrationDamageMod?: number - RicochetChance?: number - FragmentationChance?: number - Deterioration?: number - SpeedRetardation?: number - Tracer?: boolean - TracerColor?: string - TracerDistance?: number - ArmorDamage?: number - Caliber?: string - StaminaBurnPerDamage?: number - HeavyBleedingDelta?: number - LightBleedingDelta?: number - ShowBullet?: boolean - HasGrenaderComponent?: boolean - FuzeArmTimeSec?: number - ExplosionStrength?: number - MinExplosionDistance?: number - MaxExplosionDistance?: number - FragmentsCount?: number - FragmentType?: string - ShowHitEffectOnExplode?: boolean - ExplosionType?: string - AmmoLifeTimeSec?: number - Contusion?: Ixyz - ArmorDistanceDistanceDamage?: Ixyz - Blindness?: Ixyz - IsLightAndSoundShot?: boolean - LightAndSoundShotAngle?: number - LightAndSoundShotSelfContusionTime?: number - LightAndSoundShotSelfContusionStrength?: number - MalfMisfireChance?: number - MalfFeedChance?: number - StackSlots?: StackSlot[] - type?: string - eqMin?: number - eqMax?: number - rate?: number - ThrowType?: string - ExplDelay?: number - Strength?: number - ContusionDistance?: number - throwDamMax?: number - explDelay?: number - EmitTime?: number - CanBeHiddenDuringThrow?: boolean - MinTimeToContactExplode?: number - ExplosionEffectType?: string - LinkedWeapon?: string - UseAmmoWithoutShell?: boolean - RandomLootSettings?: IRandomLootSettings - RecoilCategoryMultiplierHandRotation?: number - RecoilDampingHandRotation?: number - LeanWeaponAgainstBody?: boolean - RemoveShellAfterFire?: boolean - RepairStrategyTypes?: string[] - IsEncoded?: boolean - LayoutName?: string - Lower75Prefab?: Prefab - MaxUsages?: number - ScavKillExpPenalty?: number - ScavKillExpPenaltyPVE?: number - ScavKillStandingPenalty?: number - ScavKillStandingPenaltyPVE?: number - TradersDiscount?: number - TradersDiscountPVE?: number +export interface Props { + AllowSpawnOnLocations?: any[]; + BeltMagazineRefreshCount?: number; + ChangePriceCoef?: number; + FixedPrice?: boolean; + SendToClient?: boolean; + Name?: string; + ShortName?: string; + Description?: string; + Weight?: number; + BackgroundColor?: string; + Width?: number; + Height?: number; + StackMaxSize?: number; + Rarity?: string; + SpawnChance?: number; + CreditsPrice?: number; + ItemSound?: string; + Prefab?: Prefab; + UsePrefab?: Prefab; + StackObjectsCount?: number; + NotShownInSlot?: boolean; + ExaminedByDefault?: boolean; + ExamineTime?: number; + IsUndiscardable?: boolean; + IsUnsaleable?: boolean; + IsUnbuyable?: boolean; + IsUngivable?: boolean; + IsUnremovable?: boolean; + IsLockedafterEquip?: boolean; + IsRagfairCurrency?: boolean; + IsSpecialSlotOnly?: boolean; + IsStationaryWeapon?: boolean; + QuestItem?: boolean; + QuestStashMaxCount?: number; + LootExperience?: number; + ExamineExperience?: number; + HideEntrails?: boolean; + InsuranceDisabled?: boolean; + RepairCost?: number; + RepairSpeed?: number; + ExtraSizeLeft?: number; + ExtraSizeRight?: number; + ExtraSizeUp?: number; + ExtraSizeDown?: number; + ExtraSizeForceAdd?: boolean; + MergesWithChildren?: boolean; + CanSellOnRagfair?: boolean; + CanRequireOnRagfair?: boolean; + ConflictingItems?: string[]; + Unlootable?: boolean; + UnlootableFromSlot?: string; + UnlootableFromSide?: string[]; + AnimationVariantsNumber?: number; + DiscardingBlock?: boolean; + DropSoundType?: string; + RagFairCommissionModifier?: number; + RarityPvE?: string; + IsAlwaysAvailableForInsurance?: boolean; + DiscardLimit?: number; + MaxResource?: number; + Resource?: number; + DogTagQualities?: boolean; + Grids?: Grid[]; + Slots?: Slot[]; + CanPutIntoDuringTheRaid?: boolean; + CantRemoveFromSlotsDuringRaid?: string[]; + KeyIds?: string[]; + TagColor?: number; + TagName?: string; + Durability?: number; + Accuracy?: number; + Recoil?: number; + Loudness?: number; + EffectiveDistance?: number; + Ergonomics?: number; + Velocity?: number; + WithAnimatorAiming?: boolean; + RaidModdable?: boolean; + ToolModdable?: boolean; + UniqueAnimationModID?: number; + BlocksFolding?: boolean; + BlocksCollapsible?: boolean; + IsAnimated?: boolean; + HasShoulderContact?: boolean; + SightingRange?: number; + DoubleActionAccuracyPenaltyMult?: number; + ModesCount?: any; + DurabilityBurnModificator?: number; + HeatFactor?: number; + CoolFactor?: number; + muzzleModType?: string; + CustomAimPlane?: string; + sightModType?: string; + aimingSensitivity?: number; + SightModesCount?: number; + OpticCalibrationDistances?: number[]; + ScopesCount?: number; + AimSensitivity?: number | number[][]; + Zooms?: number[][]; + CalibrationDistances?: number[][]; + Intensity?: number; + Mask?: string; + MaskSize?: number; + IsMagazineForStationaryWeapon?: boolean; + NoiseIntensity?: number; + NoiseScale?: number; + Color?: IColor; + DiffuseIntensity?: number; + MagazineWithBelt?: boolean; + HasHinge?: boolean; + RampPalette?: string; + DepthFade?: number; + RoughnessCoef?: number; + SpecularCoef?: number; + MainTexColorCoef?: number; + MinimumTemperatureValue?: number; + RampShift?: number; + HeatMin?: number; + ColdMax?: number; + IsNoisy?: boolean; + IsFpsStuck?: boolean; + IsGlitch?: boolean; + IsMotionBlurred?: boolean; + IsPixelated?: boolean; + PixelationBlockCount?: number; + ShiftsAimCamera?: number; + magAnimationIndex?: number; + Cartridges?: Slot[]; + CanFast?: boolean; + CanHit?: boolean; + CanAdmin?: boolean; + LoadUnloadModifier?: number; + CheckTimeModifier?: number; + CheckOverride?: number; + ReloadMagType?: string; + VisibleAmmoRangesString?: string; + MalfunctionChance?: number; + IsShoulderContact?: boolean; + Foldable?: boolean; + Retractable?: boolean; + SizeReduceRight?: number; + CenterOfImpact?: number; + ShotgunDispersion?: number; + IsSilencer?: boolean; + DeviationCurve?: number; + DeviationMax?: number; + SearchSound?: string; + BlocksArmorVest?: boolean; + speedPenaltyPercent?: number; + GridLayoutName?: string; + ContainerSpawnChanceModifier?: number; + SpawnExcludedFilter?: string[]; + SpawnFilter?: any[]; + containType?: any[]; + sizeWidth?: number; + sizeHeight?: number; + isSecured?: boolean; + spawnTypes?: string; + lootFilter?: any[]; + spawnRarity?: string; + minCountSpawn?: number; + maxCountSpawn?: number; + openedByKeyID?: any[]; + RigLayoutName?: string; + MaxDurability?: number; + armorZone?: string[]; + armorClass?: string | number; + armorColliders?: string[]; + armorPlateColliders?: string[]; + bluntDamageReduceFromSoftArmor?: boolean; + mousePenalty?: number; + weaponErgonomicPenalty?: number; + BluntThroughput?: number; + ArmorMaterial?: string; + ArmorType?: string; + weapClass?: string; + weapUseType?: string; + ammoCaliber?: string; + OperatingResource?: number; + PostRecoilHorizontalRangeHandRotation?: Ixyz; + PostRecoilVerticalRangeHandRotation?: Ixyz; + ProgressRecoilAngleOnStable?: Ixyz; + RepairComplexity?: number; + durabSpawnMin?: number; + durabSpawnMax?: number; + isFastReload?: boolean; + RecoilForceUp?: number; + RecoilForceBack?: number; + RecoilAngle?: number; + RecoilCamera?: number; + weapFireType?: string[]; + RecolDispersion?: number; + SingleFireRate?: number; + CanQueueSecondShot?: boolean; + bFirerate?: number; + bEffDist?: number; + bHearDist?: number; + blockLeftStance?: boolean; + isChamberLoad?: boolean; + chamberAmmoCount?: number; + isBoltCatch?: boolean; + defMagType?: string; + defAmmo?: string; + AdjustCollimatorsToTrajectory?: boolean; + shotgunDispersion?: number; + Chambers?: Slot[]; + CameraSnap?: number; + CameraToWeaponAngleSpeedRange?: Ixyz; + CameraToWeaponAngleStep?: number; + ReloadMode?: string; + AimPlane?: number; + TacticalReloadStiffnes?: Ixyz; + TacticalReloadFixation?: number; + RecoilCenter?: Ixyz; + RotationCenter?: Ixyz; + RotationCenterNoStock?: Ixyz; + ShotsGroupSettings?: IShotsGroupSettings[]; + FoldedSlot?: string; + CompactHandling?: boolean; + MinRepairDegradation?: number; + MaxRepairDegradation?: number; + IronSightRange?: number; + IsBeltMachineGun?: boolean; + IsFlareGun?: boolean; + IsGrenadeLauncher?: boolean; + IsOneoff?: boolean; + MustBoltBeOpennedForExternalReload?: boolean; + MustBoltBeOpennedForInternalReload?: boolean; + NoFiremodeOnBoltcatch?: boolean; + BoltAction?: boolean; + HipAccuracyRestorationDelay?: number; + HipAccuracyRestorationSpeed?: number; + HipInnaccuracyGain?: number; + ManualBoltCatch?: boolean; + BurstShotsCount?: number; + BaseMalfunctionChance?: number; + AllowJam?: boolean; + AllowFeed?: boolean; + AllowMisfire?: boolean; + AllowSlide?: boolean; + DurabilityBurnRatio?: number; + HeatFactorGun?: number; + CoolFactorGun?: number; + CoolFactorGunMods?: number; + HeatFactorByShot?: number; + AllowOverheat?: boolean; + DoubleActionAccuracyPenalty?: number; + RecoilPosZMult?: number; + RecoilReturnPathDampingHandRotation?: number; + RecoilReturnPathOffsetHandRotation?: number; + RecoilReturnSpeedHandRotation?: number; + RecoilStableAngleIncreaseStep?: number; + RecoilStableIndexShot?: number; + MinRepairKitDegradation?: number; + MaxRepairKitDegradation?: number; + BlocksEarpiece?: boolean; + BlocksEyewear?: boolean; + BlocksHeadwear?: boolean; + BlocksFaceCover?: boolean; + Indestructibility?: number; + headSegments?: string[]; + FaceShieldComponent?: boolean; + FaceShieldMask?: string; + MaterialType?: string; + RicochetParams?: Ixyz; + DeafStrength?: string; + BlindnessProtection?: number; + Distortion?: number; + CompressorTreshold?: number; + CompressorAttack?: number; + CompressorRelease?: number; + CompressorGain?: number; + CutoffFreq?: number; + Resonance?: number; + RolloffMultiplier?: number; + ReverbVolume?: number; + CompressorVolume?: number; + AmbientVolume?: number; + DryVolume?: number; + HighFrequenciesGain?: number; + foodUseTime?: number; + foodEffectType?: string; + StimulatorBuffs?: string; + effects_health?: IHealthEffect[] | Record>; + effects_damage?: Record; + MaximumNumberOfUsage?: number; + knifeHitDelay?: number; + knifeHitSlashRate?: number; + knifeHitStabRate?: number; + knifeHitRadius?: number; + knifeHitSlashDam?: number; + knifeHitStabDam?: number; + knifeDurab?: number; + PrimaryDistance?: number; + SecondryDistance?: number; + SlashPenetration?: number; + StabPenetration?: number; + PrimaryConsumption?: number; + SecondryConsumption?: number; + DeflectionConsumption?: number; + AppliedTrunkRotation?: Ixyz; + AppliedHeadRotation?: Ixyz; + DisplayOnModel?: boolean; + AdditionalAnimationLayer?: number; + StaminaBurnRate?: number; + ColliderScaleMultiplier?: Ixyz; + ConfigPathStr?: string; + MaxMarkersCount?: number; + scaleMin?: number; + scaleMax?: number; + medUseTime?: number; + medEffectType?: string; + MaxHpResource?: number; + hpResourceRate?: number; + apResource?: number; + krResource?: number; + MaxOpticZoom?: number; + MaxRepairResource?: number; + TargetItemFilter?: string[]; + RepairQuality?: number; + RepairType?: string; + StackMinRandom?: number; + StackMaxRandom?: number; + ammoType?: string; + InitialSpeed?: number; + BallisticCoeficient?: number; + BulletMassGram?: number; + BulletDiameterMilimeters?: number; + Damage?: number; + ammoAccr?: number; + ammoRec?: number; + ammoDist?: number; + buckshotBullets?: number; + PenetrationPower?: number; + PenetrationPowerDiviation?: number; + ammoHear?: number; + ammoSfx?: string; + MisfireChance?: number; + MinFragmentsCount?: number; + MaxFragmentsCount?: number; + ammoShiftChance?: number; + casingName?: string; + casingEjectPower?: number; + casingMass?: number; + casingSounds?: string; + ProjectileCount?: number; + PenetrationChanceObstacle?: number; + PenetrationDamageMod?: number; + RicochetChance?: number; + FragmentationChance?: number; + Deterioration?: number; + SpeedRetardation?: number; + Tracer?: boolean; + TracerColor?: string; + TracerDistance?: number; + ArmorDamage?: number; + Caliber?: string; + StaminaBurnPerDamage?: number; + HeavyBleedingDelta?: number; + LightBleedingDelta?: number; + ShowBullet?: boolean; + HasGrenaderComponent?: boolean; + FuzeArmTimeSec?: number; + ExplosionStrength?: number; + MinExplosionDistance?: number; + MaxExplosionDistance?: number; + FragmentsCount?: number; + FragmentType?: string; + ShowHitEffectOnExplode?: boolean; + ExplosionType?: string; + AmmoLifeTimeSec?: number; + Contusion?: Ixyz; + ArmorDistanceDistanceDamage?: Ixyz; + Blindness?: Ixyz; + IsLightAndSoundShot?: boolean; + LightAndSoundShotAngle?: number; + LightAndSoundShotSelfContusionTime?: number; + LightAndSoundShotSelfContusionStrength?: number; + MalfMisfireChance?: number; + MalfFeedChance?: number; + StackSlots?: StackSlot[]; + type?: string; + eqMin?: number; + eqMax?: number; + rate?: number; + ThrowType?: string; + ExplDelay?: number; + Strength?: number; + ContusionDistance?: number; + throwDamMax?: number; + explDelay?: number; + EmitTime?: number; + CanBeHiddenDuringThrow?: boolean; + MinTimeToContactExplode?: number; + ExplosionEffectType?: string; + LinkedWeapon?: string; + UseAmmoWithoutShell?: boolean; + RandomLootSettings?: IRandomLootSettings; + RecoilCategoryMultiplierHandRotation?: number; + RecoilDampingHandRotation?: number; + LeanWeaponAgainstBody?: boolean; + RemoveShellAfterFire?: boolean; + RepairStrategyTypes?: string[]; + IsEncoded?: boolean; + LayoutName?: string; + Lower75Prefab?: Prefab; + MaxUsages?: number; + ScavKillExpPenalty?: number; + ScavKillExpPenaltyPVE?: number; + ScavKillStandingPenalty?: number; + ScavKillStandingPenaltyPVE?: number; + TradersDiscount?: number; + TradersDiscountPVE?: number; } -export interface IHealthEffect -{ - type: string - value: number +export interface IHealthEffect { + type: string; + value: number; } -export interface Prefab -{ - path: string - rcid: string +export interface Prefab { + path: string; + rcid: string; } -export interface Grid -{ - _name: string - _id: string - _parent: string - _props: GridProps - _proto: string +export interface Grid { + _name: string; + _id: string; + _parent: string; + _props: GridProps; + _proto: string; } -export interface GridProps -{ - filters: GridFilter[] - cellsH: number - cellsV: number - minCount: number - maxCount: number - maxWeight: number - isSortingTable: boolean +export interface GridProps { + filters: GridFilter[]; + cellsH: number; + cellsV: number; + minCount: number; + maxCount: number; + maxWeight: number; + isSortingTable: boolean; } -export interface GridFilter -{ - Filter: string[] - ExcludedFilter: string[] +export interface GridFilter { + Filter: string[]; + ExcludedFilter: string[]; } -export interface Slot -{ - _name: string - _id: string - _parent: string - _props: SlotProps - _max_count?: number - _required?: boolean - _mergeSlotWithChildren?: boolean - _proto: string +export interface Slot { + _name: string; + _id: string; + _parent: string; + _props: SlotProps; + _max_count?: number; + _required?: boolean; + _mergeSlotWithChildren?: boolean; + _proto: string; } -export interface SlotProps -{ - filters: SlotFilter[] - MaxStackCount?: number +export interface SlotProps { + filters: SlotFilter[]; + MaxStackCount?: number; } -export interface SlotFilter -{ - Shift?: number - locked?: boolean - Plate?: string - armorColliders?: string[] - armorPlateColliders?: string[] - Filter: string[] - AnimationIndex?: number +export interface SlotFilter { + Shift?: number; + locked?: boolean; + Plate?: string; + armorColliders?: string[]; + armorPlateColliders?: string[]; + Filter: string[]; + AnimationIndex?: number; } -export interface StackSlot -{ - _name?: string - _id: string - _parent: string - _max_count: number - _props: StackSlotProps - _proto: string - upd?: any +export interface StackSlot { + _name?: string; + _id: string; + _parent: string; + _max_count: number; + _props: StackSlotProps; + _proto: string; + upd?: any; } -export interface StackSlotProps -{ - filters: SlotFilter[] +export interface StackSlotProps { + filters: SlotFilter[]; } -export interface IRandomLootSettings -{ - allowToSpawnIdenticalItems: boolean - allowToSpawnQuestItems: boolean - countByRarity: any[] - excluded: IRandomLootExcluded - filters: any[] - findInRaid: boolean - maxCount: number - minCount: number +export interface IRandomLootSettings { + allowToSpawnIdenticalItems: boolean; + allowToSpawnQuestItems: boolean; + countByRarity: any[]; + excluded: IRandomLootExcluded; + filters: any[]; + findInRaid: boolean; + maxCount: number; + minCount: number; } -export interface IRandomLootExcluded -{ - categoryTemplates: any[] - rarity: string[] - templates: any[] +export interface IRandomLootExcluded { + categoryTemplates: any[]; + rarity: string[]; + templates: any[]; } -export interface EffectsHealth -{ - Energy: EffectsHealthProps - Hydration: EffectsHealthProps +export interface EffectsHealth { + Energy: EffectsHealthProps; + Hydration: EffectsHealthProps; } -export interface EffectsHealthProps -{ - value: number +export interface EffectsHealthProps { + value: number; } -export interface EffectsDamage -{ - Pain: IEffectDamageProps - LightBleeding: IEffectDamageProps - HeavyBleeding: IEffectDamageProps - Contusion: IEffectDamageProps - RadExposure: IEffectDamageProps - Fracture: IEffectDamageProps - DestroyedPart: IEffectDamageProps +export interface EffectsDamage { + Pain: IEffectDamageProps; + LightBleeding: IEffectDamageProps; + HeavyBleeding: IEffectDamageProps; + Contusion: IEffectDamageProps; + RadExposure: IEffectDamageProps; + Fracture: IEffectDamageProps; + DestroyedPart: IEffectDamageProps; } -export interface IEffectDamageProps -{ - delay: number - duration: number - fadeOut: number - cost?: number - healthPenaltyMin?: number - healthPenaltyMax?: number +export interface IEffectDamageProps { + delay: number; + duration: number; + fadeOut: number; + cost?: number; + healthPenaltyMin?: number; + healthPenaltyMax?: number; } -export interface IColor -{ - r: number - g: number - b: number - a: number +export interface IColor { + r: number; + g: number; + b: number; + a: number; } -export interface IShotsGroupSettings -{ - EndShotIndex: number - ShotRecoilPositionStrength: Ixyz - ShotRecoilRadianRange: Ixyz - ShotRecoilRotationStrength: Ixyz - StartShotIndex: number +export interface IShotsGroupSettings { + EndShotIndex: number; + ShotRecoilPositionStrength: Ixyz; + ShotRecoilRadianRange: Ixyz; + ShotRecoilRotationStrength: Ixyz; + StartShotIndex: number; } -export enum ItemType -{ +export enum ItemType { NODE = "Node", ITEM = "Item", } diff --git a/project/src/models/eft/common/tables/ITrader.ts b/project/src/models/eft/common/tables/ITrader.ts index dbbe14e7..c6070e73 100644 --- a/project/src/models/eft/common/tables/ITrader.ts +++ b/project/src/models/eft/common/tables/ITrader.ts @@ -2,125 +2,114 @@ import { Item } from "@spt/models/eft/common/tables/IItem"; import { DogtagExchangeSide } from "@spt/models/enums/DogtagExchangeSide"; import { ITraderServiceModel } from "@spt/models/spt/services/ITraderServiceModel"; -export interface ITrader -{ - assort?: ITraderAssort - base: ITraderBase - dialogue?: Record - questassort?: Record> - suits?: ISuit[] - services?: ITraderServiceModel[] +export interface ITrader { + assort?: ITraderAssort; + base: ITraderBase; + dialogue?: Record; + questassort?: Record>; + suits?: ISuit[]; + services?: ITraderServiceModel[]; } -export interface ITraderBase -{ - refreshTraderRagfairOffers: boolean - _id: string - availableInRaid: boolean - avatar: string - balance_dol: number - balance_eur: number - balance_rub: number - buyer_up: boolean - currency: string - customization_seller: boolean - discount: number - discount_end: number - gridHeight: number - insurance: Insurance - items_buy: IItemBuyData - items_buy_prohibited: IItemBuyData - location: string - loyaltyLevels: LoyaltyLevel[] - medic: boolean - name: string - nextResupply: number - nickname: string - repair: Repair - sell_category: string[] - surname: string - unlockedByDefault: boolean +export interface ITraderBase { + refreshTraderRagfairOffers: boolean; + _id: string; + availableInRaid: boolean; + avatar: string; + balance_dol: number; + balance_eur: number; + balance_rub: number; + buyer_up: boolean; + currency: string; + customization_seller: boolean; + discount: number; + discount_end: number; + gridHeight: number; + insurance: Insurance; + items_buy: IItemBuyData; + items_buy_prohibited: IItemBuyData; + location: string; + loyaltyLevels: LoyaltyLevel[]; + medic: boolean; + name: string; + nextResupply: number; + nickname: string; + repair: Repair; + sell_category: string[]; + surname: string; + unlockedByDefault: boolean; } -export interface IItemBuyData -{ - category: string[] - id_list: string[] +export interface IItemBuyData { + category: string[]; + id_list: string[]; } -export interface Insurance -{ - availability: boolean - excluded_category: string[] - max_return_hour: number - max_storage_time: number - min_payment: number - min_return_hour: number +export interface Insurance { + availability: boolean; + excluded_category: string[]; + max_return_hour: number; + max_storage_time: number; + min_payment: number; + min_return_hour: number; } -export interface LoyaltyLevel -{ - buy_price_coef: number - exchange_price_coef: number - heal_price_coef: number - insurance_price_coef: number - minLevel: number - minSalesSum: number - minStanding: number - repair_price_coef: number +export interface LoyaltyLevel { + buy_price_coef: number; + exchange_price_coef: number; + heal_price_coef: number; + insurance_price_coef: number; + minLevel: number; + minSalesSum: number; + minStanding: number; + repair_price_coef: number; } -export interface Repair -{ - availability: boolean - currency: string - currency_coefficient: number - excluded_category: string[] +export interface Repair { + availability: boolean; + currency: string; + currency_coefficient: number; + excluded_category: string[]; /** Doesn't exist in client object */ - excluded_id_list: any[] - quality: number + excluded_id_list: any[]; + quality: number; } -export interface ITraderAssort -{ - nextResupply: number - items: Item[] - barter_scheme: Record - loyal_level_items: Record +export interface ITraderAssort { + nextResupply: number; + items: Item[]; + barter_scheme: Record; + loyal_level_items: Record; } -export interface IBarterScheme -{ - count: number - _tpl: string - onlyFunctional?: boolean - sptQuestLocked?: boolean - level?: number - side?: DogtagExchangeSide +export interface IBarterScheme { + count: number; + _tpl: string; + onlyFunctional?: boolean; + sptQuestLocked?: boolean; + level?: number; + side?: DogtagExchangeSide; } -export interface ISuit -{ - _id: string - tid: string - suiteId: string - isActive: boolean - requirements: ISuitRequirements +export interface ISuit { + _id: string; + tid: string; + suiteId: string; + isActive: boolean; + requirements: ISuitRequirements; } -export interface ISuitRequirements -{ - loyaltyLevel: number - profileLevel: number - standing: number - skillRequirements: string[] - questRequirements: string[] - itemRequirements: ItemRequirement[] +export interface ISuitRequirements { + loyaltyLevel: number; + profileLevel: number; + standing: number; + skillRequirements: string[]; + questRequirements: string[]; + itemRequirements: ItemRequirement[]; } -export interface ItemRequirement -{ - count: number - _tpl: string - onlyFunctional: boolean +export interface ItemRequirement { + count: number; + _tpl: string; + onlyFunctional: boolean; } diff --git a/project/src/models/eft/customization/IBuyClothingRequestData.ts b/project/src/models/eft/customization/IBuyClothingRequestData.ts index dab74dfe..a5c97006 100644 --- a/project/src/models/eft/customization/IBuyClothingRequestData.ts +++ b/project/src/models/eft/customization/IBuyClothingRequestData.ts @@ -1,13 +1,11 @@ -export interface IBuyClothingRequestData -{ - Action: "CustomizationBuy" - offer: string - items: ClothingItem[] +export interface IBuyClothingRequestData { + Action: "CustomizationBuy"; + offer: string; + items: ClothingItem[]; } -export interface ClothingItem -{ - del: boolean - id: string - count: number +export interface ClothingItem { + del: boolean; + id: string; + count: number; } diff --git a/project/src/models/eft/customization/IGetSuitsResponse.ts b/project/src/models/eft/customization/IGetSuitsResponse.ts index 8832c574..cbb909da 100644 --- a/project/src/models/eft/customization/IGetSuitsResponse.ts +++ b/project/src/models/eft/customization/IGetSuitsResponse.ts @@ -1,5 +1,4 @@ -export interface IGetSuitsResponse -{ - _id: string - suites: string[] +export interface IGetSuitsResponse { + _id: string; + suites: string[]; } diff --git a/project/src/models/eft/customization/IWearClothingRequestData.ts b/project/src/models/eft/customization/IWearClothingRequestData.ts index ff7e220b..122d9cfe 100644 --- a/project/src/models/eft/customization/IWearClothingRequestData.ts +++ b/project/src/models/eft/customization/IWearClothingRequestData.ts @@ -1,5 +1,4 @@ -export interface IWearClothingRequestData -{ - Action: "CustomizationWear" - suites: string[] +export interface IWearClothingRequestData { + Action: "CustomizationWear"; + suites: string[]; } diff --git a/project/src/models/eft/dialog/IAcceptFriendRequestData.ts b/project/src/models/eft/dialog/IAcceptFriendRequestData.ts index 9cd36601..a3dd797c 100644 --- a/project/src/models/eft/dialog/IAcceptFriendRequestData.ts +++ b/project/src/models/eft/dialog/IAcceptFriendRequestData.ts @@ -1,13 +1,9 @@ -export interface IAcceptFriendRequestData extends IBaseFriendRequest -{} +export interface IAcceptFriendRequestData extends IBaseFriendRequest {} -export interface ICancelFriendRequestData extends IBaseFriendRequest -{} +export interface ICancelFriendRequestData extends IBaseFriendRequest {} -export interface IDeclineFriendRequestData extends IBaseFriendRequest -{} +export interface IDeclineFriendRequestData extends IBaseFriendRequest {} -export interface IBaseFriendRequest -{ - profileId: string +export interface IBaseFriendRequest { + profileId: string; } diff --git a/project/src/models/eft/dialog/IAddUserGroupMailRequest.ts b/project/src/models/eft/dialog/IAddUserGroupMailRequest.ts index 6d6ee0e4..d1170d14 100644 --- a/project/src/models/eft/dialog/IAddUserGroupMailRequest.ts +++ b/project/src/models/eft/dialog/IAddUserGroupMailRequest.ts @@ -1,5 +1,4 @@ -export interface IAddUserGroupMailRequest -{ - dialogId: string - uid: string +export interface IAddUserGroupMailRequest { + dialogId: string; + uid: string; } diff --git a/project/src/models/eft/dialog/IChangeGroupMailOwnerRequest.ts b/project/src/models/eft/dialog/IChangeGroupMailOwnerRequest.ts index d0674393..63b413fa 100644 --- a/project/src/models/eft/dialog/IChangeGroupMailOwnerRequest.ts +++ b/project/src/models/eft/dialog/IChangeGroupMailOwnerRequest.ts @@ -1,5 +1,4 @@ -export interface IChangeGroupMailOwnerRequest -{ - dialogId: string - uid: string +export interface IChangeGroupMailOwnerRequest { + dialogId: string; + uid: string; } diff --git a/project/src/models/eft/dialog/IChatServer.ts b/project/src/models/eft/dialog/IChatServer.ts index bfef3f3d..d7276c09 100644 --- a/project/src/models/eft/dialog/IChatServer.ts +++ b/project/src/models/eft/dialog/IChatServer.ts @@ -1,19 +1,17 @@ -export interface IChatServer -{ - _id: string - RegistrationId: number - VersionId: string - Ip: string - Port: number - DateTime: number - Chats: IChat[] - Regions: string[] +export interface IChatServer { + _id: string; + RegistrationId: number; + VersionId: string; + Ip: string; + Port: number; + DateTime: number; + Chats: IChat[]; + Regions: string[]; /** Possibly removed */ - IsDeveloper?: boolean + IsDeveloper?: boolean; } -export interface IChat -{ - _id: string - Members: number +export interface IChat { + _id: string; + Members: number; } diff --git a/project/src/models/eft/dialog/IClearMailMessageRequest.ts b/project/src/models/eft/dialog/IClearMailMessageRequest.ts index 7c6007ad..ca4de5a4 100644 --- a/project/src/models/eft/dialog/IClearMailMessageRequest.ts +++ b/project/src/models/eft/dialog/IClearMailMessageRequest.ts @@ -1,4 +1,3 @@ -export interface IClearMailMessageRequest -{ - dialogId: string +export interface IClearMailMessageRequest { + dialogId: string; } diff --git a/project/src/models/eft/dialog/ICreateGroupMailRequest.ts b/project/src/models/eft/dialog/ICreateGroupMailRequest.ts index 8bcec42a..176d7f3f 100644 --- a/project/src/models/eft/dialog/ICreateGroupMailRequest.ts +++ b/project/src/models/eft/dialog/ICreateGroupMailRequest.ts @@ -1,5 +1,4 @@ -export interface ICreateGroupMailRequest -{ - Name: string - Users: string[] +export interface ICreateGroupMailRequest { + Name: string; + Users: string[]; } diff --git a/project/src/models/eft/dialog/IDeleteFriendRequest.ts b/project/src/models/eft/dialog/IDeleteFriendRequest.ts index 89115e11..2923e02f 100644 --- a/project/src/models/eft/dialog/IDeleteFriendRequest.ts +++ b/project/src/models/eft/dialog/IDeleteFriendRequest.ts @@ -1,4 +1,3 @@ -export interface IDeleteFriendRequest -{ - friend_id: string +export interface IDeleteFriendRequest { + friend_id: string; } diff --git a/project/src/models/eft/dialog/IFriendRequestData.ts b/project/src/models/eft/dialog/IFriendRequestData.ts index 7606c44d..9c326ac1 100644 --- a/project/src/models/eft/dialog/IFriendRequestData.ts +++ b/project/src/models/eft/dialog/IFriendRequestData.ts @@ -1,4 +1,3 @@ -export interface IFriendRequestData -{ - to: string +export interface IFriendRequestData { + to: string; } diff --git a/project/src/models/eft/dialog/IFriendRequestSendResponse.ts b/project/src/models/eft/dialog/IFriendRequestSendResponse.ts index fc058479..fc311eba 100644 --- a/project/src/models/eft/dialog/IFriendRequestSendResponse.ts +++ b/project/src/models/eft/dialog/IFriendRequestSendResponse.ts @@ -1,6 +1,5 @@ -export interface IFriendRequestSendResponse -{ - status: number - requestId: string - retryAfter: number +export interface IFriendRequestSendResponse { + status: number; + requestId: string; + retryAfter: number; } diff --git a/project/src/models/eft/dialog/IGetAllAttachmentsRequestData.ts b/project/src/models/eft/dialog/IGetAllAttachmentsRequestData.ts index 4df486b7..53d82894 100644 --- a/project/src/models/eft/dialog/IGetAllAttachmentsRequestData.ts +++ b/project/src/models/eft/dialog/IGetAllAttachmentsRequestData.ts @@ -1,4 +1,3 @@ -export interface IGetAllAttachmentsRequestData -{ - dialogId: string +export interface IGetAllAttachmentsRequestData { + dialogId: string; } diff --git a/project/src/models/eft/dialog/IGetAllAttachmentsResponse.ts b/project/src/models/eft/dialog/IGetAllAttachmentsResponse.ts index 1cab6c7c..0989abf9 100644 --- a/project/src/models/eft/dialog/IGetAllAttachmentsResponse.ts +++ b/project/src/models/eft/dialog/IGetAllAttachmentsResponse.ts @@ -1,8 +1,7 @@ import { Message } from "@spt/models/eft/profile/ISptProfile"; -export interface IGetAllAttachmentsResponse -{ - messages: Message[] - profiles: any[] - hasMessagesWithRewards: boolean +export interface IGetAllAttachmentsResponse { + messages: Message[]; + profiles: any[]; + hasMessagesWithRewards: boolean; } diff --git a/project/src/models/eft/dialog/IGetChatServerListRequestData.ts b/project/src/models/eft/dialog/IGetChatServerListRequestData.ts index 9056790a..8f1beac9 100644 --- a/project/src/models/eft/dialog/IGetChatServerListRequestData.ts +++ b/project/src/models/eft/dialog/IGetChatServerListRequestData.ts @@ -1,4 +1,3 @@ -export interface IGetChatServerListRequestData -{ - VersionId: string +export interface IGetChatServerListRequestData { + VersionId: string; } diff --git a/project/src/models/eft/dialog/IGetFriendListDataResponse.ts b/project/src/models/eft/dialog/IGetFriendListDataResponse.ts index 531a8f45..d7ccadd3 100644 --- a/project/src/models/eft/dialog/IGetFriendListDataResponse.ts +++ b/project/src/models/eft/dialog/IGetFriendListDataResponse.ts @@ -1,8 +1,7 @@ import { IUserDialogInfo } from "@spt/models/eft/profile/ISptProfile"; -export interface IGetFriendListDataResponse -{ - Friends: IUserDialogInfo[] - Ignore: string[] - InIgnoreList: string[] +export interface IGetFriendListDataResponse { + Friends: IUserDialogInfo[]; + Ignore: string[]; + InIgnoreList: string[]; } diff --git a/project/src/models/eft/dialog/IGetMailDialogInfoRequestData.ts b/project/src/models/eft/dialog/IGetMailDialogInfoRequestData.ts index ccf0803a..eed84b17 100644 --- a/project/src/models/eft/dialog/IGetMailDialogInfoRequestData.ts +++ b/project/src/models/eft/dialog/IGetMailDialogInfoRequestData.ts @@ -1,4 +1,3 @@ -export interface IGetMailDialogInfoRequestData -{ - dialogId: string +export interface IGetMailDialogInfoRequestData { + dialogId: string; } diff --git a/project/src/models/eft/dialog/IGetMailDialogListRequestData.ts b/project/src/models/eft/dialog/IGetMailDialogListRequestData.ts index 507bc56a..f8fbf5d0 100644 --- a/project/src/models/eft/dialog/IGetMailDialogListRequestData.ts +++ b/project/src/models/eft/dialog/IGetMailDialogListRequestData.ts @@ -1,5 +1,4 @@ -export interface IGetMailDialogListRequestData -{ - limit: number - offset: number +export interface IGetMailDialogListRequestData { + limit: number; + offset: number; } diff --git a/project/src/models/eft/dialog/IGetMailDialogViewRequestData.ts b/project/src/models/eft/dialog/IGetMailDialogViewRequestData.ts index f461bc36..f9c68cc8 100644 --- a/project/src/models/eft/dialog/IGetMailDialogViewRequestData.ts +++ b/project/src/models/eft/dialog/IGetMailDialogViewRequestData.ts @@ -1,9 +1,8 @@ import { MessageType } from "@spt/models/enums/MessageType"; -export interface IGetMailDialogViewRequestData -{ - type: MessageType - dialogId: string - limit: number - time: number // decimal +export interface IGetMailDialogViewRequestData { + type: MessageType; + dialogId: string; + limit: number; + time: number; // decimal } diff --git a/project/src/models/eft/dialog/IGetMailDialogViewResponseData.ts b/project/src/models/eft/dialog/IGetMailDialogViewResponseData.ts index ec29719d..bdc8df8c 100644 --- a/project/src/models/eft/dialog/IGetMailDialogViewResponseData.ts +++ b/project/src/models/eft/dialog/IGetMailDialogViewResponseData.ts @@ -1,8 +1,7 @@ import { IUserDialogInfo, Message } from "@spt/models/eft/profile/ISptProfile"; -export interface IGetMailDialogViewResponseData -{ - messages: Message[] - profiles: IUserDialogInfo[] - hasMessagesWithRewards: boolean +export interface IGetMailDialogViewResponseData { + messages: Message[]; + profiles: IUserDialogInfo[]; + hasMessagesWithRewards: boolean; } diff --git a/project/src/models/eft/dialog/IPinDialogRequestData.ts b/project/src/models/eft/dialog/IPinDialogRequestData.ts index 04a5b8f0..57b8a009 100644 --- a/project/src/models/eft/dialog/IPinDialogRequestData.ts +++ b/project/src/models/eft/dialog/IPinDialogRequestData.ts @@ -1,4 +1,3 @@ -export interface IPinDialogRequestData -{ - dialogId: string +export interface IPinDialogRequestData { + dialogId: string; } diff --git a/project/src/models/eft/dialog/IRemoveDialogRequestData.ts b/project/src/models/eft/dialog/IRemoveDialogRequestData.ts index 7ff2f9e6..874b8288 100644 --- a/project/src/models/eft/dialog/IRemoveDialogRequestData.ts +++ b/project/src/models/eft/dialog/IRemoveDialogRequestData.ts @@ -1,4 +1,3 @@ -export interface IRemoveDialogRequestData -{ - dialogId: string +export interface IRemoveDialogRequestData { + dialogId: string; } diff --git a/project/src/models/eft/dialog/IRemoveMailMessageRequest.ts b/project/src/models/eft/dialog/IRemoveMailMessageRequest.ts index 83ab3915..e2aa8c6b 100644 --- a/project/src/models/eft/dialog/IRemoveMailMessageRequest.ts +++ b/project/src/models/eft/dialog/IRemoveMailMessageRequest.ts @@ -1,4 +1,3 @@ -export interface IRemoveMailMessageRequest -{ - dialogId: string +export interface IRemoveMailMessageRequest { + dialogId: string; } diff --git a/project/src/models/eft/dialog/IRemoveUserGroupMailRequest.ts b/project/src/models/eft/dialog/IRemoveUserGroupMailRequest.ts index 61eff0aa..c7582f88 100644 --- a/project/src/models/eft/dialog/IRemoveUserGroupMailRequest.ts +++ b/project/src/models/eft/dialog/IRemoveUserGroupMailRequest.ts @@ -1,5 +1,4 @@ -export interface IRemoveUserGroupMailRequest -{ - dialogId: string - uid: string +export interface IRemoveUserGroupMailRequest { + dialogId: string; + uid: string; } diff --git a/project/src/models/eft/dialog/ISendMessageRequest.ts b/project/src/models/eft/dialog/ISendMessageRequest.ts index 2f823355..e32db54f 100644 --- a/project/src/models/eft/dialog/ISendMessageRequest.ts +++ b/project/src/models/eft/dialog/ISendMessageRequest.ts @@ -1,9 +1,8 @@ import { MessageType } from "@spt/models/enums/MessageType"; -export interface ISendMessageRequest -{ - dialogId: string - type: MessageType - text: string - replyTo: string +export interface ISendMessageRequest { + dialogId: string; + type: MessageType; + text: string; + replyTo: string; } diff --git a/project/src/models/eft/dialog/ISetDialogReadRequestData.ts b/project/src/models/eft/dialog/ISetDialogReadRequestData.ts index 27623fa7..20762321 100644 --- a/project/src/models/eft/dialog/ISetDialogReadRequestData.ts +++ b/project/src/models/eft/dialog/ISetDialogReadRequestData.ts @@ -1,4 +1,3 @@ -export interface ISetDialogReadRequestData -{ - dialogs: string[] +export interface ISetDialogReadRequestData { + dialogs: string[]; } diff --git a/project/src/models/eft/game/ICheckVersionResponse.ts b/project/src/models/eft/game/ICheckVersionResponse.ts index 5770b570..fa8aa6f6 100644 --- a/project/src/models/eft/game/ICheckVersionResponse.ts +++ b/project/src/models/eft/game/ICheckVersionResponse.ts @@ -1,5 +1,4 @@ -export interface ICheckVersionResponse -{ - isvalid: boolean - latestVersion: string +export interface ICheckVersionResponse { + isvalid: boolean; + latestVersion: string; } diff --git a/project/src/models/eft/game/ICurrentGroupResponse.ts b/project/src/models/eft/game/ICurrentGroupResponse.ts index d5c1141f..e58c5509 100644 --- a/project/src/models/eft/game/ICurrentGroupResponse.ts +++ b/project/src/models/eft/game/ICurrentGroupResponse.ts @@ -1,23 +1,20 @@ import { MemberCategory } from "@spt/models/enums/MemberCategory"; -export interface ICurrentGroupResponse -{ - squad: ICurrentGroupSquadMember[] +export interface ICurrentGroupResponse { + squad: ICurrentGroupSquadMember[]; } -export interface ICurrentGroupSquadMember -{ - _id: string - aid: string - info: ICurrentGroupMemberInfo - isLeader: boolean - isReady: boolean +export interface ICurrentGroupSquadMember { + _id: string; + aid: string; + info: ICurrentGroupMemberInfo; + isLeader: boolean; + isReady: boolean; } -export interface ICurrentGroupMemberInfo -{ - Nickname: string - Side: string - Level: string - MemberCategory: MemberCategory +export interface ICurrentGroupMemberInfo { + Nickname: string; + Side: string; + Level: string; + MemberCategory: MemberCategory; } diff --git a/project/src/models/eft/game/IGameConfigResponse.ts b/project/src/models/eft/game/IGameConfigResponse.ts index 011306bd..7442e247 100644 --- a/project/src/models/eft/game/IGameConfigResponse.ts +++ b/project/src/models/eft/game/IGameConfigResponse.ts @@ -1,25 +1,23 @@ -export interface IGameConfigResponse -{ - aid: number - lang: string - languages: Record - ndaFree: boolean - taxonomy: number - activeProfileId: string - backend: Backend - useProtobuf: boolean - utc_time: number +export interface IGameConfigResponse { + aid: number; + lang: string; + languages: Record; + ndaFree: boolean; + taxonomy: number; + activeProfileId: string; + backend: Backend; + useProtobuf: boolean; + utc_time: number; /** Total in game time */ - totalInGame: number - reportAvailable: boolean - twitchEventMember: boolean + totalInGame: number; + reportAvailable: boolean; + twitchEventMember: boolean; } -export interface Backend -{ - Lobby: string - Trading: string - Messaging: string - Main: string - RagFair: string +export interface Backend { + Lobby: string; + Trading: string; + Messaging: string; + Main: string; + RagFair: string; } diff --git a/project/src/models/eft/game/IGameEmptyCrcRequestData.ts b/project/src/models/eft/game/IGameEmptyCrcRequestData.ts index 9cd17c8b..a3ecad9a 100644 --- a/project/src/models/eft/game/IGameEmptyCrcRequestData.ts +++ b/project/src/models/eft/game/IGameEmptyCrcRequestData.ts @@ -1,4 +1,3 @@ -export interface IGameEmptyCrcRequestData -{ - crc: number +export interface IGameEmptyCrcRequestData { + crc: number; } diff --git a/project/src/models/eft/game/IGameKeepAliveResponse.ts b/project/src/models/eft/game/IGameKeepAliveResponse.ts index c84b6d1f..170ce6a9 100644 --- a/project/src/models/eft/game/IGameKeepAliveResponse.ts +++ b/project/src/models/eft/game/IGameKeepAliveResponse.ts @@ -1,5 +1,4 @@ -export interface IGameKeepAliveResponse -{ - msg: string - utc_time: number +export interface IGameKeepAliveResponse { + msg: string; + utc_time: number; } diff --git a/project/src/models/eft/game/IGameLogoutResponseData.ts b/project/src/models/eft/game/IGameLogoutResponseData.ts index 188a52ae..0f520503 100644 --- a/project/src/models/eft/game/IGameLogoutResponseData.ts +++ b/project/src/models/eft/game/IGameLogoutResponseData.ts @@ -1,4 +1,3 @@ -export interface IGameLogoutResponseData -{ - status: string +export interface IGameLogoutResponseData { + status: string; } diff --git a/project/src/models/eft/game/IGameModeRequestData.ts b/project/src/models/eft/game/IGameModeRequestData.ts index eb3e5de0..57ff27b3 100644 --- a/project/src/models/eft/game/IGameModeRequestData.ts +++ b/project/src/models/eft/game/IGameModeRequestData.ts @@ -1,4 +1,3 @@ -export interface IGameModeRequestData -{ - sessionMode: string | undefined +export interface IGameModeRequestData { + sessionMode: string | undefined; } diff --git a/project/src/models/eft/game/IGameModeResponse.ts b/project/src/models/eft/game/IGameModeResponse.ts index e7d8b986..406f4bce 100644 --- a/project/src/models/eft/game/IGameModeResponse.ts +++ b/project/src/models/eft/game/IGameModeResponse.ts @@ -1,11 +1,9 @@ -export enum ESessionMode -{ +export enum ESessionMode { REGULAR = "regular", PVE = "pve", } -export interface IGameModeResponse -{ - gameMode: ESessionMode - backendUrl: string +export interface IGameModeResponse { + gameMode: ESessionMode; + backendUrl: string; } diff --git a/project/src/models/eft/game/IGameStartResponse.ts b/project/src/models/eft/game/IGameStartResponse.ts index f5c90f67..9f0ab6d3 100644 --- a/project/src/models/eft/game/IGameStartResponse.ts +++ b/project/src/models/eft/game/IGameStartResponse.ts @@ -1,4 +1,3 @@ -export interface IGameStartResponse -{ - utc_time: number +export interface IGameStartResponse { + utc_time: number; } diff --git a/project/src/models/eft/game/IGetItemPricesResponse.ts b/project/src/models/eft/game/IGetItemPricesResponse.ts index 4e413378..ab6e8189 100644 --- a/project/src/models/eft/game/IGetItemPricesResponse.ts +++ b/project/src/models/eft/game/IGetItemPricesResponse.ts @@ -1,6 +1,5 @@ -export interface IGetItemPricesResponse -{ - supplyNextTime: number - prices: Record - currencyCourses: Record +export interface IGetItemPricesResponse { + supplyNextTime: number; + prices: Record; + currencyCourses: Record; } diff --git a/project/src/models/eft/game/IGetRaidTimeRequest.ts b/project/src/models/eft/game/IGetRaidTimeRequest.ts index a06415d6..b93fb0c1 100644 --- a/project/src/models/eft/game/IGetRaidTimeRequest.ts +++ b/project/src/models/eft/game/IGetRaidTimeRequest.ts @@ -1,5 +1,4 @@ -export interface IGetRaidTimeRequest -{ - Side: string - Location: string +export interface IGetRaidTimeRequest { + Side: string; + Location: string; } diff --git a/project/src/models/eft/game/IGetRaidTimeResponse.ts b/project/src/models/eft/game/IGetRaidTimeResponse.ts index 07f07309..ba97d421 100644 --- a/project/src/models/eft/game/IGetRaidTimeResponse.ts +++ b/project/src/models/eft/game/IGetRaidTimeResponse.ts @@ -1,15 +1,13 @@ -export interface IGetRaidTimeResponse -{ - RaidTimeMinutes: number - NewSurviveTimeSeconds?: number - OriginalSurvivalTimeSeconds: number - ExitChanges: ExtractChange[] +export interface IGetRaidTimeResponse { + RaidTimeMinutes: number; + NewSurviveTimeSeconds?: number; + OriginalSurvivalTimeSeconds: number; + ExitChanges: ExtractChange[]; } -export interface ExtractChange -{ - Name: string - MinTime?: number - MaxTime?: number - Chance?: number +export interface ExtractChange { + Name: string; + MinTime?: number; + MaxTime?: number; + Chance?: number; } diff --git a/project/src/models/eft/game/ISendReportRequest.ts b/project/src/models/eft/game/ISendReportRequest.ts index 77b2d407..b73d95c0 100644 --- a/project/src/models/eft/game/ISendReportRequest.ts +++ b/project/src/models/eft/game/ISendReportRequest.ts @@ -1,5 +1,4 @@ -export interface ISendReportRequest -{ - type: string - uid: string +export interface ISendReportRequest { + type: string; + uid: string; } diff --git a/project/src/models/eft/game/IServerDetails.ts b/project/src/models/eft/game/IServerDetails.ts index 0fc4e74e..101cf990 100644 --- a/project/src/models/eft/game/IServerDetails.ts +++ b/project/src/models/eft/game/IServerDetails.ts @@ -1,5 +1,4 @@ -export interface IServerDetails -{ - ip: string - port: number +export interface IServerDetails { + ip: string; + port: number; } diff --git a/project/src/models/eft/game/IVersionValidateRequestData.ts b/project/src/models/eft/game/IVersionValidateRequestData.ts index c31e7f67..04f2fd04 100644 --- a/project/src/models/eft/game/IVersionValidateRequestData.ts +++ b/project/src/models/eft/game/IVersionValidateRequestData.ts @@ -1,14 +1,12 @@ -export interface IVersionValidateRequestData -{ - version: Version - develop: boolean +export interface IVersionValidateRequestData { + version: Version; + develop: boolean; } -export interface Version -{ - major: string - minor: string - game: string - backend: string - taxonomy: string +export interface Version { + major: string; + minor: string; + game: string; + backend: string; + taxonomy: string; } diff --git a/project/src/models/eft/health/Effect.ts b/project/src/models/eft/health/Effect.ts index b27f856a..98dc6c07 100644 --- a/project/src/models/eft/health/Effect.ts +++ b/project/src/models/eft/health/Effect.ts @@ -1,5 +1,4 @@ -export enum Effect -{ +export enum Effect { FRACTURE = "Fracture", LIGHT_BLEEDING = "LightBleeding", HEAVY_BLEEDING = "HeavyBleeding", diff --git a/project/src/models/eft/health/IHealthTreatmentRequestData.ts b/project/src/models/eft/health/IHealthTreatmentRequestData.ts index 2d182ea8..04257314 100644 --- a/project/src/models/eft/health/IHealthTreatmentRequestData.ts +++ b/project/src/models/eft/health/IHealthTreatmentRequestData.ts @@ -1,41 +1,36 @@ -export interface IHealthTreatmentRequestData -{ - Action: "RestoreHealth" - trader: string - items: Cost[] - difference: Difference - timestamp: number +export interface IHealthTreatmentRequestData { + Action: "RestoreHealth"; + trader: string; + items: Cost[]; + difference: Difference; + timestamp: number; } -export interface Cost -{ +export interface Cost { /** Id of stack to take money from */ - id: string + id: string; /** Amount of money to take off player for treatment */ - count: number + count: number; } -export interface Difference -{ - BodyParts: BodyParts - Energy: number - Hydration: number +export interface Difference { + BodyParts: BodyParts; + Energy: number; + Hydration: number; } -export interface BodyParts -{ - Head: BodyPart - Chest: BodyPart - Stomach: BodyPart - LeftArm: BodyPart - RightArm: BodyPart - LeftLeg: BodyPart - RightLeg: BodyPart +export interface BodyParts { + Head: BodyPart; + Chest: BodyPart; + Stomach: BodyPart; + LeftArm: BodyPart; + RightArm: BodyPart; + LeftLeg: BodyPart; + RightLeg: BodyPart; } -export interface BodyPart -{ - Health: number +export interface BodyPart { + Health: number; /** Effects in array are to be removed */ - Effects: string[] + Effects: string[]; } diff --git a/project/src/models/eft/health/IOffraidEatRequestData.ts b/project/src/models/eft/health/IOffraidEatRequestData.ts index dcac5f1f..2c5d8a52 100644 --- a/project/src/models/eft/health/IOffraidEatRequestData.ts +++ b/project/src/models/eft/health/IOffraidEatRequestData.ts @@ -1,9 +1,8 @@ import { IBaseInteractionRequestData } from "@spt/models/eft/common/request/IBaseInteractionRequestData"; -export interface IOffraidEatRequestData extends IBaseInteractionRequestData -{ - Action: "Eat" - item: string - count: number - time: number +export interface IOffraidEatRequestData extends IBaseInteractionRequestData { + Action: "Eat"; + item: string; + count: number; + time: number; } diff --git a/project/src/models/eft/health/IOffraidHealRequestData.ts b/project/src/models/eft/health/IOffraidHealRequestData.ts index 49ddda99..6b0dba26 100644 --- a/project/src/models/eft/health/IOffraidHealRequestData.ts +++ b/project/src/models/eft/health/IOffraidHealRequestData.ts @@ -1,16 +1,14 @@ import { IBaseInteractionRequestData } from "@spt/models/eft/common/request/IBaseInteractionRequestData"; -export interface IOffraidHealRequestData extends IBaseInteractionRequestData -{ - Action: "Heal" - item: string - part: BodyPart - count: number - time: number +export interface IOffraidHealRequestData extends IBaseInteractionRequestData { + Action: "Heal"; + item: string; + part: BodyPart; + count: number; + time: number; } -export enum BodyPart -{ +export enum BodyPart { HEAD = "Head", CHEST = "Chest", STOMACH = "Stomach", diff --git a/project/src/models/eft/health/ISyncHealthRequestData.ts b/project/src/models/eft/health/ISyncHealthRequestData.ts index 4c1a0735..901f5605 100644 --- a/project/src/models/eft/health/ISyncHealthRequestData.ts +++ b/project/src/models/eft/health/ISyncHealthRequestData.ts @@ -1,26 +1,23 @@ -export interface ISyncHealthRequestData -{ - Health: Health - IsAlive: boolean - Hydration?: number - Energy?: number - Temperature?: number +export interface ISyncHealthRequestData { + Health: Health; + IsAlive: boolean; + Hydration?: number; + Energy?: number; + Temperature?: number; } -export interface Health -{ - Head?: BodyPartHealth - Chest?: BodyPartHealth - Stomach?: BodyPartHealth - LeftArm?: BodyPartHealth - RightArm?: BodyPartHealth - LeftLeg?: BodyPartHealth - RightLeg?: BodyPartHealth +export interface Health { + Head?: BodyPartHealth; + Chest?: BodyPartHealth; + Stomach?: BodyPartHealth; + LeftArm?: BodyPartHealth; + RightArm?: BodyPartHealth; + LeftLeg?: BodyPartHealth; + RightLeg?: BodyPartHealth; } -export interface BodyPartHealth -{ - Maximum: number - Current: number - Effects: Record +export interface BodyPartHealth { + Maximum: number; + Current: number; + Effects: Record; } diff --git a/project/src/models/eft/health/IWorkoutData.ts b/project/src/models/eft/health/IWorkoutData.ts index 06c009c2..54536469 100644 --- a/project/src/models/eft/health/IWorkoutData.ts +++ b/project/src/models/eft/health/IWorkoutData.ts @@ -1,7 +1,6 @@ // TODO: Type this properly. -export interface IWorkoutData extends Record -{ - skills: any - effects: any +export interface IWorkoutData extends Record { + skills: any; + effects: any; } diff --git a/project/src/models/eft/hideout/HideoutUpgradeCompleteRequestData.ts b/project/src/models/eft/hideout/HideoutUpgradeCompleteRequestData.ts index 34ea75b8..8583e8d9 100644 --- a/project/src/models/eft/hideout/HideoutUpgradeCompleteRequestData.ts +++ b/project/src/models/eft/hideout/HideoutUpgradeCompleteRequestData.ts @@ -1,6 +1,5 @@ -export interface HideoutUpgradeCompleteRequestData -{ - Action: string - areaType: number - timestamp: number +export interface HideoutUpgradeCompleteRequestData { + Action: string; + areaType: number; + timestamp: number; } diff --git a/project/src/models/eft/hideout/IHandleQTEEventRequestData.ts b/project/src/models/eft/hideout/IHandleQTEEventRequestData.ts index ed59291e..5dda4859 100644 --- a/project/src/models/eft/hideout/IHandleQTEEventRequestData.ts +++ b/project/src/models/eft/hideout/IHandleQTEEventRequestData.ts @@ -1,9 +1,8 @@ -export interface IHandleQTEEventRequestData -{ - Action: string +export interface IHandleQTEEventRequestData { + Action: string; /** true if QTE was successful, otherwise false */ - results: boolean[] + results: boolean[]; /** Id of the QTE object used from db/hideout/qte.json */ - id: string - timestamp: number + id: string; + timestamp: number; } diff --git a/project/src/models/eft/hideout/IHideoutArea.ts b/project/src/models/eft/hideout/IHideoutArea.ts index eeebd5c9..47b885e7 100644 --- a/project/src/models/eft/hideout/IHideoutArea.ts +++ b/project/src/models/eft/hideout/IHideoutArea.ts @@ -1,94 +1,86 @@ import { BonusSkillType } from "@spt/models/enums/BonusSkillType"; import { BonusType } from "@spt/models/enums/BonusType"; -export interface IHideoutArea -{ - _id: string - type: number - enabled: boolean - needsFuel: boolean - requirements: IAreaRequirement[] - takeFromSlotLocked: boolean - craftGivesExp: boolean - displayLevel: boolean - enableAreaRequirements: boolean - parentArea?: string - stages: Record +export interface IHideoutArea { + _id: string; + type: number; + enabled: boolean; + needsFuel: boolean; + requirements: IAreaRequirement[]; + takeFromSlotLocked: boolean; + craftGivesExp: boolean; + displayLevel: boolean; + enableAreaRequirements: boolean; + parentArea?: string; + stages: Record; } -export interface IAreaRequirement -{ - areaType: number - requiredlevel: number - type: string +export interface IAreaRequirement { + areaType: number; + requiredlevel: number; + type: string; } -export interface Stage -{ - autoUpgrade: boolean - bonuses: StageBonus[] - constructionTime: number +export interface Stage { + autoUpgrade: boolean; + bonuses: StageBonus[]; + constructionTime: number; /** Containers inventory tpl */ - container?: string - description: string - displayInterface: boolean - improvements: IStageImprovement[] - requirements: IStageRequirement[] - slots: number + container?: string; + description: string; + displayInterface: boolean; + improvements: IStageImprovement[]; + requirements: IStageRequirement[]; + slots: number; } -export interface IStageImprovement -{ - id: string - bonuses: IStageImprovementBonus[] - improvementTime: number - requirements: IStageImprovementRequirement[] +export interface IStageImprovement { + id: string; + bonuses: IStageImprovementBonus[]; + improvementTime: number; + requirements: IStageImprovementRequirement[]; } -export interface IStageImprovementBonus -{ - passive: boolean - production: boolean - type: string - value: number - visible: boolean +export interface IStageImprovementBonus { + passive: boolean; + production: boolean; + type: string; + value: number; + visible: boolean; } -export interface IStageImprovementRequirement -{ - count: number - isEncoded: boolean - isFunctional: boolean - templateId: string - type: string +export interface IStageImprovementRequirement { + count: number; + isEncoded: boolean; + isFunctional: boolean; + templateId: string; + type: string; } -export interface IStageRequirement -{ - areaType?: number - requiredLevel?: number - type: string - templateId?: string - count?: number - isEncoded: false - isFunctional?: boolean - traderId?: string - loyaltyLevel?: number - skillName?: string - skillLevel?: number +export interface IStageRequirement { + areaType?: number; + requiredLevel?: number; + type: string; + templateId?: string; + count?: number; + isEncoded: false; + isFunctional?: boolean; + traderId?: string; + loyaltyLevel?: number; + skillName?: string; + skillLevel?: number; } -export interface StageBonus -{ - value: number - passive: boolean - production: boolean - visible: boolean - skillType?: BonusSkillType - type: BonusType - filter?: string[] - icon?: string +export interface StageBonus { + value: number; + passive: boolean; + production: boolean; + visible: boolean; + skillType?: BonusSkillType; + type: BonusType; + filter?: string[]; + icon?: string; /** CHANGES PER DUMP */ - id?: string - templateId?: string + id?: string; + templateId?: string; } diff --git a/project/src/models/eft/hideout/IHideoutCancelProductionRequestData.ts b/project/src/models/eft/hideout/IHideoutCancelProductionRequestData.ts index ef0451fa..4946cc61 100644 --- a/project/src/models/eft/hideout/IHideoutCancelProductionRequestData.ts +++ b/project/src/models/eft/hideout/IHideoutCancelProductionRequestData.ts @@ -1,6 +1,5 @@ -export interface IHideoutCancelProductionRequestData -{ - Action: "HideoutCancelProductionCommand" - recipeId: string - timestamp: number +export interface IHideoutCancelProductionRequestData { + Action: "HideoutCancelProductionCommand"; + recipeId: string; + timestamp: number; } diff --git a/project/src/models/eft/hideout/IHideoutContinuousProductionStartRequestData.ts b/project/src/models/eft/hideout/IHideoutContinuousProductionStartRequestData.ts index 20a50f0d..3ef00c60 100644 --- a/project/src/models/eft/hideout/IHideoutContinuousProductionStartRequestData.ts +++ b/project/src/models/eft/hideout/IHideoutContinuousProductionStartRequestData.ts @@ -1,6 +1,5 @@ -export interface IHideoutContinuousProductionStartRequestData -{ - Action: "HideoutContinuousProductionStart" - recipeId: string - timestamp: number +export interface IHideoutContinuousProductionStartRequestData { + Action: "HideoutContinuousProductionStart"; + recipeId: string; + timestamp: number; } diff --git a/project/src/models/eft/hideout/IHideoutImproveAreaRequestData.ts b/project/src/models/eft/hideout/IHideoutImproveAreaRequestData.ts index 01315949..499e0291 100644 --- a/project/src/models/eft/hideout/IHideoutImproveAreaRequestData.ts +++ b/project/src/models/eft/hideout/IHideoutImproveAreaRequestData.ts @@ -1,16 +1,14 @@ -export interface IHideoutImproveAreaRequestData -{ - Action: "HideoutImproveArea" +export interface IHideoutImproveAreaRequestData { + Action: "HideoutImproveArea"; /** Hideout area id from areas.json */ - id: string - areaType: number - items: HideoutItem[] - timestamp: number + id: string; + areaType: number; + items: HideoutItem[]; + timestamp: number; } -export interface HideoutItem -{ +export interface HideoutItem { /** Hideout inventory id that was used by improvement action */ - id: string - count: number + id: string; + count: number; } diff --git a/project/src/models/eft/hideout/IHideoutProduction.ts b/project/src/models/eft/hideout/IHideoutProduction.ts index cd27b807..150e7daf 100644 --- a/project/src/models/eft/hideout/IHideoutProduction.ts +++ b/project/src/models/eft/hideout/IHideoutProduction.ts @@ -1,28 +1,26 @@ -export interface IHideoutProduction -{ - _id: string - areaType: number - requirements: Requirement[] - productionTime: number +export interface IHideoutProduction { + _id: string; + areaType: number; + requirements: Requirement[]; + productionTime: number; /** Tpl of item being crafted */ - endProduct: string - isEncoded: boolean - locked: boolean - needFuelForAllProductionTime: boolean - continuous: boolean - count: number - productionLimitCount: number + endProduct: string; + isEncoded: boolean; + locked: boolean; + needFuelForAllProductionTime: boolean; + continuous: boolean; + count: number; + productionLimitCount: number; } -export interface Requirement -{ - templateId?: string - count?: number - isEncoded?: boolean - isFunctional?: boolean - type: string - areaType?: number - requiredLevel?: number - resource?: number - questId?: string +export interface Requirement { + templateId?: string; + count?: number; + isEncoded?: boolean; + isFunctional?: boolean; + type: string; + areaType?: number; + requiredLevel?: number; + resource?: number; + questId?: string; } diff --git a/project/src/models/eft/hideout/IHideoutPutItemInRequestData.ts b/project/src/models/eft/hideout/IHideoutPutItemInRequestData.ts index 03effd68..f3c7b6fd 100644 --- a/project/src/models/eft/hideout/IHideoutPutItemInRequestData.ts +++ b/project/src/models/eft/hideout/IHideoutPutItemInRequestData.ts @@ -1,13 +1,11 @@ -export interface IHideoutPutItemInRequestData -{ - Action: "HideoutPutItemsInAreaSlots" - areaType: number - items: Record - timestamp: number +export interface IHideoutPutItemInRequestData { + Action: "HideoutPutItemsInAreaSlots"; + areaType: number; + items: Record; + timestamp: number; } -export interface ItemDetails -{ - count: number - id: string +export interface ItemDetails { + count: number; + id: string; } diff --git a/project/src/models/eft/hideout/IHideoutScavCase.ts b/project/src/models/eft/hideout/IHideoutScavCase.ts index 783cb761..11dba6f3 100644 --- a/project/src/models/eft/hideout/IHideoutScavCase.ts +++ b/project/src/models/eft/hideout/IHideoutScavCase.ts @@ -1,23 +1,20 @@ import { MinMax } from "@spt/models/common/MinMax"; -export interface IHideoutScavCase -{ - _id: string - ProductionTime: number - Requirements: Requirement[] - EndProducts: EndProducts +export interface IHideoutScavCase { + _id: string; + ProductionTime: number; + Requirements: Requirement[]; + EndProducts: EndProducts; } -export interface Requirement -{ - templateId: string - count: number - isFunctional: boolean - type: string +export interface Requirement { + templateId: string; + count: number; + isFunctional: boolean; + type: string; } -export interface EndProducts -{ - Common: MinMax - Rare: MinMax - Superrare: MinMax +export interface EndProducts { + Common: MinMax; + Rare: MinMax; + Superrare: MinMax; } diff --git a/project/src/models/eft/hideout/IHideoutScavCaseStartRequestData.ts b/project/src/models/eft/hideout/IHideoutScavCaseStartRequestData.ts index 4ea6aab8..f7a971d6 100644 --- a/project/src/models/eft/hideout/IHideoutScavCaseStartRequestData.ts +++ b/project/src/models/eft/hideout/IHideoutScavCaseStartRequestData.ts @@ -1,20 +1,17 @@ -export interface IHideoutScavCaseStartRequestData -{ - Action: "HideoutScavCaseProductionStart" - recipeId: string - items: HideoutItem[] - tools: Tool[] - timestamp: number +export interface IHideoutScavCaseStartRequestData { + Action: "HideoutScavCaseProductionStart"; + recipeId: string; + items: HideoutItem[]; + tools: Tool[]; + timestamp: number; } -export interface HideoutItem -{ - id: string - count: number +export interface HideoutItem { + id: string; + count: number; } -export interface Tool -{ - id: string - count: number +export interface Tool { + id: string; + count: number; } diff --git a/project/src/models/eft/hideout/IHideoutSettingsBase.ts b/project/src/models/eft/hideout/IHideoutSettingsBase.ts index cc373d84..8e459391 100644 --- a/project/src/models/eft/hideout/IHideoutSettingsBase.ts +++ b/project/src/models/eft/hideout/IHideoutSettingsBase.ts @@ -1,7 +1,6 @@ -export interface IHideoutSettingsBase -{ - generatorSpeedWithoutFuel: number - generatorFuelFlowRate: number - airFilterUnitFlowRate: number - gpuBoostRate: number +export interface IHideoutSettingsBase { + generatorSpeedWithoutFuel: number; + generatorFuelFlowRate: number; + airFilterUnitFlowRate: number; + gpuBoostRate: number; } diff --git a/project/src/models/eft/hideout/IHideoutSingleProductionStartRequestData.ts b/project/src/models/eft/hideout/IHideoutSingleProductionStartRequestData.ts index 322f9909..989ee32c 100644 --- a/project/src/models/eft/hideout/IHideoutSingleProductionStartRequestData.ts +++ b/project/src/models/eft/hideout/IHideoutSingleProductionStartRequestData.ts @@ -1,14 +1,12 @@ -export interface IHideoutSingleProductionStartRequestData -{ - Action: "HideoutSingleProductionStart" - recipeId: string - items: Item[] - tools: Item[] - timestamp: number +export interface IHideoutSingleProductionStartRequestData { + Action: "HideoutSingleProductionStart"; + recipeId: string; + items: Item[]; + tools: Item[]; + timestamp: number; } -export interface Item -{ - id: string - count: number +export interface Item { + id: string; + count: number; } diff --git a/project/src/models/eft/hideout/IHideoutTakeItemOutRequestData.ts b/project/src/models/eft/hideout/IHideoutTakeItemOutRequestData.ts index ff20af2d..83a740af 100644 --- a/project/src/models/eft/hideout/IHideoutTakeItemOutRequestData.ts +++ b/project/src/models/eft/hideout/IHideoutTakeItemOutRequestData.ts @@ -1,7 +1,6 @@ -export interface IHideoutTakeItemOutRequestData -{ - Action: "HideoutTakeItemsFromAreaSlots" - areaType: number - slots: number[] - timestamp: number +export interface IHideoutTakeItemOutRequestData { + Action: "HideoutTakeItemsFromAreaSlots"; + areaType: number; + slots: number[]; + timestamp: number; } diff --git a/project/src/models/eft/hideout/IHideoutTakeProductionRequestData.ts b/project/src/models/eft/hideout/IHideoutTakeProductionRequestData.ts index 2dd5a74f..a6847ef2 100644 --- a/project/src/models/eft/hideout/IHideoutTakeProductionRequestData.ts +++ b/project/src/models/eft/hideout/IHideoutTakeProductionRequestData.ts @@ -1,6 +1,5 @@ -export interface IHideoutTakeProductionRequestData -{ - Action: "HideoutTakeProduction" - recipeId: string - timestamp: number +export interface IHideoutTakeProductionRequestData { + Action: "HideoutTakeProduction"; + recipeId: string; + timestamp: number; } diff --git a/project/src/models/eft/hideout/IHideoutToggleAreaRequestData.ts b/project/src/models/eft/hideout/IHideoutToggleAreaRequestData.ts index b8a19da0..cdea5134 100644 --- a/project/src/models/eft/hideout/IHideoutToggleAreaRequestData.ts +++ b/project/src/models/eft/hideout/IHideoutToggleAreaRequestData.ts @@ -1,7 +1,6 @@ -export interface IHideoutToggleAreaRequestData -{ - Action: "HideoutToggleArea" - areaType: number - enabled: boolean - timestamp: number +export interface IHideoutToggleAreaRequestData { + Action: "HideoutToggleArea"; + areaType: number; + enabled: boolean; + timestamp: number; } diff --git a/project/src/models/eft/hideout/IHideoutUpgradeCompleteRequestData.ts b/project/src/models/eft/hideout/IHideoutUpgradeCompleteRequestData.ts index 1d5ece72..545311e4 100644 --- a/project/src/models/eft/hideout/IHideoutUpgradeCompleteRequestData.ts +++ b/project/src/models/eft/hideout/IHideoutUpgradeCompleteRequestData.ts @@ -1,6 +1,5 @@ -export interface IHideoutUpgradeCompleteRequestData -{ - Action: "HideoutUpgradeComplete" - areaType: number - timestamp: number +export interface IHideoutUpgradeCompleteRequestData { + Action: "HideoutUpgradeComplete"; + areaType: number; + timestamp: number; } diff --git a/project/src/models/eft/hideout/IHideoutUpgradeRequestData.ts b/project/src/models/eft/hideout/IHideoutUpgradeRequestData.ts index 3850d48e..073fd2e8 100644 --- a/project/src/models/eft/hideout/IHideoutUpgradeRequestData.ts +++ b/project/src/models/eft/hideout/IHideoutUpgradeRequestData.ts @@ -1,13 +1,11 @@ -export interface IHideoutUpgradeRequestData -{ - Action: "HideoutUpgrade" - areaType: number - items: HideoutItem[] - timestamp: number +export interface IHideoutUpgradeRequestData { + Action: "HideoutUpgrade"; + areaType: number; + items: HideoutItem[]; + timestamp: number; } -export interface HideoutItem -{ - count: number - id: string +export interface HideoutItem { + count: number; + id: string; } diff --git a/project/src/models/eft/hideout/IQteData.ts b/project/src/models/eft/hideout/IQteData.ts index b5a4d979..335e7fd9 100644 --- a/project/src/models/eft/hideout/IQteData.ts +++ b/project/src/models/eft/hideout/IQteData.ts @@ -1,145 +1,129 @@ import { Effect } from "@spt/models/eft/health/Effect"; import { BodyPart } from "@spt/models/eft/health/IOffraidHealRequestData"; +import { HideoutAreas } from "@spt/models/enums/HideoutAreas"; +import { SkillTypes } from "@spt/models/enums/SkillTypes"; +import { Traders } from "@spt/models/enums/Traders"; import { QteActivityType } from "@spt/models/enums/hideout/QteActivityType"; import { QteEffectType } from "@spt/models/enums/hideout/QteEffectType"; import { QteResultType } from "@spt/models/enums/hideout/QteResultType"; import { QteRewardType } from "@spt/models/enums/hideout/QteRewardType"; import { QteType } from "@spt/models/enums/hideout/QteType"; import { RequirementType } from "@spt/models/enums/hideout/RequirementType"; -import { HideoutAreas } from "@spt/models/enums/HideoutAreas"; -import { SkillTypes } from "@spt/models/enums/SkillTypes"; -import { Traders } from "@spt/models/enums/Traders"; -export interface IQteData -{ - id: string - type: QteActivityType - area: HideoutAreas - areaLevel: number - quickTimeEvents: IQuickTimeEvent[] +export interface IQteData { + id: string; + type: QteActivityType; + area: HideoutAreas; + areaLevel: number; + quickTimeEvents: IQuickTimeEvent[]; requirements: ( - | IAreaRequirement - | IItemRequirement - | ITraderUnlockRequirement - | ITraderLoyaltyRequirement - | ISkillRequirement - | IResourceRequirement - | IToolRequirement - | IQuestRequirement - | IHealthRequirement - | IBodyPartBuffRequirement - )[] - results: Record + | IAreaRequirement + | IItemRequirement + | ITraderUnlockRequirement + | ITraderLoyaltyRequirement + | ISkillRequirement + | IResourceRequirement + | IToolRequirement + | IQuestRequirement + | IHealthRequirement + | IBodyPartBuffRequirement + )[]; + results: Record; } -export interface IQuickTimeEvent -{ - type: QteType - position: { x: number, y: number } - startDelay: number - endDelay: number - speed: number - successRange: { x: number, y: number } - key: string +export interface IQuickTimeEvent { + type: QteType; + position: { x: number; y: number }; + startDelay: number; + endDelay: number; + speed: number; + successRange: { x: number; y: number }; + key: string; } -export interface IQteRequirement -{ - type: RequirementType +export interface IQteRequirement { + type: RequirementType; } -export interface IQteResult -{ - energy: number - hydration: number - rewardsRange: IQteEffect[] +export interface IQteResult { + energy: number; + hydration: number; + rewardsRange: IQteEffect[]; } -export interface IQteEffect -{ - type: QteRewardType - skillId: number - levelMultipliers: ISkillLevelMultiplier[] - time: number - weight: number - result: QteResultType +export interface IQteEffect { + type: QteRewardType; + skillId: number; + levelMultipliers: ISkillLevelMultiplier[]; + time: number; + weight: number; + result: QteResultType; } -export interface ISkillLevelMultiplier -{ - level: number - multiplier: number +export interface ISkillLevelMultiplier { + level: number; + multiplier: number; } -export interface IAreaRequirement extends IQteRequirement -{ - type: RequirementType.AREA - areaType: HideoutAreas - requiredLevel: number +export interface IAreaRequirement extends IQteRequirement { + type: RequirementType.AREA; + areaType: HideoutAreas; + requiredLevel: number; } -export interface ITraderUnlockRequirement extends IQteRequirement -{ - type: RequirementType.TRADER_UNLOCK - traderId: Traders +export interface ITraderUnlockRequirement extends IQteRequirement { + type: RequirementType.TRADER_UNLOCK; + traderId: Traders; } -export interface ITraderLoyaltyRequirement extends IQteRequirement -{ - type: RequirementType.TRADER_LOYALTY - traderId: Traders - loyaltyLevel: number +export interface ITraderLoyaltyRequirement extends IQteRequirement { + type: RequirementType.TRADER_LOYALTY; + traderId: Traders; + loyaltyLevel: number; } -export interface ISkillRequirement extends IQteRequirement -{ - type: RequirementType.SKILL - skillName: SkillTypes - skillLevel: number +export interface ISkillRequirement extends IQteRequirement { + type: RequirementType.SKILL; + skillName: SkillTypes; + skillLevel: number; } -export interface IResourceRequirement extends IQteRequirement -{ - type: RequirementType.RESOURCE - templateId: string - resource: number +export interface IResourceRequirement extends IQteRequirement { + type: RequirementType.RESOURCE; + templateId: string; + resource: number; } -export interface IItemRequirement extends IQteRequirement -{ - type: RequirementType.ITEM - templateId: string - count: number - isFunctional: boolean - isEncoded: boolean +export interface IItemRequirement extends IQteRequirement { + type: RequirementType.ITEM; + templateId: string; + count: number; + isFunctional: boolean; + isEncoded: boolean; } -export interface IToolRequirement extends IQteRequirement -{ - type: RequirementType.TOOL - templateId: string - count: number - isFunctional: boolean - isEncoded: boolean +export interface IToolRequirement extends IQteRequirement { + type: RequirementType.TOOL; + templateId: string; + count: number; + isFunctional: boolean; + isEncoded: boolean; } -export interface IQuestRequirement extends IQteRequirement -{ - type: RequirementType.QUEST_COMPLETE - questId: string +export interface IQuestRequirement extends IQteRequirement { + type: RequirementType.QUEST_COMPLETE; + questId: string; } -export interface IHealthRequirement extends IQteRequirement -{ - type: RequirementType.HEALTH - energy: number - hydration: number +export interface IHealthRequirement extends IQteRequirement { + type: RequirementType.HEALTH; + energy: number; + hydration: number; } -export interface IBodyPartBuffRequirement extends IQteRequirement -{ - type: RequirementType.BODY_PART_BUFF - effectName: Effect - bodyPart: BodyPart - excluded: boolean +export interface IBodyPartBuffRequirement extends IQteRequirement { + type: RequirementType.BODY_PART_BUFF; + effectName: Effect; + bodyPart: BodyPart; + excluded: boolean; } diff --git a/project/src/models/eft/hideout/IRecordShootingRangePoints.ts b/project/src/models/eft/hideout/IRecordShootingRangePoints.ts index 01d06b60..5bfd2fd1 100644 --- a/project/src/models/eft/hideout/IRecordShootingRangePoints.ts +++ b/project/src/models/eft/hideout/IRecordShootingRangePoints.ts @@ -1,5 +1,4 @@ -export interface IRecordShootingRangePoints -{ - Action: "RecordShootingRangePoints" - points: number +export interface IRecordShootingRangePoints { + Action: "RecordShootingRangePoints"; + points: number; } diff --git a/project/src/models/eft/httpResponse/IGetBodyResponseData.ts b/project/src/models/eft/httpResponse/IGetBodyResponseData.ts index 9b380c88..b5dc5c15 100644 --- a/project/src/models/eft/httpResponse/IGetBodyResponseData.ts +++ b/project/src/models/eft/httpResponse/IGetBodyResponseData.ts @@ -1,6 +1,5 @@ -export interface IGetBodyResponseData -{ - err: number - errmsg: any - (data: Type): Type +export interface IGetBodyResponseData { + err: number; + errmsg: any; + (data: Type): Type; } diff --git a/project/src/models/eft/httpResponse/INullResponseData.ts b/project/src/models/eft/httpResponse/INullResponseData.ts index 7403774b..26dc461f 100644 --- a/project/src/models/eft/httpResponse/INullResponseData.ts +++ b/project/src/models/eft/httpResponse/INullResponseData.ts @@ -1,6 +1,5 @@ -export interface INullResponseData -{ - err: number - errmsg: any - data: undefined +export interface INullResponseData { + err: number; + errmsg: any; + data: undefined; } diff --git a/project/src/models/eft/inRaid/IInsuredItemsData.ts b/project/src/models/eft/inRaid/IInsuredItemsData.ts index 25ec7914..7ef22cee 100644 --- a/project/src/models/eft/inRaid/IInsuredItemsData.ts +++ b/project/src/models/eft/inRaid/IInsuredItemsData.ts @@ -1,8 +1,7 @@ -export interface IInsuredItemsData -{ - id: string - durability?: number - maxDurability?: number - hits?: number - usedInQuest: boolean +export interface IInsuredItemsData { + id: string; + durability?: number; + maxDurability?: number; + hits?: number; + usedInQuest: boolean; } diff --git a/project/src/models/eft/inRaid/IItemDeliveryRequestData.ts b/project/src/models/eft/inRaid/IItemDeliveryRequestData.ts index f94074ae..2726e981 100644 --- a/project/src/models/eft/inRaid/IItemDeliveryRequestData.ts +++ b/project/src/models/eft/inRaid/IItemDeliveryRequestData.ts @@ -1,7 +1,6 @@ import { Item } from "@spt/models/eft/common/tables/IItem"; -export interface IItemDeliveryRequestData -{ - items: Item[] - traderId: string +export interface IItemDeliveryRequestData { + items: Item[]; + traderId: string; } diff --git a/project/src/models/eft/inRaid/IRegisterPlayerRequestData.ts b/project/src/models/eft/inRaid/IRegisterPlayerRequestData.ts index 1daccfe7..e2d9cf16 100644 --- a/project/src/models/eft/inRaid/IRegisterPlayerRequestData.ts +++ b/project/src/models/eft/inRaid/IRegisterPlayerRequestData.ts @@ -1,6 +1,5 @@ -export interface IRegisterPlayerRequestData -{ - crc: number - locationId: string - variantId: number +export interface IRegisterPlayerRequestData { + crc: number; + locationId: string; + variantId: number; } diff --git a/project/src/models/eft/inRaid/IScavSaveRequestData.ts b/project/src/models/eft/inRaid/IScavSaveRequestData.ts index a56f9c95..7ea11bc3 100644 --- a/project/src/models/eft/inRaid/IScavSaveRequestData.ts +++ b/project/src/models/eft/inRaid/IScavSaveRequestData.ts @@ -3,7 +3,6 @@ import { ISyncHealthRequestData } from "@spt/models/eft/health/ISyncHealthReques import { IInsuredItemsData } from "@spt/models/eft/inRaid/IInsuredItemsData"; import { PlayerRaidEndState } from "@spt/models/enums/PlayerRaidEndState"; -export interface IScavSaveRequestData -{ - profile: IPostRaidPmcData +export interface IScavSaveRequestData { + profile: IPostRaidPmcData; } diff --git a/project/src/models/eft/insurance/IGetInsuranceCostRequestData.ts b/project/src/models/eft/insurance/IGetInsuranceCostRequestData.ts index 6a808c8e..0e32e969 100644 --- a/project/src/models/eft/insurance/IGetInsuranceCostRequestData.ts +++ b/project/src/models/eft/insurance/IGetInsuranceCostRequestData.ts @@ -1,5 +1,4 @@ -export interface IGetInsuranceCostRequestData -{ - traders: string[] - items: string[] +export interface IGetInsuranceCostRequestData { + traders: string[]; + items: string[]; } diff --git a/project/src/models/eft/insurance/IInsureRequestData.ts b/project/src/models/eft/insurance/IInsureRequestData.ts index e4c20536..57f98808 100644 --- a/project/src/models/eft/insurance/IInsureRequestData.ts +++ b/project/src/models/eft/insurance/IInsureRequestData.ts @@ -1,8 +1,7 @@ import { IBaseInteractionRequestData } from "@spt/models/eft/common/request/IBaseInteractionRequestData"; -export interface IInsureRequestData extends IBaseInteractionRequestData -{ - Action: "Insure" - tid: string - items: string[] +export interface IInsureRequestData extends IBaseInteractionRequestData { + Action: "Insure"; + tid: string; + items: string[]; } diff --git a/project/src/models/eft/inventory/IAddItemDirectRequest.ts b/project/src/models/eft/inventory/IAddItemDirectRequest.ts index 9d400c40..6d4328bf 100644 --- a/project/src/models/eft/inventory/IAddItemDirectRequest.ts +++ b/project/src/models/eft/inventory/IAddItemDirectRequest.ts @@ -1,10 +1,9 @@ import { Item } from "@spt/models/eft/common/tables/IItem"; -export interface IAddItemDirectRequest -{ +export interface IAddItemDirectRequest { /** Item and child mods to add to player inventory */ - itemWithModsToAdd: Item[] - foundInRaid: boolean - callback: (buyCount: number) => void - useSortingTable: boolean + itemWithModsToAdd: Item[]; + foundInRaid: boolean; + callback: (buyCount: number) => void; + useSortingTable: boolean; } diff --git a/project/src/models/eft/inventory/IAddItemRequestData.ts b/project/src/models/eft/inventory/IAddItemRequestData.ts index 4652d1c3..90f4534b 100644 --- a/project/src/models/eft/inventory/IAddItemRequestData.ts +++ b/project/src/models/eft/inventory/IAddItemRequestData.ts @@ -1,13 +1,11 @@ -export interface IAddItemRequestData -{ +export interface IAddItemRequestData { /** Trader id */ - tid: string - items: AddItem[] + tid: string; + items: AddItem[]; } -export interface AddItem -{ - count: number - sptIsPreset?: boolean - item_id: string +export interface AddItem { + count: number; + sptIsPreset?: boolean; + item_id: string; } diff --git a/project/src/models/eft/inventory/IAddItemTempObject.ts b/project/src/models/eft/inventory/IAddItemTempObject.ts index df788934..08cf8c81 100644 --- a/project/src/models/eft/inventory/IAddItemTempObject.ts +++ b/project/src/models/eft/inventory/IAddItemTempObject.ts @@ -1,11 +1,10 @@ import { Item, Location } from "@spt/models/eft/common/tables/IItem"; -export interface IAddItemTempObject -{ - itemRef: Item - count: number - isPreset: boolean - location?: Location +export interface IAddItemTempObject { + itemRef: Item; + count: number; + isPreset: boolean; + location?: Location; // Container item will be placed in - stash or sorting table - containerId?: string + containerId?: string; } diff --git a/project/src/models/eft/inventory/IAddItemsDirectRequest.ts b/project/src/models/eft/inventory/IAddItemsDirectRequest.ts index 68d46314..8d863dd9 100644 --- a/project/src/models/eft/inventory/IAddItemsDirectRequest.ts +++ b/project/src/models/eft/inventory/IAddItemsDirectRequest.ts @@ -1,12 +1,11 @@ import { Item } from "@spt/models/eft/common/tables/IItem"; -export interface IAddItemsDirectRequest -{ +export interface IAddItemsDirectRequest { /** Item and child mods to add to player inventory */ - itemsWithModsToAdd: Item[][] - foundInRaid: boolean + itemsWithModsToAdd: Item[][]; + foundInRaid: boolean; /** Runs after EACH item with children is added */ - callback?: (buyCount: number) => void + callback?: (buyCount: number) => void; /** Should sorting table be used when no space found in stash */ - useSortingTable: boolean + useSortingTable: boolean; } diff --git a/project/src/models/eft/inventory/IInventoryAddRequestData.ts b/project/src/models/eft/inventory/IInventoryAddRequestData.ts index c90d8e71..e4b3c38c 100644 --- a/project/src/models/eft/inventory/IInventoryAddRequestData.ts +++ b/project/src/models/eft/inventory/IInventoryAddRequestData.ts @@ -1,11 +1,7 @@ -import { - Container, - IInventoryBaseActionRequestData, -} from "@spt/models/eft/inventory/IInventoryBaseActionRequestData"; +import { Container, IInventoryBaseActionRequestData } from "@spt/models/eft/inventory/IInventoryBaseActionRequestData"; -export interface IInventoryAddRequestData extends IInventoryBaseActionRequestData -{ - Action: "Add" - item: string - container: Container +export interface IInventoryAddRequestData extends IInventoryBaseActionRequestData { + Action: "Add"; + item: string; + container: Container; } diff --git a/project/src/models/eft/inventory/IInventoryBaseActionRequestData.ts b/project/src/models/eft/inventory/IInventoryBaseActionRequestData.ts index 7d55529a..c221174a 100644 --- a/project/src/models/eft/inventory/IInventoryBaseActionRequestData.ts +++ b/project/src/models/eft/inventory/IInventoryBaseActionRequestData.ts @@ -1,37 +1,32 @@ import { IBaseInteractionRequestData } from "@spt/models/eft/common/request/IBaseInteractionRequestData"; -export interface IInventoryBaseActionRequestData extends IBaseInteractionRequestData -{} +export interface IInventoryBaseActionRequestData extends IBaseInteractionRequestData {} -export interface To -{ - id: string - container: string - location?: ToLocation | number // Hack - isSearched?: boolean +export interface To { + id: string; + container: string; + location?: ToLocation | number; // Hack + isSearched?: boolean; } -export interface ToLocation -{ - x: number - y: number - r: string - rotation?: string - isSearched: boolean +export interface ToLocation { + x: number; + y: number; + r: string; + rotation?: string; + isSearched: boolean; } -export interface Container -{ - id: string - container: string - location?: Location | number // Hack - BSG data object shows it as Location only +export interface Container { + id: string; + container: string; + location?: Location | number; // Hack - BSG data object shows it as Location only } -export interface Location -{ - x: number - y: number - r: string - rotation?: string - isSearched: boolean +export interface Location { + x: number; + y: number; + r: string; + rotation?: string; + isSearched: boolean; } diff --git a/project/src/models/eft/inventory/IInventoryBindRequestData.ts b/project/src/models/eft/inventory/IInventoryBindRequestData.ts index b2bba814..0762e15b 100644 --- a/project/src/models/eft/inventory/IInventoryBindRequestData.ts +++ b/project/src/models/eft/inventory/IInventoryBindRequestData.ts @@ -1,8 +1,7 @@ import { IInventoryBaseActionRequestData } from "@spt/models/eft/inventory/IInventoryBaseActionRequestData"; -export interface IInventoryBindRequestData extends IInventoryBaseActionRequestData -{ - Action: "Bind" - item: string - index: number +export interface IInventoryBindRequestData extends IInventoryBaseActionRequestData { + Action: "Bind"; + item: string; + index: number; } diff --git a/project/src/models/eft/inventory/IInventoryCreateMarkerRequestData.ts b/project/src/models/eft/inventory/IInventoryCreateMarkerRequestData.ts index a1e6899e..d7e19178 100644 --- a/project/src/models/eft/inventory/IInventoryCreateMarkerRequestData.ts +++ b/project/src/models/eft/inventory/IInventoryCreateMarkerRequestData.ts @@ -1,16 +1,14 @@ import { IInventoryBaseActionRequestData } from "@spt/models/eft/inventory/IInventoryBaseActionRequestData"; -export interface IInventoryCreateMarkerRequestData extends IInventoryBaseActionRequestData -{ - Action: "CreateMapMarker" - item: string - mapMarker: MapMarker +export interface IInventoryCreateMarkerRequestData extends IInventoryBaseActionRequestData { + Action: "CreateMapMarker"; + item: string; + mapMarker: MapMarker; } -export interface MapMarker -{ - Type: string - X: number - Y: number - Note: string +export interface MapMarker { + Type: string; + X: number; + Y: number; + Note: string; } diff --git a/project/src/models/eft/inventory/IInventoryDeleteMarkerRequestData.ts b/project/src/models/eft/inventory/IInventoryDeleteMarkerRequestData.ts index 9395725e..f8943849 100644 --- a/project/src/models/eft/inventory/IInventoryDeleteMarkerRequestData.ts +++ b/project/src/models/eft/inventory/IInventoryDeleteMarkerRequestData.ts @@ -1,9 +1,8 @@ import { IInventoryBaseActionRequestData } from "@spt/models/eft/inventory/IInventoryBaseActionRequestData"; -export interface IInventoryDeleteMarkerRequestData extends IInventoryBaseActionRequestData -{ - Action: "DeleteMapMarker" - item: string - X: number - Y: number +export interface IInventoryDeleteMarkerRequestData extends IInventoryBaseActionRequestData { + Action: "DeleteMapMarker"; + item: string; + X: number; + Y: number; } diff --git a/project/src/models/eft/inventory/IInventoryEditMarkerRequestData.ts b/project/src/models/eft/inventory/IInventoryEditMarkerRequestData.ts index 42ac492e..676f6df1 100644 --- a/project/src/models/eft/inventory/IInventoryEditMarkerRequestData.ts +++ b/project/src/models/eft/inventory/IInventoryEditMarkerRequestData.ts @@ -1,18 +1,16 @@ import { IInventoryBaseActionRequestData } from "@spt/models/eft/inventory/IInventoryBaseActionRequestData"; -export interface IInventoryEditMarkerRequestData extends IInventoryBaseActionRequestData -{ - Action: "EditMapMarker" - item: string - X: number - Y: number - mapMarker: MapMarker +export interface IInventoryEditMarkerRequestData extends IInventoryBaseActionRequestData { + Action: "EditMapMarker"; + item: string; + X: number; + Y: number; + mapMarker: MapMarker; } -export interface MapMarker -{ - Type: string - X: number - Y: number - Note: string +export interface MapMarker { + Type: string; + X: number; + Y: number; + Note: string; } diff --git a/project/src/models/eft/inventory/IInventoryExamineRequestData.ts b/project/src/models/eft/inventory/IInventoryExamineRequestData.ts index 7ae9c1d7..9b393506 100644 --- a/project/src/models/eft/inventory/IInventoryExamineRequestData.ts +++ b/project/src/models/eft/inventory/IInventoryExamineRequestData.ts @@ -1,9 +1,8 @@ import { OwnerInfo } from "@spt/models/eft/common/request/IBaseInteractionRequestData"; import { IInventoryBaseActionRequestData } from "@spt/models/eft/inventory/IInventoryBaseActionRequestData"; -export interface IInventoryExamineRequestData extends IInventoryBaseActionRequestData -{ - Action: "Examine" - item: string - fromOwner: OwnerInfo +export interface IInventoryExamineRequestData extends IInventoryBaseActionRequestData { + Action: "Examine"; + item: string; + fromOwner: OwnerInfo; } diff --git a/project/src/models/eft/inventory/IInventoryFoldRequestData.ts b/project/src/models/eft/inventory/IInventoryFoldRequestData.ts index 84c29d50..71eb7bf5 100644 --- a/project/src/models/eft/inventory/IInventoryFoldRequestData.ts +++ b/project/src/models/eft/inventory/IInventoryFoldRequestData.ts @@ -1,8 +1,7 @@ import { IInventoryBaseActionRequestData } from "@spt/models/eft/inventory/IInventoryBaseActionRequestData"; -export interface IInventoryFoldRequestData extends IInventoryBaseActionRequestData -{ - Action: "Fold" - item: string - value: boolean +export interface IInventoryFoldRequestData extends IInventoryBaseActionRequestData { + Action: "Fold"; + item: string; + value: boolean; } diff --git a/project/src/models/eft/inventory/IInventoryMergeRequestData.ts b/project/src/models/eft/inventory/IInventoryMergeRequestData.ts index cbd32774..4e620ca5 100644 --- a/project/src/models/eft/inventory/IInventoryMergeRequestData.ts +++ b/project/src/models/eft/inventory/IInventoryMergeRequestData.ts @@ -1,8 +1,7 @@ import { IInventoryBaseActionRequestData } from "@spt/models/eft/inventory/IInventoryBaseActionRequestData"; -export interface IInventoryMergeRequestData extends IInventoryBaseActionRequestData -{ - Action: "Merge" - item: string - with: string +export interface IInventoryMergeRequestData extends IInventoryBaseActionRequestData { + Action: "Merge"; + item: string; + with: string; } diff --git a/project/src/models/eft/inventory/IInventoryMoveRequestData.ts b/project/src/models/eft/inventory/IInventoryMoveRequestData.ts index 65ad3cec..8d594673 100644 --- a/project/src/models/eft/inventory/IInventoryMoveRequestData.ts +++ b/project/src/models/eft/inventory/IInventoryMoveRequestData.ts @@ -1,8 +1,7 @@ import { IInventoryBaseActionRequestData, To } from "@spt/models/eft/inventory/IInventoryBaseActionRequestData"; -export interface IInventoryMoveRequestData extends IInventoryBaseActionRequestData -{ - Action: "Move" - item: string - to: To +export interface IInventoryMoveRequestData extends IInventoryBaseActionRequestData { + Action: "Move"; + item: string; + to: To; } diff --git a/project/src/models/eft/inventory/IInventoryReadEncyclopediaRequestData.ts b/project/src/models/eft/inventory/IInventoryReadEncyclopediaRequestData.ts index de473b5a..e402affc 100644 --- a/project/src/models/eft/inventory/IInventoryReadEncyclopediaRequestData.ts +++ b/project/src/models/eft/inventory/IInventoryReadEncyclopediaRequestData.ts @@ -1,7 +1,6 @@ import { IInventoryBaseActionRequestData } from "@spt/models/eft/inventory/IInventoryBaseActionRequestData"; -export interface IInventoryReadEncyclopediaRequestData extends IInventoryBaseActionRequestData -{ - Action: "ReadEncyclopedia" - ids: string[] +export interface IInventoryReadEncyclopediaRequestData extends IInventoryBaseActionRequestData { + Action: "ReadEncyclopedia"; + ids: string[]; } diff --git a/project/src/models/eft/inventory/IInventoryRemoveRequestData.ts b/project/src/models/eft/inventory/IInventoryRemoveRequestData.ts index 0aa68d22..a87e057f 100644 --- a/project/src/models/eft/inventory/IInventoryRemoveRequestData.ts +++ b/project/src/models/eft/inventory/IInventoryRemoveRequestData.ts @@ -1,7 +1,6 @@ import { IInventoryBaseActionRequestData } from "@spt/models/eft/inventory/IInventoryBaseActionRequestData"; -export interface IInventoryRemoveRequestData extends IInventoryBaseActionRequestData -{ - Action: "Remove" - item: string +export interface IInventoryRemoveRequestData extends IInventoryBaseActionRequestData { + Action: "Remove"; + item: string; } diff --git a/project/src/models/eft/inventory/IInventorySortRequestData.ts b/project/src/models/eft/inventory/IInventorySortRequestData.ts index 4912cd60..1517fb32 100644 --- a/project/src/models/eft/inventory/IInventorySortRequestData.ts +++ b/project/src/models/eft/inventory/IInventorySortRequestData.ts @@ -1,26 +1,23 @@ import { Upd } from "@spt/models/eft/common/tables/IItem"; import { IInventoryBaseActionRequestData } from "@spt/models/eft/inventory/IInventoryBaseActionRequestData"; -export interface IInventorySortRequestData extends IInventoryBaseActionRequestData -{ - Action: "ApplyInventoryChanges" - changedItems: ChangedItem[] +export interface IInventorySortRequestData extends IInventoryBaseActionRequestData { + Action: "ApplyInventoryChanges"; + changedItems: ChangedItem[]; } -export interface ChangedItem -{ - _id: string - _tpl: string - parentId: string - slotId: string - location: Location - upd: Upd +export interface ChangedItem { + _id: string; + _tpl: string; + parentId: string; + slotId: string; + location: Location; + upd: Upd; } -export interface Location -{ - x: number - y: number - r: string - isSearched: boolean +export interface Location { + x: number; + y: number; + r: string; + isSearched: boolean; } diff --git a/project/src/models/eft/inventory/IInventorySplitRequestData.ts b/project/src/models/eft/inventory/IInventorySplitRequestData.ts index 86a7b4aa..58259004 100644 --- a/project/src/models/eft/inventory/IInventorySplitRequestData.ts +++ b/project/src/models/eft/inventory/IInventorySplitRequestData.ts @@ -1,16 +1,12 @@ -import { - Container, - IInventoryBaseActionRequestData, -} from "@spt/models/eft/inventory/IInventoryBaseActionRequestData"; +import { Container, IInventoryBaseActionRequestData } from "@spt/models/eft/inventory/IInventoryBaseActionRequestData"; -export interface IInventorySplitRequestData extends IInventoryBaseActionRequestData -{ - Action: "Split" +export interface IInventorySplitRequestData extends IInventoryBaseActionRequestData { + Action: "Split"; /** Id of item to split */ - splitItem: string + splitItem: string; /** Id of new item stack */ - newItem: string + newItem: string; /** Destination new item will be placed in */ - container: Container - count: number + container: Container; + count: number; } diff --git a/project/src/models/eft/inventory/IInventorySwapRequestData.ts b/project/src/models/eft/inventory/IInventorySwapRequestData.ts index a83fc397..6b824e08 100644 --- a/project/src/models/eft/inventory/IInventorySwapRequestData.ts +++ b/project/src/models/eft/inventory/IInventorySwapRequestData.ts @@ -1,13 +1,12 @@ import { OwnerInfo } from "@spt/models/eft/common/request/IBaseInteractionRequestData"; import { IInventoryBaseActionRequestData, To } from "@spt/models/eft/inventory/IInventoryBaseActionRequestData"; -export interface IInventorySwapRequestData extends IInventoryBaseActionRequestData -{ - Action: "Swap" - item: string - to: To - item2: string - to2: To - fromOwner2: OwnerInfo - toOwner2: OwnerInfo +export interface IInventorySwapRequestData extends IInventoryBaseActionRequestData { + Action: "Swap"; + item: string; + to: To; + item2: string; + to2: To; + fromOwner2: OwnerInfo; + toOwner2: OwnerInfo; } diff --git a/project/src/models/eft/inventory/IInventoryTagRequestData.ts b/project/src/models/eft/inventory/IInventoryTagRequestData.ts index 531e1aac..1df9c207 100644 --- a/project/src/models/eft/inventory/IInventoryTagRequestData.ts +++ b/project/src/models/eft/inventory/IInventoryTagRequestData.ts @@ -1,9 +1,8 @@ import { IInventoryBaseActionRequestData } from "@spt/models/eft/inventory/IInventoryBaseActionRequestData"; -export interface IInventoryTagRequestData extends IInventoryBaseActionRequestData -{ - Action: "Tag" - item: string - TagName: string - TagColor: number +export interface IInventoryTagRequestData extends IInventoryBaseActionRequestData { + Action: "Tag"; + item: string; + TagName: string; + TagColor: number; } diff --git a/project/src/models/eft/inventory/IInventoryToggleRequestData.ts b/project/src/models/eft/inventory/IInventoryToggleRequestData.ts index 8040bf0c..2baed7d0 100644 --- a/project/src/models/eft/inventory/IInventoryToggleRequestData.ts +++ b/project/src/models/eft/inventory/IInventoryToggleRequestData.ts @@ -1,8 +1,7 @@ import { IInventoryBaseActionRequestData } from "@spt/models/eft/inventory/IInventoryBaseActionRequestData"; -export interface IInventoryToggleRequestData extends IInventoryBaseActionRequestData -{ - Action: "Toggle" - item: string - value: boolean +export interface IInventoryToggleRequestData extends IInventoryBaseActionRequestData { + Action: "Toggle"; + item: string; + value: boolean; } diff --git a/project/src/models/eft/inventory/IInventoryTransferRequestData.ts b/project/src/models/eft/inventory/IInventoryTransferRequestData.ts index 848bf14f..77332e97 100644 --- a/project/src/models/eft/inventory/IInventoryTransferRequestData.ts +++ b/project/src/models/eft/inventory/IInventoryTransferRequestData.ts @@ -1,9 +1,8 @@ import { IInventoryBaseActionRequestData } from "@spt/models/eft/inventory/IInventoryBaseActionRequestData"; -export interface IInventoryTransferRequestData extends IInventoryBaseActionRequestData -{ - Action: "Transfer" - item: string - with: string - count: number +export interface IInventoryTransferRequestData extends IInventoryBaseActionRequestData { + Action: "Transfer"; + item: string; + with: string; + count: number; } diff --git a/project/src/models/eft/inventory/IInventoryUnbindRequestData.ts b/project/src/models/eft/inventory/IInventoryUnbindRequestData.ts index d9056d5a..8084c597 100644 --- a/project/src/models/eft/inventory/IInventoryUnbindRequestData.ts +++ b/project/src/models/eft/inventory/IInventoryUnbindRequestData.ts @@ -1,8 +1,7 @@ import { IInventoryBaseActionRequestData } from "@spt/models/eft/inventory/IInventoryBaseActionRequestData"; -export interface IInventoryUnbindRequestData extends IInventoryBaseActionRequestData -{ - Action: "Unbind" - item: string - index: number +export interface IInventoryUnbindRequestData extends IInventoryBaseActionRequestData { + Action: "Unbind"; + item: string; + index: number; } diff --git a/project/src/models/eft/inventory/IOpenRandomLootContainerRequestData.ts b/project/src/models/eft/inventory/IOpenRandomLootContainerRequestData.ts index 50d79805..884bcc35 100644 --- a/project/src/models/eft/inventory/IOpenRandomLootContainerRequestData.ts +++ b/project/src/models/eft/inventory/IOpenRandomLootContainerRequestData.ts @@ -1,15 +1,13 @@ import { IInventoryBaseActionRequestData } from "@spt/models/eft/inventory/IInventoryBaseActionRequestData"; -export interface IOpenRandomLootContainerRequestData extends IInventoryBaseActionRequestData -{ - Action: "OpenRandomLootContainer" +export interface IOpenRandomLootContainerRequestData extends IInventoryBaseActionRequestData { + Action: "OpenRandomLootContainer"; /** Container item id being opened */ - item: string - to: To[] + item: string; + to: To[]; } -export interface To -{ +export interface To { /** Player character (pmc/scav) id items will be sent to */ - id: string + id: string; } diff --git a/project/src/models/eft/inventory/IRedeemProfileRequestData.ts b/project/src/models/eft/inventory/IRedeemProfileRequestData.ts index 821f1d33..e4b17327 100644 --- a/project/src/models/eft/inventory/IRedeemProfileRequestData.ts +++ b/project/src/models/eft/inventory/IRedeemProfileRequestData.ts @@ -1,13 +1,11 @@ import { IInventoryBaseActionRequestData } from "@spt/models/eft/inventory/IInventoryBaseActionRequestData"; -export interface IRedeemProfileRequestData extends IInventoryBaseActionRequestData -{ - Action: "RedeemProfileReward" - events: IRedeemProfileRequestEvent[] +export interface IRedeemProfileRequestData extends IInventoryBaseActionRequestData { + Action: "RedeemProfileReward"; + events: IRedeemProfileRequestEvent[]; } -export interface IRedeemProfileRequestEvent -{ - MessageId: string - EventId: string +export interface IRedeemProfileRequestEvent { + MessageId: string; + EventId: string; } diff --git a/project/src/models/eft/inventory/ISetFavoriteItems.ts b/project/src/models/eft/inventory/ISetFavoriteItems.ts index 4f5a113e..878a686f 100644 --- a/project/src/models/eft/inventory/ISetFavoriteItems.ts +++ b/project/src/models/eft/inventory/ISetFavoriteItems.ts @@ -1,8 +1,7 @@ import { IInventoryBaseActionRequestData } from "@spt/models/eft/inventory/IInventoryBaseActionRequestData"; -export interface ISetFavoriteItems extends IInventoryBaseActionRequestData -{ - Action: "SetFavoriteItems" - items: any[] - timestamp: number +export interface ISetFavoriteItems extends IInventoryBaseActionRequestData { + Action: "SetFavoriteItems"; + items: any[]; + timestamp: number; } diff --git a/project/src/models/eft/itemEvent/IEmptyItemEventRouterResponse.ts b/project/src/models/eft/itemEvent/IEmptyItemEventRouterResponse.ts index 95eb9024..56e63601 100644 --- a/project/src/models/eft/itemEvent/IEmptyItemEventRouterResponse.ts +++ b/project/src/models/eft/itemEvent/IEmptyItemEventRouterResponse.ts @@ -1,6 +1,5 @@ import { IItemEventRouterBase } from "@spt/models/eft/itemEvent/IItemEventRouterBase"; -export interface IEmptyItemEventRouterResponse extends IItemEventRouterBase -{ - profileChanges: "" +export interface IEmptyItemEventRouterResponse extends IItemEventRouterBase { + profileChanges: ""; } diff --git a/project/src/models/eft/itemEvent/IItemEventRouterBase.ts b/project/src/models/eft/itemEvent/IItemEventRouterBase.ts index 1fee1c53..0c8220b4 100644 --- a/project/src/models/eft/itemEvent/IItemEventRouterBase.ts +++ b/project/src/models/eft/itemEvent/IItemEventRouterBase.ts @@ -5,105 +5,94 @@ import { IPmcDataRepeatableQuest } from "@spt/models/eft/common/tables/IRepeatab import { IRagfairOffer } from "@spt/models/eft/ragfair/IRagfairOffer"; import { EquipmentBuildType } from "@spt/models/enums/EquipmentBuildType"; -export interface IItemEventRouterBase -{ - warnings: Warning[] - profileChanges: TProfileChanges | "" +export interface IItemEventRouterBase { + warnings: Warning[]; + profileChanges: TProfileChanges | ""; } export type TProfileChanges = Record; -export interface Warning -{ - index: number - errmsg: string - code?: string - data?: any +export interface Warning { + index: number; + errmsg: string; + code?: string; + data?: any; } -export interface ProfileChange -{ - _id: string - experience: number - quests: IQuest[] - ragFairOffers: IRagfairOffer[] - weaponBuilds: IWeaponBuildChange[] - equipmentBuilds: IEquipmentBuildChange[] - items: ItemChanges - production: Record +export interface ProfileChange { + _id: string; + experience: number; + quests: IQuest[]; + ragFairOffers: IRagfairOffer[]; + weaponBuilds: IWeaponBuildChange[]; + equipmentBuilds: IEquipmentBuildChange[]; + items: ItemChanges; + production: Record; /** Hideout area improvement id */ - improvements: Record - skills: Skills - health: Health - traderRelations: Record - repeatableQuests?: IPmcDataRepeatableQuest[] - recipeUnlocked: Record - changedHideoutStashes?: Record - questsStatus: IQuestStatus[] + improvements: Record; + skills: Skills; + health: Health; + traderRelations: Record; + repeatableQuests?: IPmcDataRepeatableQuest[]; + recipeUnlocked: Record; + changedHideoutStashes?: Record; + questsStatus: IQuestStatus[]; } -export interface IHideoutStashItem -{ - Id: string - Tpl: string +export interface IHideoutStashItem { + Id: string; + Tpl: string; } -export interface IWeaponBuildChange -{ - id: string - name: string - root: string - items: Item[] +export interface IWeaponBuildChange { + id: string; + name: string; + root: string; + items: Item[]; } -export interface IEquipmentBuildChange -{ - id: string - name: string - root: string - items: Item[] - type: string - fastpanel: any[] - buildType: EquipmentBuildType +export interface IEquipmentBuildChange { + id: string; + name: string; + root: string; + items: Item[]; + type: string; + fastpanel: any[]; + buildType: EquipmentBuildType; } -export interface ItemChanges -{ - new: Product[] - change: Product[] - del: Product[] // Only needs _id property +export interface ItemChanges { + new: Product[]; + change: Product[]; + del: Product[]; // Only needs _id property } -export interface Improvement -{ - completed: boolean - improveCompleteTimestamp: number +export interface Improvement { + completed: boolean; + improveCompleteTimestamp: number; } /** Related to TraderInfo */ -export interface TraderData -{ - salesSum: number - standing: number - loyalty: number - unlocked: boolean - disabled: boolean +export interface TraderData { + salesSum: number; + standing: number; + loyalty: number; + unlocked: boolean; + disabled: boolean; } -export interface Product -{ - _id: string - _tpl?: string - parentId?: string - slotId?: string - location?: ItemChangeLocation - upd?: Upd +export interface Product { + _id: string; + _tpl?: string; + parentId?: string; + slotId?: string; + location?: ItemChangeLocation; + upd?: Upd; } -export interface ItemChangeLocation -{ - x: number - y: number - r: number - isSearched?: boolean +export interface ItemChangeLocation { + x: number; + y: number; + r: number; + isSearched?: boolean; } diff --git a/project/src/models/eft/itemEvent/IItemEventRouterRequest.ts b/project/src/models/eft/itemEvent/IItemEventRouterRequest.ts index f8b41398..5da80586 100644 --- a/project/src/models/eft/itemEvent/IItemEventRouterRequest.ts +++ b/project/src/models/eft/itemEvent/IItemEventRouterRequest.ts @@ -1,28 +1,24 @@ -export interface IItemEventRouterRequest -{ - data: Daum[] - tm: number - reload: number +export interface IItemEventRouterRequest { + data: Daum[]; + tm: number; + reload: number; } -export interface Daum -{ - Action: string - item: string - to: To +export interface Daum { + Action: string; + item: string; + to: To; } -export interface To -{ - id: string - container: string - location?: Location +export interface To { + id: string; + container: string; + location?: Location; } -export interface Location -{ - x: number - y: number - r: string - isSearched: boolean +export interface Location { + x: number; + y: number; + r: string; + isSearched: boolean; } diff --git a/project/src/models/eft/itemEvent/IItemEventRouterResponse.ts b/project/src/models/eft/itemEvent/IItemEventRouterResponse.ts index 1fe69d91..ad9829d7 100644 --- a/project/src/models/eft/itemEvent/IItemEventRouterResponse.ts +++ b/project/src/models/eft/itemEvent/IItemEventRouterResponse.ts @@ -1,5 +1,4 @@ import { IItemEventRouterBase } from "@spt/models/eft/itemEvent/IItemEventRouterBase"; /** An object sent back to the game client that contains alterations the client must make to ensure server/client are in sync */ -export interface IItemEventRouterResponse extends IItemEventRouterBase -{} +export interface IItemEventRouterResponse extends IItemEventRouterBase {} diff --git a/project/src/models/eft/launcher/IChangeRequestData.ts b/project/src/models/eft/launcher/IChangeRequestData.ts index ba53a6a8..a77be86d 100644 --- a/project/src/models/eft/launcher/IChangeRequestData.ts +++ b/project/src/models/eft/launcher/IChangeRequestData.ts @@ -1,6 +1,5 @@ import { ILoginRequestData } from "@spt/models/eft/launcher/ILoginRequestData"; -export interface IChangeRequestData extends ILoginRequestData -{ - change: string +export interface IChangeRequestData extends ILoginRequestData { + change: string; } diff --git a/project/src/models/eft/launcher/IGetMiniProfileRequestData.ts b/project/src/models/eft/launcher/IGetMiniProfileRequestData.ts index 6b6432df..a14c7c93 100644 --- a/project/src/models/eft/launcher/IGetMiniProfileRequestData.ts +++ b/project/src/models/eft/launcher/IGetMiniProfileRequestData.ts @@ -1,5 +1,4 @@ -export interface IGetMiniProfileRequestData -{ - username: string - password: string +export interface IGetMiniProfileRequestData { + username: string; + password: string; } diff --git a/project/src/models/eft/launcher/ILoginRequestData.ts b/project/src/models/eft/launcher/ILoginRequestData.ts index 1e819064..e9658131 100644 --- a/project/src/models/eft/launcher/ILoginRequestData.ts +++ b/project/src/models/eft/launcher/ILoginRequestData.ts @@ -1,5 +1,4 @@ -export interface ILoginRequestData -{ - username: string - password: string +export interface ILoginRequestData { + username: string; + password: string; } diff --git a/project/src/models/eft/launcher/IMiniProfile.ts b/project/src/models/eft/launcher/IMiniProfile.ts index 3ab8297d..f9a0a2b6 100644 --- a/project/src/models/eft/launcher/IMiniProfile.ts +++ b/project/src/models/eft/launcher/IMiniProfile.ts @@ -1,16 +1,15 @@ -import { Spt } from "../profile/ISptProfile" +import { Spt } from "../profile/ISptProfile"; -export interface IMiniProfile -{ - username: string - nickname: string - side: string - currlvl: number - currexp: number - prevexp: number - nextlvl: number - maxlvl: number - edition: string - profileId: string - sptData: Spt +export interface IMiniProfile { + username: string; + nickname: string; + side: string; + currlvl: number; + currexp: number; + prevexp: number; + nextlvl: number; + maxlvl: number; + edition: string; + profileId: string; + sptData: Spt; } diff --git a/project/src/models/eft/launcher/IRegisterData.ts b/project/src/models/eft/launcher/IRegisterData.ts index 4d6ccd06..cbae9213 100644 --- a/project/src/models/eft/launcher/IRegisterData.ts +++ b/project/src/models/eft/launcher/IRegisterData.ts @@ -1,6 +1,5 @@ import { ILoginRequestData } from "@spt/models/eft/launcher/ILoginRequestData"; -export interface IRegisterData extends ILoginRequestData -{ - edition: string +export interface IRegisterData extends ILoginRequestData { + edition: string; } diff --git a/project/src/models/eft/location/IAirdropLootResult.ts b/project/src/models/eft/location/IAirdropLootResult.ts index bce60e2f..7c626cde 100644 --- a/project/src/models/eft/location/IAirdropLootResult.ts +++ b/project/src/models/eft/location/IAirdropLootResult.ts @@ -1,7 +1,6 @@ import { LootItem } from "@spt/models/spt/services/LootItem"; -export interface IAirdropLootResult -{ - dropType: string - loot: LootItem[] +export interface IAirdropLootResult { + dropType: string; + loot: LootItem[]; } diff --git a/project/src/models/eft/location/IGetAirdropLootResponse.ts b/project/src/models/eft/location/IGetAirdropLootResponse.ts index 1e8f1ae9..dc5662d5 100644 --- a/project/src/models/eft/location/IGetAirdropLootResponse.ts +++ b/project/src/models/eft/location/IGetAirdropLootResponse.ts @@ -1,9 +1,8 @@ import { Item } from "@spt/models/eft/common/tables/IItem"; import { AirdropTypeEnum } from "@spt/models/enums/AirdropType"; -export interface IGetAirdropLootResponse -{ +export interface IGetAirdropLootResponse { // The type of airdrop - icon: AirdropTypeEnum - container: Item[] + icon: AirdropTypeEnum; + container: Item[]; } diff --git a/project/src/models/eft/location/IGetLocationRequestData.ts b/project/src/models/eft/location/IGetLocationRequestData.ts index 0eed8c0f..04e84d99 100644 --- a/project/src/models/eft/location/IGetLocationRequestData.ts +++ b/project/src/models/eft/location/IGetLocationRequestData.ts @@ -1,6 +1,5 @@ -export interface IGetLocationRequestData -{ - crc: number - locationId: string - variantId: number +export interface IGetLocationRequestData { + crc: number; + locationId: string; + variantId: number; } diff --git a/project/src/models/eft/match/IEndLocalRaidRequestData.ts b/project/src/models/eft/match/IEndLocalRaidRequestData.ts index f3995953..9c81c3f8 100644 --- a/project/src/models/eft/match/IEndLocalRaidRequestData.ts +++ b/project/src/models/eft/match/IEndLocalRaidRequestData.ts @@ -2,26 +2,24 @@ import { ExitStatus } from "@spt/models/enums/ExitStatis"; import { IPmcData } from "../common/IPmcData"; import { Item } from "../common/tables/IItem"; -export interface IEndLocalRaidRequestData -{ +export interface IEndLocalRaidRequestData { /** ID of server player just left */ - serverId: string - results: IEndRaidResult + serverId: string; + results: IEndRaidResult; /** Insured items left in raid by player */ - lostInsuredItems: Item[] + lostInsuredItems: Item[]; /** Items sent via traders to player, keyed to service e.g. BTRTransferStash */ - transferItems: Record + transferItems: Record; } -export interface IEndRaidResult -{ - profile: IPmcData - result: string - ExitStatus: ExitStatus - killerId: string - killerAid: string - exitName: string - inSession: boolean - favorite: boolean - playTime: number +export interface IEndRaidResult { + profile: IPmcData; + result: string; + ExitStatus: ExitStatus; + killerId: string; + killerAid: string; + exitName: string; + inSession: boolean; + favorite: boolean; + playTime: number; } diff --git a/project/src/models/eft/match/IEndOfflineRaidRequestData.ts b/project/src/models/eft/match/IEndOfflineRaidRequestData.ts index 62294f13..9368c329 100644 --- a/project/src/models/eft/match/IEndOfflineRaidRequestData.ts +++ b/project/src/models/eft/match/IEndOfflineRaidRequestData.ts @@ -1,7 +1,6 @@ -export interface IEndOfflineRaidRequestData -{ - crc: number - exitStatus: string - exitName: string - raidSeconds: number +export interface IEndOfflineRaidRequestData { + crc: number; + exitStatus: string; + exitName: string; + raidSeconds: number; } diff --git a/project/src/models/eft/match/IGetRaidConfigurationRequestData.ts b/project/src/models/eft/match/IGetRaidConfigurationRequestData.ts index 1f72008d..97bbccd9 100644 --- a/project/src/models/eft/match/IGetRaidConfigurationRequestData.ts +++ b/project/src/models/eft/match/IGetRaidConfigurationRequestData.ts @@ -1,8 +1,7 @@ import { IRaidSettings } from "@spt/models/eft/match/IRaidSettings"; -export interface IGetRaidConfigurationRequestData extends IRaidSettings -{ - keyId: string - CanShowGroupPreview: boolean - MaxGroupCount: number +export interface IGetRaidConfigurationRequestData extends IRaidSettings { + keyId: string; + CanShowGroupPreview: boolean; + MaxGroupCount: number; } diff --git a/project/src/models/eft/match/IGroupCharacter.ts b/project/src/models/eft/match/IGroupCharacter.ts index 57eb9416..71178ad4 100644 --- a/project/src/models/eft/match/IGroupCharacter.ts +++ b/project/src/models/eft/match/IGroupCharacter.ts @@ -1,41 +1,40 @@ import { Item } from "@spt/models/eft/common/tables/IItem"; import { MemberCategory } from "@spt/models/enums/MemberCategory"; -export interface IGroupCharacter -{ - _id: string - aid: number +export interface IGroupCharacter { + _id: string; + aid: number; Info: { - Nickname: string - Side: string - Level: number - MemberCategory: MemberCategory - GameVersion?: string - SavageLockTime?: number - SavageNickname?: string - hasCoopExtension?: boolean - } + Nickname: string; + Side: string; + Level: number; + MemberCategory: MemberCategory; + GameVersion?: string; + SavageLockTime?: number; + SavageNickname?: string; + hasCoopExtension?: boolean; + }; PlayerVisualRepresentation?: { Info: { - Side: string - Level: number - Nickname: string - MemberCategory: MemberCategory - GameVersion: string - } + Side: string; + Level: number; + Nickname: string; + MemberCategory: MemberCategory; + GameVersion: string; + }; Customization: { - Head: string - Body: string - Feet: string - Hands: string - } + Head: string; + Body: string; + Feet: string; + Hands: string; + }; Equipment: { - Id: string - Items: Item[] - } - } - isLeader: boolean - isReady?: boolean - region?: string - lookingGroup?: boolean + Id: string; + Items: Item[]; + }; + }; + isLeader: boolean; + isReady?: boolean; + region?: string; + lookingGroup?: boolean; } diff --git a/project/src/models/eft/match/IMatchGroupCurrentResponse.ts b/project/src/models/eft/match/IMatchGroupCurrentResponse.ts index cace98f7..7864f93a 100644 --- a/project/src/models/eft/match/IMatchGroupCurrentResponse.ts +++ b/project/src/models/eft/match/IMatchGroupCurrentResponse.ts @@ -1,6 +1,5 @@ import { IGroupCharacter } from "@spt/models/eft/match/IGroupCharacter"; -export interface IMatchGroupCurrentResponse -{ - squad: IGroupCharacter[] +export interface IMatchGroupCurrentResponse { + squad: IGroupCharacter[]; } diff --git a/project/src/models/eft/match/IMatchGroupInviteSendRequest.ts b/project/src/models/eft/match/IMatchGroupInviteSendRequest.ts index b1dddb36..e03cb90a 100644 --- a/project/src/models/eft/match/IMatchGroupInviteSendRequest.ts +++ b/project/src/models/eft/match/IMatchGroupInviteSendRequest.ts @@ -1,5 +1,4 @@ -export interface IMatchGroupInviteSendRequest -{ - to: string - inLobby: boolean +export interface IMatchGroupInviteSendRequest { + to: string; + inLobby: boolean; } diff --git a/project/src/models/eft/match/IMatchGroupPlayerRemoveRequest.ts b/project/src/models/eft/match/IMatchGroupPlayerRemoveRequest.ts index 6cdef152..623eadb1 100644 --- a/project/src/models/eft/match/IMatchGroupPlayerRemoveRequest.ts +++ b/project/src/models/eft/match/IMatchGroupPlayerRemoveRequest.ts @@ -1,4 +1,3 @@ -export interface IMatchGroupPlayerRemoveRequest -{ - aidToKick: string +export interface IMatchGroupPlayerRemoveRequest { + aidToKick: string; } diff --git a/project/src/models/eft/match/IMatchGroupStartGameRequest.ts b/project/src/models/eft/match/IMatchGroupStartGameRequest.ts index dbe6ada3..1776df07 100644 --- a/project/src/models/eft/match/IMatchGroupStartGameRequest.ts +++ b/project/src/models/eft/match/IMatchGroupStartGameRequest.ts @@ -1,7 +1,6 @@ import { IServer } from "@spt/models/eft/match/IServer"; -export interface IMatchGroupStartGameRequest -{ - groupId: string - servers: IServer[] +export interface IMatchGroupStartGameRequest { + groupId: string; + servers: IServer[]; } diff --git a/project/src/models/eft/match/IMatchGroupStatusRequest.ts b/project/src/models/eft/match/IMatchGroupStatusRequest.ts index 9da6a764..3824c428 100644 --- a/project/src/models/eft/match/IMatchGroupStatusRequest.ts +++ b/project/src/models/eft/match/IMatchGroupStatusRequest.ts @@ -1,11 +1,10 @@ import { RaidMode } from "@spt/models/enums/RaidMode"; -export interface IMatchGroupStatusRequest -{ - location: string - savage: boolean - dt: string - keyId: string - raidMode: RaidMode - spawnPlace: string +export interface IMatchGroupStatusRequest { + location: string; + savage: boolean; + dt: string; + keyId: string; + raidMode: RaidMode; + spawnPlace: string; } diff --git a/project/src/models/eft/match/IMatchGroupStatusResponse.ts b/project/src/models/eft/match/IMatchGroupStatusResponse.ts index 3ef36bc9..14f46370 100644 --- a/project/src/models/eft/match/IMatchGroupStatusResponse.ts +++ b/project/src/models/eft/match/IMatchGroupStatusResponse.ts @@ -1,7 +1,6 @@ import { IGroupCharacter } from "@spt/models/eft/match/IGroupCharacter"; -export interface IMatchGroupStatusResponse -{ - players: IGroupCharacter[] - maxPveCountExceeded: boolean +export interface IMatchGroupStatusResponse { + players: IGroupCharacter[]; + maxPveCountExceeded: boolean; } diff --git a/project/src/models/eft/match/IMatchGroupTransferRequest.ts b/project/src/models/eft/match/IMatchGroupTransferRequest.ts index 692e9cd4..44763870 100644 --- a/project/src/models/eft/match/IMatchGroupTransferRequest.ts +++ b/project/src/models/eft/match/IMatchGroupTransferRequest.ts @@ -1,4 +1,3 @@ -export interface IMatchGroupTransferRequest -{ - aidToChange: string +export interface IMatchGroupTransferRequest { + aidToChange: string; } diff --git a/project/src/models/eft/match/IProfileStatusRequest.ts b/project/src/models/eft/match/IProfileStatusRequest.ts index b5039edb..0667a99a 100644 --- a/project/src/models/eft/match/IProfileStatusRequest.ts +++ b/project/src/models/eft/match/IProfileStatusRequest.ts @@ -1,4 +1,3 @@ -export interface IProfileStatusRequest -{ - groupId: number +export interface IProfileStatusRequest { + groupId: number; } diff --git a/project/src/models/eft/match/IProfileStatusResponse.ts b/project/src/models/eft/match/IProfileStatusResponse.ts index 69a26d46..90636e1f 100644 --- a/project/src/models/eft/match/IProfileStatusResponse.ts +++ b/project/src/models/eft/match/IProfileStatusResponse.ts @@ -1,7 +1,6 @@ import { ISessionStatus } from "@spt/models/eft/match/ISessionStatus"; -export interface IProfileStatusResponse -{ - maxPveCountExceeded: boolean - profiles: ISessionStatus[] +export interface IProfileStatusResponse { + maxPveCountExceeded: boolean; + profiles: ISessionStatus[]; } diff --git a/project/src/models/eft/match/IPutMetricsRequestData.ts b/project/src/models/eft/match/IPutMetricsRequestData.ts index 2eea6cd8..312b622b 100644 --- a/project/src/models/eft/match/IPutMetricsRequestData.ts +++ b/project/src/models/eft/match/IPutMetricsRequestData.ts @@ -1,64 +1,60 @@ -export interface IPutMetricsRequestData -{ - sid: string - settings: any - SharedSettings: ISharedSettings - HardwareDescription: IHardwareDescription - Location: string - Metrics: any - ClientEvents: IClientEvents - SpikeSamples: any[] - mode: string +export interface IPutMetricsRequestData { + sid: string; + settings: any; + SharedSettings: ISharedSettings; + HardwareDescription: IHardwareDescription; + Location: string; + Metrics: any; + ClientEvents: IClientEvents; + SpikeSamples: any[]; + mode: string; } -export interface ISharedSettings -{ - StatedFieldOfView: number +export interface ISharedSettings { + StatedFieldOfView: number; } -export interface IHardwareDescription -{ - deviceUniqueIdentifier: string - systemMemorySize: number - graphicsDeviceID: number - graphicsDeviceName: string - graphicsDeviceType: string - graphicsDeviceVendor: string - graphicsDeviceVendorID: number - graphicsDeviceVersion: string - graphicsMemorySize: number - graphicsMultiThreaded: boolean - graphicsShaderLevel: number - operatingSystem: string - processorCount: number - processorFrequency: number - processorType: string - driveType: string - swapDriveType: string +export interface IHardwareDescription { + deviceUniqueIdentifier: string; + systemMemorySize: number; + graphicsDeviceID: number; + graphicsDeviceName: string; + graphicsDeviceType: string; + graphicsDeviceVendor: string; + graphicsDeviceVendorID: number; + graphicsDeviceVersion: string; + graphicsMemorySize: number; + graphicsMultiThreaded: boolean; + graphicsShaderLevel: number; + operatingSystem: string; + processorCount: number; + processorFrequency: number; + processorType: string; + driveType: string; + swapDriveType: string; } -export interface IClientEvents -{ - MatchingCompleted: number - MatchingCompletedReal: number - LocationLoaded: number - LocationLoadedReal: number - GamePrepared: number - GamePreparedReal: number - GameCreated: number - GameCreatedReal: number - GamePooled: number - GamePooledReal: number - GameRunned: number - GameRunnedReal: number - GameSpawn: number - GameSpawnReal: number - PlayerSpawnEvent: number - PlayerSpawnEventReal: number - GameSpawned: number - GameSpawnedReal: number - GameStarting: number - GameStartingReal: number - GameStarted: number - GameStartedReal: number +export interface IClientEvents { + MatchingCompleted: number; + MatchingCompletedReal: number; + LocationLoaded: number; + LocationLoadedReal: number; + GamePrepared: number; + GamePreparedReal: number; + GameCreated: number; + GameCreatedReal: number; + GamePooled: number; + GamePooledReal: number; + GameRunned: number; + GameRunnedReal: number; + GameSpawn: number; + GameSpawnReal: number; + PlayerSpawnEvent: number; + PlayerSpawnEventReal: number; + GameSpawned: number; + GameSpawnedReal: number; + GameStarting: number; + GameStartingReal: number; + GameStarted: number; + GameStartedReal: number; } diff --git a/project/src/models/eft/match/IRaidSettings.ts b/project/src/models/eft/match/IRaidSettings.ts index e52d15b0..2b8c232c 100644 --- a/project/src/models/eft/match/IRaidSettings.ts +++ b/project/src/models/eft/match/IRaidSettings.ts @@ -10,41 +10,37 @@ import { TimeFlowType } from "@spt/models/enums/RaidSettings/TimeAndWeather/Time import { WindSpeed } from "@spt/models/enums/RaidSettings/TimeAndWeather/WindSpeed"; import { SideType } from "@spt/models/enums/SideType"; -export interface IRaidSettings -{ - location: string - timeVariant: DateTime - raidMode: RaidMode - metabolismDisabled: boolean - playersSpawnPlace: PlayersSpawnPlace - timeAndWeatherSettings: TimeAndWeatherSettings - botSettings: BotSettings - wavesSettings: WavesSettings - side: SideType +export interface IRaidSettings { + location: string; + timeVariant: DateTime; + raidMode: RaidMode; + metabolismDisabled: boolean; + playersSpawnPlace: PlayersSpawnPlace; + timeAndWeatherSettings: TimeAndWeatherSettings; + botSettings: BotSettings; + wavesSettings: WavesSettings; + side: SideType; } -export interface TimeAndWeatherSettings -{ - isRandomTime: boolean - isRandomWeather: boolean - cloudinessType: CloudinessType - rainType: RainType - fogType: FogType - windType: WindSpeed - timeFlowType: TimeFlowType - hourOfDay: number +export interface TimeAndWeatherSettings { + isRandomTime: boolean; + isRandomWeather: boolean; + cloudinessType: CloudinessType; + rainType: RainType; + fogType: FogType; + windType: WindSpeed; + timeFlowType: TimeFlowType; + hourOfDay: number; } -export interface BotSettings -{ - isScavWars: boolean - botAmount: BotAmount +export interface BotSettings { + isScavWars: boolean; + botAmount: BotAmount; } -export interface WavesSettings -{ - botAmount: BotAmount - botDifficulty: BotDifficulty - isBosses: boolean - isTaggedAndCursed: boolean +export interface WavesSettings { + botAmount: BotAmount; + botDifficulty: BotDifficulty; + isBosses: boolean; + isTaggedAndCursed: boolean; } diff --git a/project/src/models/eft/match/IRequestIdRequest.ts b/project/src/models/eft/match/IRequestIdRequest.ts index a742c2ce..755ca1bd 100644 --- a/project/src/models/eft/match/IRequestIdRequest.ts +++ b/project/src/models/eft/match/IRequestIdRequest.ts @@ -1,4 +1,3 @@ -export interface IRequestIdRequest -{ - requestId: string +export interface IRequestIdRequest { + requestId: string; } diff --git a/project/src/models/eft/match/IServer.ts b/project/src/models/eft/match/IServer.ts index d5510fdd..d7c30d87 100644 --- a/project/src/models/eft/match/IServer.ts +++ b/project/src/models/eft/match/IServer.ts @@ -1,6 +1,5 @@ -export interface IServer -{ - ping: number - ip: string - port: number +export interface IServer { + ping: number; + ip: string; + port: number; } diff --git a/project/src/models/eft/match/ISessionStatus.ts b/project/src/models/eft/match/ISessionStatus.ts index 16ebbaf0..c745cbf1 100644 --- a/project/src/models/eft/match/ISessionStatus.ts +++ b/project/src/models/eft/match/ISessionStatus.ts @@ -1,15 +1,14 @@ -export interface ISessionStatus -{ - profileid: string - profileToken: string - status: string - ip: string - port: number - sid: string - version?: string - location?: string - raidMode?: string - mode?: string - shortId?: string - additional_info?: any[] +export interface ISessionStatus { + profileid: string; + profileToken: string; + status: string; + ip: string; + port: number; + sid: string; + version?: string; + location?: string; + raidMode?: string; + mode?: string; + shortId?: string; + additional_info?: any[]; } diff --git a/project/src/models/eft/match/IStartLocalRaidRequestData.ts b/project/src/models/eft/match/IStartLocalRaidRequestData.ts index 1bb2a4f5..5483297f 100644 --- a/project/src/models/eft/match/IStartLocalRaidRequestData.ts +++ b/project/src/models/eft/match/IStartLocalRaidRequestData.ts @@ -1,8 +1,7 @@ -export interface IStartLocalRaidRequestData -{ - serverId: string - location: string - timeVariant: string - mode: string - playerSide: string +export interface IStartLocalRaidRequestData { + serverId: string; + location: string; + timeVariant: string; + mode: string; + playerSide: string; } diff --git a/project/src/models/eft/match/IStartLocalRaidResponseData.ts b/project/src/models/eft/match/IStartLocalRaidResponseData.ts index f87375a2..79fd3346 100644 --- a/project/src/models/eft/match/IStartLocalRaidResponseData.ts +++ b/project/src/models/eft/match/IStartLocalRaidResponseData.ts @@ -2,15 +2,13 @@ import { ILocationBase } from "@spt/models/eft/common/ILocationBase"; import { IInsuredItem } from "@spt/models/eft/common/tables/IBotBase"; import { ILocationServices } from "@spt/models/eft/common/tables/ILocationServices"; -export interface IStartLocalRaidResponseData -{ - serverId: string - serverSettings: ILocationServices - profile: IProfileInsuredItems - locationLoot: ILocationBase +export interface IStartLocalRaidResponseData { + serverId: string; + serverSettings: ILocationServices; + profile: IProfileInsuredItems; + locationLoot: ILocationBase; } -export interface IProfileInsuredItems -{ - insuredItems: IInsuredItem[] +export interface IProfileInsuredItems { + insuredItems: IInsuredItem[]; } diff --git a/project/src/models/eft/match/IUpdatePingRequestData.ts b/project/src/models/eft/match/IUpdatePingRequestData.ts index 9a0c90bf..defbd66e 100644 --- a/project/src/models/eft/match/IUpdatePingRequestData.ts +++ b/project/src/models/eft/match/IUpdatePingRequestData.ts @@ -1,4 +1,3 @@ -export interface IUpdatePingRequestData -{ - servers: any[] +export interface IUpdatePingRequestData { + servers: any[]; } diff --git a/project/src/models/eft/notes/INoteActionData.ts b/project/src/models/eft/notes/INoteActionData.ts index 1fadc9ca..99bc694f 100644 --- a/project/src/models/eft/notes/INoteActionData.ts +++ b/project/src/models/eft/notes/INoteActionData.ts @@ -1,14 +1,12 @@ import { IBaseInteractionRequestData } from "@spt/models/eft/common/request/IBaseInteractionRequestData"; -export interface INoteActionData extends IBaseInteractionRequestData -{ - Action: string - index: number - note: INote +export interface INoteActionData extends IBaseInteractionRequestData { + Action: string; + index: number; + note: INote; } -export interface INote -{ - Time: number - Text: string +export interface INote { + Time: number; + Text: string; } diff --git a/project/src/models/eft/notifier/INotifier.ts b/project/src/models/eft/notifier/INotifier.ts index 61bea63b..4ead2724 100644 --- a/project/src/models/eft/notifier/INotifier.ts +++ b/project/src/models/eft/notifier/INotifier.ts @@ -1,8 +1,7 @@ -export interface INotifierChannel -{ - server: string - channel_id: string - url: string - notifierServer: string - ws: string +export interface INotifierChannel { + server: string; + channel_id: string; + url: string; + notifierServer: string; + ws: string; } diff --git a/project/src/models/eft/notifier/ISelectProfileResponse.ts b/project/src/models/eft/notifier/ISelectProfileResponse.ts index b2f8f74a..f2d6be77 100644 --- a/project/src/models/eft/notifier/ISelectProfileResponse.ts +++ b/project/src/models/eft/notifier/ISelectProfileResponse.ts @@ -1,4 +1,3 @@ -export interface ISelectProfileResponse -{ - status: string +export interface ISelectProfileResponse { + status: string; } diff --git a/project/src/models/eft/player/IPlayerIncrementSkillLevelRequestData.ts b/project/src/models/eft/player/IPlayerIncrementSkillLevelRequestData.ts index a04722d6..db3df3e0 100644 --- a/project/src/models/eft/player/IPlayerIncrementSkillLevelRequestData.ts +++ b/project/src/models/eft/player/IPlayerIncrementSkillLevelRequestData.ts @@ -1,27 +1,23 @@ import { Skills } from "@spt/models/eft/common/tables/IBotBase"; -export interface IPlayerIncrementSkillLevelRequestData -{ - _id: string - experience: number - quests: any[] - ragFairOffers: any[] - builds: any[] - items: Items - production: Production - skills: Skills - traderRelations: TraderRelations +export interface IPlayerIncrementSkillLevelRequestData { + _id: string; + experience: number; + quests: any[]; + ragFairOffers: any[]; + builds: any[]; + items: Items; + production: Production; + skills: Skills; + traderRelations: TraderRelations; } -export interface Items -{ - new: any[] - change: any[] - del: any[] +export interface Items { + new: any[]; + change: any[]; + del: any[]; } -export interface Production -{} +export type Production = {}; -export interface TraderRelations -{} +export type TraderRelations = {}; diff --git a/project/src/models/eft/presetBuild/IPresetBuildActionRequestData.ts b/project/src/models/eft/presetBuild/IPresetBuildActionRequestData.ts index 4043e859..3da0b75e 100644 --- a/project/src/models/eft/presetBuild/IPresetBuildActionRequestData.ts +++ b/project/src/models/eft/presetBuild/IPresetBuildActionRequestData.ts @@ -1,11 +1,10 @@ import { Item } from "@spt/models/eft/common/tables/IItem"; -export interface IPresetBuildActionRequestData -{ - Action: string - Id: string +export interface IPresetBuildActionRequestData { + Action: string; + Id: string; /** name of preset given by player */ - Name: string - Root: string - Items: Item[] + Name: string; + Root: string; + Items: Item[]; } diff --git a/project/src/models/eft/presetBuild/IRemoveBuildRequestData.ts b/project/src/models/eft/presetBuild/IRemoveBuildRequestData.ts index 2014ed6e..bcbdbceb 100644 --- a/project/src/models/eft/presetBuild/IRemoveBuildRequestData.ts +++ b/project/src/models/eft/presetBuild/IRemoveBuildRequestData.ts @@ -1,4 +1,3 @@ -export interface IRemoveBuildRequestData -{ - id: string +export interface IRemoveBuildRequestData { + id: string; } diff --git a/project/src/models/eft/profile/GetProfileStatusResponseData.ts b/project/src/models/eft/profile/GetProfileStatusResponseData.ts index f70e6dcb..059d2348 100644 --- a/project/src/models/eft/profile/GetProfileStatusResponseData.ts +++ b/project/src/models/eft/profile/GetProfileStatusResponseData.ts @@ -1,21 +1,19 @@ -export interface GetProfileStatusResponseData -{ - maxPveCountExceeded: false - profiles: ProfileData[] +export interface GetProfileStatusResponseData { + maxPveCountExceeded: false; + profiles: ProfileData[]; } -export interface ProfileData -{ - profileid: string - profileToken: string - status: string - ip: string - port: number - sid: string - version?: string - location?: string - raidMode?: string - mode?: string - shortId?: string - additional_info?: any[] +export interface ProfileData { + profileid: string; + profileToken: string; + status: string; + ip: string; + port: number; + sid: string; + version?: string; + location?: string; + raidMode?: string; + mode?: string; + shortId?: string; + additional_info?: any[]; } diff --git a/project/src/models/eft/profile/ICompletedAchievementsResponse.ts b/project/src/models/eft/profile/ICompletedAchievementsResponse.ts index 89e8904b..09275bc7 100644 --- a/project/src/models/eft/profile/ICompletedAchievementsResponse.ts +++ b/project/src/models/eft/profile/ICompletedAchievementsResponse.ts @@ -1,4 +1,3 @@ -export interface ICompletedAchievementsResponse -{ - elements: Record +export interface ICompletedAchievementsResponse { + elements: Record; } diff --git a/project/src/models/eft/profile/IConnectResponse.ts b/project/src/models/eft/profile/IConnectResponse.ts index 005c5d62..8e809efc 100644 --- a/project/src/models/eft/profile/IConnectResponse.ts +++ b/project/src/models/eft/profile/IConnectResponse.ts @@ -1,7 +1,6 @@ -export interface IConnectResponse -{ - backendUrl: string - name: string - editions: string[] - profileDescriptions: Record +export interface IConnectResponse { + backendUrl: string; + name: string; + editions: string[]; + profileDescriptions: Record; } diff --git a/project/src/models/eft/profile/ICreateProfileResponse.ts b/project/src/models/eft/profile/ICreateProfileResponse.ts index decb6bb6..c2974829 100644 --- a/project/src/models/eft/profile/ICreateProfileResponse.ts +++ b/project/src/models/eft/profile/ICreateProfileResponse.ts @@ -1,4 +1,3 @@ -export interface ICreateProfileResponse -{ - uid: string +export interface ICreateProfileResponse { + uid: string; } diff --git a/project/src/models/eft/profile/IGetAchievementsResponse.ts b/project/src/models/eft/profile/IGetAchievementsResponse.ts index 5c85c78b..e0171f27 100644 --- a/project/src/models/eft/profile/IGetAchievementsResponse.ts +++ b/project/src/models/eft/profile/IGetAchievementsResponse.ts @@ -1,6 +1,5 @@ import { IAchievement } from "@spt/models/eft/common/tables/IAchievement"; -export interface IGetAchievementsResponse -{ - elements: IAchievement[] +export interface IGetAchievementsResponse { + elements: IAchievement[]; } diff --git a/project/src/models/eft/profile/IGetOtherProfileRequest.ts b/project/src/models/eft/profile/IGetOtherProfileRequest.ts index 6fd60cb3..de3144b7 100644 --- a/project/src/models/eft/profile/IGetOtherProfileRequest.ts +++ b/project/src/models/eft/profile/IGetOtherProfileRequest.ts @@ -1,4 +1,3 @@ -export interface IGetOtherProfileRequest -{ - accountId: string +export interface IGetOtherProfileRequest { + accountId: string; } diff --git a/project/src/models/eft/profile/IGetOtherProfileResponse.ts b/project/src/models/eft/profile/IGetOtherProfileResponse.ts index d0e00e7f..7623b30d 100644 --- a/project/src/models/eft/profile/IGetOtherProfileResponse.ts +++ b/project/src/models/eft/profile/IGetOtherProfileResponse.ts @@ -1,52 +1,46 @@ import { OverallCounters, Skills } from "@spt/models/eft/common/tables/IBotBase"; import { Item } from "@spt/models/eft/common/tables/IItem"; -export interface IGetOtherProfileResponse -{ - id: string - aid: number - info: IOtherProfileInfo - customization: IOtherProfileCustomization - skills: Skills - equipment: IOtherProfileEquipment - achievements: Record - favoriteItems: string[] - pmcStats: IOtherProfileStats - scavStats: IOtherProfileStats +export interface IGetOtherProfileResponse { + id: string; + aid: number; + info: IOtherProfileInfo; + customization: IOtherProfileCustomization; + skills: Skills; + equipment: IOtherProfileEquipment; + achievements: Record; + favoriteItems: string[]; + pmcStats: IOtherProfileStats; + scavStats: IOtherProfileStats; } -export interface IOtherProfileInfo -{ - nickname: string - side: string - experience: number - memberCategory: number - bannedState: boolean - bannedUntil: number - registrationDate: number +export interface IOtherProfileInfo { + nickname: string; + side: string; + experience: number; + memberCategory: number; + bannedState: boolean; + bannedUntil: number; + registrationDate: number; } -export interface IOtherProfileCustomization -{ - head: string - body: string - feet: string - hands: string +export interface IOtherProfileCustomization { + head: string; + body: string; + feet: string; + hands: string; } -export interface IOtherProfileEquipment -{ - Id: string - Items: Item[] +export interface IOtherProfileEquipment { + Id: string; + Items: Item[]; } -export interface IOtherProfileStats -{ - eft: IOtherProfileSubStats +export interface IOtherProfileStats { + eft: IOtherProfileSubStats; } -export interface IOtherProfileSubStats -{ - totalInGameTime: number - overAllCounters: OverallCounters +export interface IOtherProfileSubStats { + totalInGameTime: number; + overAllCounters: OverallCounters; } diff --git a/project/src/models/eft/profile/IGetProfileSettingsRequest.ts b/project/src/models/eft/profile/IGetProfileSettingsRequest.ts index 892f24b3..11415228 100644 --- a/project/src/models/eft/profile/IGetProfileSettingsRequest.ts +++ b/project/src/models/eft/profile/IGetProfileSettingsRequest.ts @@ -1,6 +1,5 @@ -export interface IGetProfileSettingsRequest -{ +export interface IGetProfileSettingsRequest { /** Chosen value for profile.Info.SelectedMemberCategory */ - memberCategory: number - squadInviteRestriction: boolean + memberCategory: number; + squadInviteRestriction: boolean; } diff --git a/project/src/models/eft/profile/IProfileChangeNicknameRequestData.ts b/project/src/models/eft/profile/IProfileChangeNicknameRequestData.ts index 58a278e7..4a611966 100644 --- a/project/src/models/eft/profile/IProfileChangeNicknameRequestData.ts +++ b/project/src/models/eft/profile/IProfileChangeNicknameRequestData.ts @@ -1,4 +1,3 @@ -export interface IProfileChangeNicknameRequestData -{ - nickname: string +export interface IProfileChangeNicknameRequestData { + nickname: string; } diff --git a/project/src/models/eft/profile/IProfileChangeVoiceRequestData.ts b/project/src/models/eft/profile/IProfileChangeVoiceRequestData.ts index 6a44bceb..91058cee 100644 --- a/project/src/models/eft/profile/IProfileChangeVoiceRequestData.ts +++ b/project/src/models/eft/profile/IProfileChangeVoiceRequestData.ts @@ -1,4 +1,3 @@ -export interface IProfileChangeVoiceRequestData -{ - voice: string +export interface IProfileChangeVoiceRequestData { + voice: string; } diff --git a/project/src/models/eft/profile/IProfileCreateRequestData.ts b/project/src/models/eft/profile/IProfileCreateRequestData.ts index c437d7f7..93cc656f 100644 --- a/project/src/models/eft/profile/IProfileCreateRequestData.ts +++ b/project/src/models/eft/profile/IProfileCreateRequestData.ts @@ -1,7 +1,6 @@ -export interface IProfileCreateRequestData -{ - side: string - nickname: string - headId: string - voiceId: string +export interface IProfileCreateRequestData { + side: string; + nickname: string; + headId: string; + voiceId: string; } diff --git a/project/src/models/eft/profile/ISearchFriendRequestData.ts b/project/src/models/eft/profile/ISearchFriendRequestData.ts index cc7848b1..e63e386d 100644 --- a/project/src/models/eft/profile/ISearchFriendRequestData.ts +++ b/project/src/models/eft/profile/ISearchFriendRequestData.ts @@ -1,4 +1,3 @@ -export interface ISearchFriendRequestData -{ - nickname: string +export interface ISearchFriendRequestData { + nickname: string; } diff --git a/project/src/models/eft/profile/ISearchFriendResponse.ts b/project/src/models/eft/profile/ISearchFriendResponse.ts index f49d28eb..393ecbe7 100644 --- a/project/src/models/eft/profile/ISearchFriendResponse.ts +++ b/project/src/models/eft/profile/ISearchFriendResponse.ts @@ -1,14 +1,12 @@ -export interface ISearchFriendResponse -{ - _id: string - aid: number - Info: Info +export interface ISearchFriendResponse { + _id: string; + aid: number; + Info: Info; } -export interface Info -{ - Nickname: string - Side: string - Level: number - MemberCategory: number +export interface Info { + Nickname: string; + Side: string; + Level: number; + MemberCategory: number; } diff --git a/project/src/models/eft/profile/ISptProfile.ts b/project/src/models/eft/profile/ISptProfile.ts index 48a0ed82..fbc5ae56 100644 --- a/project/src/models/eft/profile/ISptProfile.ts +++ b/project/src/models/eft/profile/ISptProfile.ts @@ -5,317 +5,279 @@ import { MemberCategory } from "@spt/models/enums/MemberCategory"; import { MessageType } from "@spt/models/enums/MessageType"; import { IProfileChangeEvent } from "@spt/models/spt/dialog/ISendMessageDetails"; -export interface ISptProfile -{ - info: Info - characters: Characters +export interface ISptProfile { + info: Info; + characters: Characters; /** Clothing purchases */ - suits: string[] - userbuilds: IUserBuilds - dialogues: Record - spt: Spt - vitality: Vitality - inraid: Inraid - insurance: Insurance[] + suits: string[]; + userbuilds: IUserBuilds; + dialogues: Record; + spt: Spt; + vitality: Vitality; + inraid: Inraid; + insurance: Insurance[]; /** Assort purchases made by player since last trader refresh */ - traderPurchases?: Record> + traderPurchases?: Record>; /** Achievements earned by player */ - achievements: Record + achievements: Record; } -export class TraderPurchaseData -{ +export class TraderPurchaseData { count: number; purchaseTimestamp: number; } -export interface Info -{ +export interface Info { /** main profile id */ - id: string - scavId: string - aid: number - username: string - password: string - wipe: boolean - edition: string + id: string; + scavId: string; + aid: number; + username: string; + password: string; + wipe: boolean; + edition: string; } -export interface Characters -{ - pmc: IPmcData - scav: IPmcData +export interface Characters { + pmc: IPmcData; + scav: IPmcData; } /** used by profile.userbuilds */ -export interface IUserBuilds -{ - weaponBuilds: IWeaponBuild[] - equipmentBuilds: IEquipmentBuild[] - magazineBuilds: IMagazineBuild[] +export interface IUserBuilds { + weaponBuilds: IWeaponBuild[]; + equipmentBuilds: IEquipmentBuild[]; + magazineBuilds: IMagazineBuild[]; } -export interface IUserBuild -{ - Id: string - Name: string +export interface IUserBuild { + Id: string; + Name: string; } -export interface IWeaponBuild extends IUserBuild -{ - Root: string - Items: Item[] // Same as PMC inventory items +export interface IWeaponBuild extends IUserBuild { + Root: string; + Items: Item[]; // Same as PMC inventory items } -export interface IEquipmentBuild extends IUserBuild -{ - Root: string - Items: Item[] // Same as PMC inventory items - BuildType: EquipmentBuildType +export interface IEquipmentBuild extends IUserBuild { + Root: string; + Items: Item[]; // Same as PMC inventory items + BuildType: EquipmentBuildType; } -export interface IMagazineBuild extends IUserBuild -{ - Caliber: string - TopCount: number - BottomCount: number - Items: IMagazineTemplateAmmoItem[] +export interface IMagazineBuild extends IUserBuild { + Caliber: string; + TopCount: number; + BottomCount: number; + Items: IMagazineTemplateAmmoItem[]; } -export interface IMagazineTemplateAmmoItem -{ - TemplateId: string - Count: number +export interface IMagazineTemplateAmmoItem { + TemplateId: string; + Count: number; } /** Used by defaultEquipmentPresets.json */ -export interface IDefaultEquipmentPreset extends IUserBuild -{ - Items: Item[] - Root: string - BuildType: EquipmentBuildType - type: string +export interface IDefaultEquipmentPreset extends IUserBuild { + Items: Item[]; + Root: string; + BuildType: EquipmentBuildType; + type: string; } -export interface Dialogue -{ - attachmentsNew: number - new: number - type: MessageType - Users?: IUserDialogInfo[] - pinned: boolean - messages: Message[] - _id: string +export interface Dialogue { + attachmentsNew: number; + new: number; + type: MessageType; + Users?: IUserDialogInfo[]; + pinned: boolean; + messages: Message[]; + _id: string; } -export interface IUserDialogInfo -{ - _id: string - aid: number - Info?: IUserDialogDetails +export interface IUserDialogInfo { + _id: string; + aid: number; + Info?: IUserDialogDetails; } -export interface IUserDialogDetails -{ - Nickname: string - Side: string - Level: number - MemberCategory: MemberCategory - SelectedMemberCategory: MemberCategory +export interface IUserDialogDetails { + Nickname: string; + Side: string; + Level: number; + MemberCategory: MemberCategory; + SelectedMemberCategory: MemberCategory; } // @Cleanup: Maybe the same as Dialogue? -export interface DialogueInfo -{ - attachmentsNew: number - new: number - _id: string - type: MessageType - pinned: boolean - Users?: IUserDialogInfo[] - message: MessagePreview +export interface DialogueInfo { + attachmentsNew: number; + new: number; + _id: string; + type: MessageType; + pinned: boolean; + Users?: IUserDialogInfo[]; + message: MessagePreview; } -export interface Message -{ - _id: string - uid: string - type: MessageType - dt: number - UtcDateTime?: number - Member?: IUpdatableChatMember - templateId?: string - text?: string - replyTo?: IReplyTo - hasRewards?: boolean - rewardCollected: boolean - items?: MessageItems - maxStorageTime?: number - systemData?: ISystemData - profileChangeEvents?: IProfileChangeEvent[] +export interface Message { + _id: string; + uid: string; + type: MessageType; + dt: number; + UtcDateTime?: number; + Member?: IUpdatableChatMember; + templateId?: string; + text?: string; + replyTo?: IReplyTo; + hasRewards?: boolean; + rewardCollected: boolean; + items?: MessageItems; + maxStorageTime?: number; + systemData?: ISystemData; + profileChangeEvents?: IProfileChangeEvent[]; } -export interface IReplyTo -{ - _id: string - uid: string - type: MessageType - dt: number - text?: string +export interface IReplyTo { + _id: string; + uid: string; + type: MessageType; + dt: number; + text?: string; } -export interface MessagePreview -{ - uid: string - type: MessageType - dt: number - templateId: string - text?: string - systemData?: ISystemData +export interface MessagePreview { + uid: string; + type: MessageType; + dt: number; + templateId: string; + text?: string; + systemData?: ISystemData; } -export interface MessageItems -{ - stash?: string - data?: Item[] +export interface MessageItems { + stash?: string; + data?: Item[]; } -export interface ISystemData -{ - date?: string - time?: string - location?: string - buyerNickname?: string - soldItem?: string - itemCount?: number +export interface ISystemData { + date?: string; + time?: string; + location?: string; + buyerNickname?: string; + soldItem?: string; + itemCount?: number; } -export interface IUpdatableChatMember -{ - Nickname: string - Side: string - Level: number - MemberCategory: MemberCategory - Ignored: boolean - Banned: boolean +export interface IUpdatableChatMember { + Nickname: string; + Side: string; + Level: number; + MemberCategory: MemberCategory; + Ignored: boolean; + Banned: boolean; } -export interface DateTime -{ - date: string - time: string +export interface DateTime { + date: string; + time: string; } -export interface Spt -{ +export interface Spt { /** What version of SPT was this profile made with */ - version: string + version: string; /** What mods has this profile loaded at any point in time */ - mods?: ModDetails[] + mods?: ModDetails[]; /** What gifts has this profile received and how many */ - receivedGifts?: ReceivedGift[] + receivedGifts?: ReceivedGift[]; /** item TPLs blacklisted from being sold on flea for this profile */ - blacklistedItemTpls?: string[] + blacklistedItemTpls?: string[]; /** key: daily type */ - freeRepeatableRefreshUsedCount?: Record + freeRepeatableRefreshUsedCount?: Record; } -export interface ModDetails -{ - name: string - version: string - author: string - dateAdded: number - url: string +export interface ModDetails { + name: string; + version: string; + author: string; + dateAdded: number; + url: string; } -export interface ReceivedGift -{ - giftId: string - timestampLastAccepted: number - current: number +export interface ReceivedGift { + giftId: string; + timestampLastAccepted: number; + current: number; } -export interface Vitality -{ - health: Health - effects: Effects +export interface Vitality { + health: Health; + effects: Effects; } -export interface Health -{ - Hydration: number - Energy: number - Temperature: number - Head: number - Chest: number - Stomach: number - LeftArm: number - RightArm: number - LeftLeg: number - RightLeg: number +export interface Health { + Hydration: number; + Energy: number; + Temperature: number; + Head: number; + Chest: number; + Stomach: number; + LeftArm: number; + RightArm: number; + LeftLeg: number; + RightLeg: number; } -export interface Effects -{ - Head: Head - Chest: Chest - Stomach: Stomach - LeftArm: LeftArm - RightArm: RightArm - LeftLeg: LeftLeg - RightLeg: RightLeg +export interface Effects { + Head: Head; + Chest: Chest; + Stomach: Stomach; + LeftArm: LeftArm; + RightArm: RightArm; + LeftLeg: LeftLeg; + RightLeg: RightLeg; } -export interface Head -{} +export type Head = {}; -export interface Chest -{} +export type Chest = {}; -export interface Stomach -{} +export type Stomach = {}; -export interface LeftArm -{ - Fracture?: number +export interface LeftArm { + Fracture?: number; } -export interface RightArm -{ - Fracture?: number +export interface RightArm { + Fracture?: number; } -export interface LeftLeg -{ - Fracture?: number +export interface LeftLeg { + Fracture?: number; } -export interface RightLeg -{ - Fracture?: number +export interface RightLeg { + Fracture?: number; } -export interface Inraid -{ - location: string - character: string +export interface Inraid { + location: string; + character: string; } -export interface Insurance -{ - scheduledTime: number - traderId: string - maxStorageTime: number - systemData: ISystemData - messageType: MessageType - messageTemplateId: string - items: Item[] +export interface Insurance { + scheduledTime: number; + traderId: string; + maxStorageTime: number; + systemData: ISystemData; + messageType: MessageType; + messageTemplateId: string; + items: Item[]; } -export interface MessageContentRagfair -{ - offerId: string - count: number - handbookId: string +export interface MessageContentRagfair { + offerId: string; + count: number; + handbookId: string; } diff --git a/project/src/models/eft/profile/IValidateNicknameRequestData.ts b/project/src/models/eft/profile/IValidateNicknameRequestData.ts index f580a63a..9cca7e71 100644 --- a/project/src/models/eft/profile/IValidateNicknameRequestData.ts +++ b/project/src/models/eft/profile/IValidateNicknameRequestData.ts @@ -1,4 +1,3 @@ -export interface IValidateNicknameRequestData -{ - nickname: string +export interface IValidateNicknameRequestData { + nickname: string; } diff --git a/project/src/models/eft/quests/IAcceptQuestRequestData.ts b/project/src/models/eft/quests/IAcceptQuestRequestData.ts index 23606ba1..0e4821ac 100644 --- a/project/src/models/eft/quests/IAcceptQuestRequestData.ts +++ b/project/src/models/eft/quests/IAcceptQuestRequestData.ts @@ -1,6 +1,5 @@ -export interface IAcceptQuestRequestData -{ - Action: "QuestAccept" - qid: string - type: string +export interface IAcceptQuestRequestData { + Action: "QuestAccept"; + qid: string; + type: string; } diff --git a/project/src/models/eft/quests/ICompleteQuestRequestData.ts b/project/src/models/eft/quests/ICompleteQuestRequestData.ts index 75f38885..cda4b353 100644 --- a/project/src/models/eft/quests/ICompleteQuestRequestData.ts +++ b/project/src/models/eft/quests/ICompleteQuestRequestData.ts @@ -1,8 +1,7 @@ -export interface ICompleteQuestRequestData -{ - Action: string +export interface ICompleteQuestRequestData { + Action: string; /** Quest Id */ - qid: string - removeExcessItems: boolean + qid: string; + removeExcessItems: boolean; } diff --git a/project/src/models/eft/quests/IFailQuestRequestData.ts b/project/src/models/eft/quests/IFailQuestRequestData.ts index 22fd94fd..a1a65ea5 100644 --- a/project/src/models/eft/quests/IFailQuestRequestData.ts +++ b/project/src/models/eft/quests/IFailQuestRequestData.ts @@ -1,6 +1,5 @@ -export interface IFailQuestRequestData -{ - Action: "QuestFail" - qid: string - removeExcessItems: boolean +export interface IFailQuestRequestData { + Action: "QuestFail"; + qid: string; + removeExcessItems: boolean; } diff --git a/project/src/models/eft/quests/IHandoverQuestRequestData.ts b/project/src/models/eft/quests/IHandoverQuestRequestData.ts index 42f97791..09ba01da 100644 --- a/project/src/models/eft/quests/IHandoverQuestRequestData.ts +++ b/project/src/models/eft/quests/IHandoverQuestRequestData.ts @@ -1,13 +1,11 @@ -export interface IHandoverQuestRequestData -{ - Action: "QuestHandover" - qid: string - conditionId: string - items: Item[] +export interface IHandoverQuestRequestData { + Action: "QuestHandover"; + qid: string; + conditionId: string; + items: Item[]; } -export interface Item -{ - id: string - count: number +export interface Item { + id: string; + count: number; } diff --git a/project/src/models/eft/quests/IListQuestsRequestData.ts b/project/src/models/eft/quests/IListQuestsRequestData.ts index 22f98124..91f0b8cc 100644 --- a/project/src/models/eft/quests/IListQuestsRequestData.ts +++ b/project/src/models/eft/quests/IListQuestsRequestData.ts @@ -1,4 +1,3 @@ -export interface IListQuestsRequestData -{ - completed: boolean +export interface IListQuestsRequestData { + completed: boolean; } diff --git a/project/src/models/eft/quests/IRepeatableQuestChangeRequest.ts b/project/src/models/eft/quests/IRepeatableQuestChangeRequest.ts index c644063c..015f58ef 100644 --- a/project/src/models/eft/quests/IRepeatableQuestChangeRequest.ts +++ b/project/src/models/eft/quests/IRepeatableQuestChangeRequest.ts @@ -1,5 +1,4 @@ -export interface IRepeatableQuestChangeRequest -{ - Action: "RepeatableQuestChange" - qid: string +export interface IRepeatableQuestChangeRequest { + Action: "RepeatableQuestChange"; + qid: string; } diff --git a/project/src/models/eft/ragfair/IAddOfferRequestData.ts b/project/src/models/eft/ragfair/IAddOfferRequestData.ts index ddb7d1e0..52c91862 100644 --- a/project/src/models/eft/ragfair/IAddOfferRequestData.ts +++ b/project/src/models/eft/ragfair/IAddOfferRequestData.ts @@ -1,16 +1,14 @@ -export interface IAddOfferRequestData -{ - Action: string - sellInOnePiece: boolean - items: string[] - requirements: Requirement[] +export interface IAddOfferRequestData { + Action: string; + sellInOnePiece: boolean; + items: string[]; + requirements: Requirement[]; } -export interface Requirement -{ - _tpl: string - count: number - level: number - side: number - onlyFunctional: boolean +export interface Requirement { + _tpl: string; + count: number; + level: number; + side: number; + onlyFunctional: boolean; } diff --git a/project/src/models/eft/ragfair/IExtendOfferRequestData.ts b/project/src/models/eft/ragfair/IExtendOfferRequestData.ts index 5ffbd443..2a4a876d 100644 --- a/project/src/models/eft/ragfair/IExtendOfferRequestData.ts +++ b/project/src/models/eft/ragfair/IExtendOfferRequestData.ts @@ -1,5 +1,4 @@ -export interface IExtendOfferRequestData -{ - offerId: string - renewalTime: number +export interface IExtendOfferRequestData { + offerId: string; + renewalTime: number; } diff --git a/project/src/models/eft/ragfair/IGetItemPriceResult.ts b/project/src/models/eft/ragfair/IGetItemPriceResult.ts index 8549d1a8..34d1ecda 100644 --- a/project/src/models/eft/ragfair/IGetItemPriceResult.ts +++ b/project/src/models/eft/ragfair/IGetItemPriceResult.ts @@ -1,6 +1,5 @@ import { MinMax } from "@spt/models/common/MinMax"; -export interface IGetItemPriceResult extends MinMax -{ - avg: number +export interface IGetItemPriceResult extends MinMax { + avg: number; } diff --git a/project/src/models/eft/ragfair/IGetMarketPriceRequestData.ts b/project/src/models/eft/ragfair/IGetMarketPriceRequestData.ts index 38f472a6..00f8f17e 100644 --- a/project/src/models/eft/ragfair/IGetMarketPriceRequestData.ts +++ b/project/src/models/eft/ragfair/IGetMarketPriceRequestData.ts @@ -1,4 +1,3 @@ -export interface IGetMarketPriceRequestData -{ - templateId: string +export interface IGetMarketPriceRequestData { + templateId: string; } diff --git a/project/src/models/eft/ragfair/IGetOffersResult.ts b/project/src/models/eft/ragfair/IGetOffersResult.ts index 03631589..4b63ef09 100644 --- a/project/src/models/eft/ragfair/IGetOffersResult.ts +++ b/project/src/models/eft/ragfair/IGetOffersResult.ts @@ -1,9 +1,8 @@ import { IRagfairOffer } from "@spt/models/eft/ragfair/IRagfairOffer"; -export interface IGetOffersResult -{ - categories?: Record - offers: IRagfairOffer[] - offersCount: number - selectedCategory: string +export interface IGetOffersResult { + categories?: Record; + offers: IRagfairOffer[]; + offersCount: number; + selectedCategory: string; } diff --git a/project/src/models/eft/ragfair/IGetRagfairOfferByIdRequest.ts b/project/src/models/eft/ragfair/IGetRagfairOfferByIdRequest.ts index 981a783d..91e3615c 100644 --- a/project/src/models/eft/ragfair/IGetRagfairOfferByIdRequest.ts +++ b/project/src/models/eft/ragfair/IGetRagfairOfferByIdRequest.ts @@ -1,4 +1,3 @@ -export interface IGetRagfairOfferByIdRequest -{ - id: number +export interface IGetRagfairOfferByIdRequest { + id: number; } diff --git a/project/src/models/eft/ragfair/IRagfairOffer.ts b/project/src/models/eft/ragfair/IRagfairOffer.ts index 6c6cc7a2..4bbbdc46 100644 --- a/project/src/models/eft/ragfair/IRagfairOffer.ts +++ b/project/src/models/eft/ragfair/IRagfairOffer.ts @@ -2,56 +2,52 @@ import { Item } from "@spt/models/eft/common/tables/IItem"; import { DogtagExchangeSide } from "@spt/models/enums/DogtagExchangeSide"; import { MemberCategory } from "@spt/models/enums/MemberCategory"; -export interface IRagfairOffer -{ - sellResult?: SellResult[] - _id: string - items: Item[] - requirements: OfferRequirement[] - root: string - intId: number +export interface IRagfairOffer { + sellResult?: SellResult[]; + _id: string; + items: Item[]; + requirements: OfferRequirement[]; + root: string; + intId: number; /** Handbook price */ - itemsCost: number + itemsCost: number; /** Rouble price per item */ - requirementsCost: number - startTime: number - endTime: number - sellInOnePiece: boolean + requirementsCost: number; + startTime: number; + endTime: number; + sellInOnePiece: boolean; /** Rouble price - same as requirementsCost */ - summaryCost: number - user: IRagfairOfferUser + summaryCost: number; + user: IRagfairOfferUser; /** Trader only */ - unlimitedCount?: boolean - loyaltyLevel: number - buyRestrictionMax?: number - buyRestrictionCurrent?: number - locked?: boolean + unlimitedCount?: boolean; + loyaltyLevel: number; + buyRestrictionMax?: number; + buyRestrictionCurrent?: number; + locked?: boolean; } -export interface OfferRequirement -{ - _tpl: string - count: number - onlyFunctional: boolean - level?: number - side?: DogtagExchangeSide +export interface OfferRequirement { + _tpl: string; + count: number; + onlyFunctional: boolean; + level?: number; + side?: DogtagExchangeSide; } -export interface IRagfairOfferUser -{ - id: string - nickname?: string - rating?: number - memberType: MemberCategory - selectedMemberCategory?: MemberCategory - avatar?: string - isRatingGrowing?: boolean - aid?: number +export interface IRagfairOfferUser { + id: string; + nickname?: string; + rating?: number; + memberType: MemberCategory; + selectedMemberCategory?: MemberCategory; + avatar?: string; + isRatingGrowing?: boolean; + aid?: number; } -export interface SellResult -{ - sellTime: number - amount: number +export interface SellResult { + sellTime: number; + amount: number; } diff --git a/project/src/models/eft/ragfair/IRemoveOfferRequestData.ts b/project/src/models/eft/ragfair/IRemoveOfferRequestData.ts index 4f8b6aaf..d9266154 100644 --- a/project/src/models/eft/ragfair/IRemoveOfferRequestData.ts +++ b/project/src/models/eft/ragfair/IRemoveOfferRequestData.ts @@ -1,5 +1,4 @@ -export interface IRemoveOfferRequestData -{ - Action: string - offerId: string +export interface IRemoveOfferRequestData { + Action: string; + offerId: string; } diff --git a/project/src/models/eft/ragfair/ISearchRequestData.ts b/project/src/models/eft/ragfair/ISearchRequestData.ts index 58968e44..ff3d22a2 100644 --- a/project/src/models/eft/ragfair/ISearchRequestData.ts +++ b/project/src/models/eft/ragfair/ISearchRequestData.ts @@ -1,38 +1,35 @@ import { RagfairSort } from "@spt/models/enums/RagfairSort"; -export interface ISearchRequestData -{ - page: number - limit: number - sortType: RagfairSort - sortDirection: number - currency: number - priceFrom: number - priceTo: number - quantityFrom: number - quantityTo: number - conditionFrom: number - conditionTo: number - oneHourExpiration: boolean - removeBartering: boolean - offerOwnerType: OfferOwnerType - onlyFunctional: boolean - updateOfferCount: boolean - handbookId: string - linkedSearchId: string - neededSearchId: string - buildItems: BuildItems - buildCount: number - tm: number - reload: number +export interface ISearchRequestData { + page: number; + limit: number; + sortType: RagfairSort; + sortDirection: number; + currency: number; + priceFrom: number; + priceTo: number; + quantityFrom: number; + quantityTo: number; + conditionFrom: number; + conditionTo: number; + oneHourExpiration: boolean; + removeBartering: boolean; + offerOwnerType: OfferOwnerType; + onlyFunctional: boolean; + updateOfferCount: boolean; + handbookId: string; + linkedSearchId: string; + neededSearchId: string; + buildItems: BuildItems; + buildCount: number; + tm: number; + reload: number; } -export enum OfferOwnerType -{ +export enum OfferOwnerType { ANYOWNERTYPE = 0, TRADEROWNERTYPE = 1, PLAYEROWNERTYPE = 2, } -export interface BuildItems -{} +export type BuildItems = {}; diff --git a/project/src/models/eft/ragfair/ISendRagfairReportRequestData.ts b/project/src/models/eft/ragfair/ISendRagfairReportRequestData.ts index 424ec0a2..2d14d209 100644 --- a/project/src/models/eft/ragfair/ISendRagfairReportRequestData.ts +++ b/project/src/models/eft/ragfair/ISendRagfairReportRequestData.ts @@ -1,4 +1,3 @@ -export interface ISendRagfairReportRequestData -{ - offerId: number +export interface ISendRagfairReportRequestData { + offerId: number; } diff --git a/project/src/models/eft/ragfair/IStorePlayerOfferTaxAmountRequestData.ts b/project/src/models/eft/ragfair/IStorePlayerOfferTaxAmountRequestData.ts index ab0d0fef..ebf470eb 100644 --- a/project/src/models/eft/ragfair/IStorePlayerOfferTaxAmountRequestData.ts +++ b/project/src/models/eft/ragfair/IStorePlayerOfferTaxAmountRequestData.ts @@ -1,7 +1,6 @@ -export interface IStorePlayerOfferTaxAmountRequestData -{ - id: string - tpl: string - count: number - fee: number +export interface IStorePlayerOfferTaxAmountRequestData { + id: string; + tpl: string; + count: number; + fee: number; } diff --git a/project/src/models/eft/repair/IBaseRepairActionDataRequest.ts b/project/src/models/eft/repair/IBaseRepairActionDataRequest.ts index 7ee92971..e645fb32 100644 --- a/project/src/models/eft/repair/IBaseRepairActionDataRequest.ts +++ b/project/src/models/eft/repair/IBaseRepairActionDataRequest.ts @@ -1,4 +1,3 @@ -export interface IBaseRepairActionDataRequest -{ - Action: string +export interface IBaseRepairActionDataRequest { + Action: string; } diff --git a/project/src/models/eft/repair/IRepairActionDataRequest.ts b/project/src/models/eft/repair/IRepairActionDataRequest.ts index c6f7a096..887df87d 100644 --- a/project/src/models/eft/repair/IRepairActionDataRequest.ts +++ b/project/src/models/eft/repair/IRepairActionDataRequest.ts @@ -1,14 +1,12 @@ import { IBaseRepairActionDataRequest } from "@spt/models/eft/repair/IBaseRepairActionDataRequest"; -export interface IRepairActionDataRequest extends IBaseRepairActionDataRequest -{ - Action: "Repair" - repairKitsInfo: RepairKitsInfo[] - target: string // item to repair +export interface IRepairActionDataRequest extends IBaseRepairActionDataRequest { + Action: "Repair"; + repairKitsInfo: RepairKitsInfo[]; + target: string; // item to repair } -export interface RepairKitsInfo -{ - _id: string // id of repair kit to use - count: number // amout of units to reduce kit by +export interface RepairKitsInfo { + _id: string; // id of repair kit to use + count: number; // amout of units to reduce kit by } diff --git a/project/src/models/eft/repair/ITraderRepairActionDataRequest.ts b/project/src/models/eft/repair/ITraderRepairActionDataRequest.ts index 69bbbf44..9765ff38 100644 --- a/project/src/models/eft/repair/ITraderRepairActionDataRequest.ts +++ b/project/src/models/eft/repair/ITraderRepairActionDataRequest.ts @@ -1,14 +1,12 @@ import { IBaseRepairActionDataRequest } from "@spt/models/eft/repair/IBaseRepairActionDataRequest"; -export interface ITraderRepairActionDataRequest extends IBaseRepairActionDataRequest -{ - Action: "TraderRepair" - tid: string - repairItems: RepairItem[] +export interface ITraderRepairActionDataRequest extends IBaseRepairActionDataRequest { + Action: "TraderRepair"; + tid: string; + repairItems: RepairItem[]; } -export interface RepairItem -{ - _id: string - count: number +export interface RepairItem { + _id: string; + count: number; } diff --git a/project/src/models/eft/trade/IProcessBaseTradeRequestData.ts b/project/src/models/eft/trade/IProcessBaseTradeRequestData.ts index c7f40b7c..a9ef757c 100644 --- a/project/src/models/eft/trade/IProcessBaseTradeRequestData.ts +++ b/project/src/models/eft/trade/IProcessBaseTradeRequestData.ts @@ -1,6 +1,5 @@ -export interface IProcessBaseTradeRequestData -{ - Action: string - type: string - tid: string +export interface IProcessBaseTradeRequestData { + Action: string; + type: string; + tid: string; } diff --git a/project/src/models/eft/trade/IProcessBuyTradeRequestData.ts b/project/src/models/eft/trade/IProcessBuyTradeRequestData.ts index 4abe15e1..154c61c7 100644 --- a/project/src/models/eft/trade/IProcessBuyTradeRequestData.ts +++ b/project/src/models/eft/trade/IProcessBuyTradeRequestData.ts @@ -1,19 +1,17 @@ import { IProcessBaseTradeRequestData } from "@spt/models/eft/trade/IProcessBaseTradeRequestData"; -export interface IProcessBuyTradeRequestData extends IProcessBaseTradeRequestData -{ - Action: "buy_from_trader" | "TradingConfirm" | "RestoreHealth" | "SptInsure" | "SptRepair" | "" - type: string - tid: string - item_id: string - count: number - scheme_id: number - scheme_items: SchemeItem[] +export interface IProcessBuyTradeRequestData extends IProcessBaseTradeRequestData { + Action: "buy_from_trader" | "TradingConfirm" | "RestoreHealth" | "SptInsure" | "SptRepair" | ""; + type: string; + tid: string; + item_id: string; + count: number; + scheme_id: number; + scheme_items: SchemeItem[]; } -export interface SchemeItem -{ +export interface SchemeItem { /** Id of stack to take money from, is money tpl when Action is `SptInsure` */ - id: string - count: number + id: string; + count: number; } diff --git a/project/src/models/eft/trade/IProcessRagfairTradeRequestData.ts b/project/src/models/eft/trade/IProcessRagfairTradeRequestData.ts index 88bc36e2..d7e045e1 100644 --- a/project/src/models/eft/trade/IProcessRagfairTradeRequestData.ts +++ b/project/src/models/eft/trade/IProcessRagfairTradeRequestData.ts @@ -1,18 +1,15 @@ -export interface IProcessRagfairTradeRequestData -{ - Action: string - offers: IOfferRequest[] +export interface IProcessRagfairTradeRequestData { + Action: string; + offers: IOfferRequest[]; } -export interface IOfferRequest -{ - id: string - count: number - items: IItemReqeust[] +export interface IOfferRequest { + id: string; + count: number; + items: IItemReqeust[]; } -export interface IItemReqeust -{ - id: string - count: number +export interface IItemReqeust { + id: string; + count: number; } diff --git a/project/src/models/eft/trade/IProcessSellTradeRequestData.ts b/project/src/models/eft/trade/IProcessSellTradeRequestData.ts index 883b0fd0..a484efdb 100644 --- a/project/src/models/eft/trade/IProcessSellTradeRequestData.ts +++ b/project/src/models/eft/trade/IProcessSellTradeRequestData.ts @@ -1,17 +1,15 @@ import { IProcessBaseTradeRequestData } from "@spt/models/eft/trade/IProcessBaseTradeRequestData"; -export interface IProcessSellTradeRequestData extends IProcessBaseTradeRequestData -{ - Action: "sell_to_trader" - type: string - tid: string - price: number - items: Item[] +export interface IProcessSellTradeRequestData extends IProcessBaseTradeRequestData { + Action: "sell_to_trader"; + type: string; + tid: string; + price: number; + items: Item[]; } -export interface Item -{ - id: string - count: number - scheme_id: number +export interface Item { + id: string; + count: number; + scheme_id: number; } diff --git a/project/src/models/eft/trade/ISellScavItemsToFenceRequestData.ts b/project/src/models/eft/trade/ISellScavItemsToFenceRequestData.ts index 7904974a..30c8d15b 100644 --- a/project/src/models/eft/trade/ISellScavItemsToFenceRequestData.ts +++ b/project/src/models/eft/trade/ISellScavItemsToFenceRequestData.ts @@ -1,9 +1,8 @@ import { OwnerInfo } from "@spt/models/eft/common/request/IBaseInteractionRequestData"; -export interface ISellScavItemsToFenceRequestData -{ - Action: "SellAllFromSavage" - totalValue: number - fromOwner: OwnerInfo - toOwner: OwnerInfo +export interface ISellScavItemsToFenceRequestData { + Action: "SellAllFromSavage"; + totalValue: number; + fromOwner: OwnerInfo; + toOwner: OwnerInfo; } diff --git a/project/src/models/eft/weather/IWeatherData.ts b/project/src/models/eft/weather/IWeatherData.ts index ac3b6c59..900c7a97 100644 --- a/project/src/models/eft/weather/IWeatherData.ts +++ b/project/src/models/eft/weather/IWeatherData.ts @@ -1,27 +1,25 @@ import { Season } from "@spt/models/enums/Season"; import { WindDirection } from "@spt/models/enums/WindDirection"; -export interface IWeatherData -{ - acceleration: number - time: string - date: string - weather: IWeather - season: Season +export interface IWeatherData { + acceleration: number; + time: string; + date: string; + weather: IWeather; + season: Season; } -export interface IWeather -{ - pressure: number - temp: number - fog: number - rain_intensity: number - rain: number - wind_gustiness: number - wind_direction: WindDirection - wind_speed: number - cloud: number - time: string - date: string - timestamp: number +export interface IWeather { + pressure: number; + temp: number; + fog: number; + rain_intensity: number; + rain: number; + wind_gustiness: number; + wind_direction: WindDirection; + wind_speed: number; + cloud: number; + time: string; + date: string; + timestamp: number; } diff --git a/project/src/models/eft/wishlist/IAddToWishlistRequest.ts b/project/src/models/eft/wishlist/IAddToWishlistRequest.ts index 107fe1ba..656f77bc 100644 --- a/project/src/models/eft/wishlist/IAddToWishlistRequest.ts +++ b/project/src/models/eft/wishlist/IAddToWishlistRequest.ts @@ -1,5 +1,4 @@ -export interface IAddToWishlistRequest -{ - Action: string - items: Record +export interface IAddToWishlistRequest { + Action: string; + items: Record; } diff --git a/project/src/models/eft/wishlist/IChangeWishlistItemCategoryRequest.ts b/project/src/models/eft/wishlist/IChangeWishlistItemCategoryRequest.ts index 76c84254..7ce88e0d 100644 --- a/project/src/models/eft/wishlist/IChangeWishlistItemCategoryRequest.ts +++ b/project/src/models/eft/wishlist/IChangeWishlistItemCategoryRequest.ts @@ -1,6 +1,5 @@ -export interface IChangeWishlistItemCategoryRequest -{ - Action: string - item: string - category: number +export interface IChangeWishlistItemCategoryRequest { + Action: string; + item: string; + category: number; } diff --git a/project/src/models/eft/wishlist/IRemoveFromWishlistRequest.ts b/project/src/models/eft/wishlist/IRemoveFromWishlistRequest.ts index 8aca5cab..6a13b1f7 100644 --- a/project/src/models/eft/wishlist/IRemoveFromWishlistRequest.ts +++ b/project/src/models/eft/wishlist/IRemoveFromWishlistRequest.ts @@ -1,5 +1,4 @@ -export interface IRemoveFromWishlistRequest -{ - Action: string - items: string[] +export interface IRemoveFromWishlistRequest { + Action: string; + items: string[]; } diff --git a/project/src/models/eft/ws/IWsAid.ts b/project/src/models/eft/ws/IWsAid.ts index 69fe7d2f..b2a05c3f 100644 --- a/project/src/models/eft/ws/IWsAid.ts +++ b/project/src/models/eft/ws/IWsAid.ts @@ -1,6 +1,5 @@ import { IWsNotificationEvent } from "@spt/models/eft/ws/IWsNotificationEvent"; -export interface IWsAid extends IWsNotificationEvent -{ - aid: number +export interface IWsAid extends IWsNotificationEvent { + aid: number; } diff --git a/project/src/models/eft/ws/IWsAidNickname.ts b/project/src/models/eft/ws/IWsAidNickname.ts index 3dd74dcd..bd9f04b5 100644 --- a/project/src/models/eft/ws/IWsAidNickname.ts +++ b/project/src/models/eft/ws/IWsAidNickname.ts @@ -1,7 +1,6 @@ import { IWsNotificationEvent } from "@spt/models/eft/ws/IWsNotificationEvent"; -export interface IWsAidNickname extends IWsNotificationEvent -{ - aid: number - Nickname: string +export interface IWsAidNickname extends IWsNotificationEvent { + aid: number; + Nickname: string; } diff --git a/project/src/models/eft/ws/IWsChatMessageReceived.ts b/project/src/models/eft/ws/IWsChatMessageReceived.ts index 959cc4c3..41a3b8a9 100644 --- a/project/src/models/eft/ws/IWsChatMessageReceived.ts +++ b/project/src/models/eft/ws/IWsChatMessageReceived.ts @@ -2,9 +2,8 @@ import { IGroupCharacter } from "@spt/models/eft/match/IGroupCharacter"; import { Message } from "@spt/models/eft/profile/ISptProfile"; import { IWsNotificationEvent } from "@spt/models/eft/ws/IWsNotificationEvent"; -export interface IWsChatMessageReceived extends IWsNotificationEvent -{ - dialogId: string - message: Message - profiles?: IGroupCharacter[] +export interface IWsChatMessageReceived extends IWsNotificationEvent { + dialogId: string; + message: Message; + profiles?: IGroupCharacter[]; } diff --git a/project/src/models/eft/ws/IWsGroupId.ts b/project/src/models/eft/ws/IWsGroupId.ts index 864e83ae..1b92cc56 100644 --- a/project/src/models/eft/ws/IWsGroupId.ts +++ b/project/src/models/eft/ws/IWsGroupId.ts @@ -1,6 +1,5 @@ import { IWsNotificationEvent } from "@spt/models/eft/ws/IWsNotificationEvent"; -export interface IWsGroupId extends IWsNotificationEvent -{ - groupId: string +export interface IWsGroupId extends IWsNotificationEvent { + groupId: string; } diff --git a/project/src/models/eft/ws/IWsGroupMatchInviteAccept.ts b/project/src/models/eft/ws/IWsGroupMatchInviteAccept.ts index 1456580b..d001af4d 100644 --- a/project/src/models/eft/ws/IWsGroupMatchInviteAccept.ts +++ b/project/src/models/eft/ws/IWsGroupMatchInviteAccept.ts @@ -1,5 +1,4 @@ import { IGroupCharacter } from "@spt/models/eft/match/IGroupCharacter"; import { IWsNotificationEvent } from "@spt/models/eft/ws/IWsNotificationEvent"; -export interface IWsGroupMatchInviteAccept extends IWsNotificationEvent, IGroupCharacter -{} +export interface IWsGroupMatchInviteAccept extends IWsNotificationEvent, IGroupCharacter {} diff --git a/project/src/models/eft/ws/IWsGroupMatchInviteDecline.ts b/project/src/models/eft/ws/IWsGroupMatchInviteDecline.ts index fc776eea..e62a6eae 100644 --- a/project/src/models/eft/ws/IWsGroupMatchInviteDecline.ts +++ b/project/src/models/eft/ws/IWsGroupMatchInviteDecline.ts @@ -1,7 +1,6 @@ import { IWsNotificationEvent } from "@spt/models/eft/ws/IWsNotificationEvent"; -export interface IWsGroupMatchInviteDecline extends IWsNotificationEvent -{ - aid: number - Nickname: string +export interface IWsGroupMatchInviteDecline extends IWsNotificationEvent { + aid: number; + Nickname: string; } diff --git a/project/src/models/eft/ws/IWsGroupMatchInviteSend.ts b/project/src/models/eft/ws/IWsGroupMatchInviteSend.ts index 2f88c351..2b7f608f 100644 --- a/project/src/models/eft/ws/IWsGroupMatchInviteSend.ts +++ b/project/src/models/eft/ws/IWsGroupMatchInviteSend.ts @@ -1,9 +1,8 @@ import { IGroupCharacter } from "@spt/models/eft/match/IGroupCharacter"; import { IWsNotificationEvent } from "@spt/models/eft/ws/IWsNotificationEvent"; -export interface IWsGroupMatchInviteSend extends IWsNotificationEvent -{ - requestId: string - from: number - members: IGroupCharacter[] +export interface IWsGroupMatchInviteSend extends IWsNotificationEvent { + requestId: string; + from: number; + members: IGroupCharacter[]; } diff --git a/project/src/models/eft/ws/IWsGroupMatchLeaderChanged.ts b/project/src/models/eft/ws/IWsGroupMatchLeaderChanged.ts index fd133aa4..db6fe805 100644 --- a/project/src/models/eft/ws/IWsGroupMatchLeaderChanged.ts +++ b/project/src/models/eft/ws/IWsGroupMatchLeaderChanged.ts @@ -1,6 +1,5 @@ import { IWsNotificationEvent } from "@spt/models/eft/ws/IWsNotificationEvent"; -export interface IWsGroupMatchLeaderChanged extends IWsNotificationEvent -{ - owner: number +export interface IWsGroupMatchLeaderChanged extends IWsNotificationEvent { + owner: number; } diff --git a/project/src/models/eft/ws/IWsGroupMatchRaidReady.ts b/project/src/models/eft/ws/IWsGroupMatchRaidReady.ts index 6d5cda19..e5d7dfa7 100644 --- a/project/src/models/eft/ws/IWsGroupMatchRaidReady.ts +++ b/project/src/models/eft/ws/IWsGroupMatchRaidReady.ts @@ -1,7 +1,6 @@ import { IGroupCharacter } from "@spt/models/eft/match/IGroupCharacter"; import { IWsNotificationEvent } from "@spt/models/eft/ws/IWsNotificationEvent"; -export interface IWsGroupMatchRaidReady extends IWsNotificationEvent -{ - extendedProfile: IGroupCharacter +export interface IWsGroupMatchRaidReady extends IWsNotificationEvent { + extendedProfile: IGroupCharacter; } diff --git a/project/src/models/eft/ws/IWsGroupMatchRaidSettings.ts b/project/src/models/eft/ws/IWsGroupMatchRaidSettings.ts index 3629b903..cc8ba4bb 100644 --- a/project/src/models/eft/ws/IWsGroupMatchRaidSettings.ts +++ b/project/src/models/eft/ws/IWsGroupMatchRaidSettings.ts @@ -1,7 +1,6 @@ import { IRaidSettings } from "@spt/models/eft/match/IRaidSettings"; import { IWsNotificationEvent } from "@spt/models/eft/ws/IWsNotificationEvent"; -export interface IWsGroupMatchRaidSettings extends IWsNotificationEvent -{ - raidSettings: IRaidSettings +export interface IWsGroupMatchRaidSettings extends IWsNotificationEvent { + raidSettings: IRaidSettings; } diff --git a/project/src/models/eft/ws/IWsNotificationEvent.ts b/project/src/models/eft/ws/IWsNotificationEvent.ts index 5346f44e..5fc72f3a 100644 --- a/project/src/models/eft/ws/IWsNotificationEvent.ts +++ b/project/src/models/eft/ws/IWsNotificationEvent.ts @@ -1,5 +1,4 @@ -export interface IWsNotificationEvent -{ - type: string - eventId: string +export interface IWsNotificationEvent { + type: string; + eventId: string; } diff --git a/project/src/models/eft/ws/IWsPing.ts b/project/src/models/eft/ws/IWsPing.ts index 7275213b..fc37aa40 100644 --- a/project/src/models/eft/ws/IWsPing.ts +++ b/project/src/models/eft/ws/IWsPing.ts @@ -1,4 +1,3 @@ import { IWsNotificationEvent } from "@spt/models/eft/ws/IWsNotificationEvent"; -export interface IWsPing extends IWsNotificationEvent -{} +export interface IWsPing extends IWsNotificationEvent {} diff --git a/project/src/models/eft/ws/IWsRagfairOfferSold.ts b/project/src/models/eft/ws/IWsRagfairOfferSold.ts index 927b6bc6..f8710683 100644 --- a/project/src/models/eft/ws/IWsRagfairOfferSold.ts +++ b/project/src/models/eft/ws/IWsRagfairOfferSold.ts @@ -1,8 +1,7 @@ import { IWsNotificationEvent } from "@spt/models/eft/ws/IWsNotificationEvent"; -export interface IWsRagfairOfferSold extends IWsNotificationEvent -{ - offerId: string - count: number - handbookId: string +export interface IWsRagfairOfferSold extends IWsNotificationEvent { + offerId: string; + count: number; + handbookId: string; } diff --git a/project/src/models/eft/ws/IWsUserConfirmed.ts b/project/src/models/eft/ws/IWsUserConfirmed.ts index 7b2ed72c..a9b20ff6 100644 --- a/project/src/models/eft/ws/IWsUserConfirmed.ts +++ b/project/src/models/eft/ws/IWsUserConfirmed.ts @@ -2,18 +2,17 @@ import { IWsNotificationEvent } from "@spt/models/eft/ws/IWsNotificationEvent"; import { ProfileStatus } from "@spt/models/enums/ProfileStatus"; import { RaidMode } from "@spt/models/enums/RaidMode"; -export interface IWsUserConfirmed extends IWsNotificationEvent -{ - profileid: string - profileToken: string - status: ProfileStatus - ip: string - port: number - sid: string - version: string - location: string - raidMode: RaidMode - mode: string - shortId: string - additional_info: any[] +export interface IWsUserConfirmed extends IWsNotificationEvent { + profileid: string; + profileToken: string; + status: ProfileStatus; + ip: string; + port: number; + sid: string; + version: string; + location: string; + raidMode: RaidMode; + mode: string; + shortId: string; + additional_info: any[]; } diff --git a/project/src/models/enums/AccountTypes.ts b/project/src/models/enums/AccountTypes.ts index 991d0f8c..f3a533a8 100644 --- a/project/src/models/enums/AccountTypes.ts +++ b/project/src/models/enums/AccountTypes.ts @@ -1,4 +1,3 @@ -export enum AccountTypes -{ +export enum AccountTypes { SPT_DEVELOPER = "spt developer", } diff --git a/project/src/models/enums/AirdropType.ts b/project/src/models/enums/AirdropType.ts index 6a2c3dc0..16d016d5 100644 --- a/project/src/models/enums/AirdropType.ts +++ b/project/src/models/enums/AirdropType.ts @@ -1,5 +1,4 @@ -export enum AirdropTypeEnum -{ +export enum AirdropTypeEnum { COMMON = "common", SUPPLY = "supply", MEDICAL = "medical", diff --git a/project/src/models/enums/AmmoTypes.ts b/project/src/models/enums/AmmoTypes.ts index 3de62124..bd4b3ba1 100644 --- a/project/src/models/enums/AmmoTypes.ts +++ b/project/src/models/enums/AmmoTypes.ts @@ -1,5 +1,4 @@ -export enum Grenade -{ +export enum Grenade { M386_HE_GRENADE = "5ede475b549eed7c6d5c18fb", M576_MP_APERS_GRENADE = "5ede475339ee016e8c534742", M433_HEDP_GRENADE = "5f0c892565703e5c461894e9", @@ -8,8 +7,7 @@ export enum Grenade M441_HE_GRENADE = "5ede47405b097655935d7d16", } -export enum Ammo762x51 -{ +export enum Ammo762x51 { M62_TRACER = "5a608bf24f39f98ffc77720e", M80 = "58dd3ad986f77403051cba8f", M61 = "5a6086ea4f39f99cd479502f", @@ -19,8 +17,7 @@ export enum Ammo762x51 M993 = "5efb0c1bd79ff02a1f5e68d9", } -export enum Ammo762x54 -{ +export enum Ammo762x54 { SNB_GZH = "560d61e84bdc2da74d8b4571", LPS_GZH = "5887431f2459777e1612938f", PS_GZH = "59e77a2386f7742ee578960a", @@ -32,16 +29,14 @@ export enum Ammo762x54 HP_BT = "64b8f7c241772715af0f9c3d", } -export enum Ammo86x70 -{ +export enum Ammo86x70 { TAC_X = "5fc382b6d6fa9c00c571bbc3", UCW = "5fc382c1016cce60e8341b20", AP = "5fc382a9d724d907e2077dab", FMJ = "5fc275cf85fd526b824a571a", } -export enum Ammo46x30 -{ +export enum Ammo46x30 { AP_SX = "5ba26835d4351e0035628ff5", ACTION_SX = "5ba26812d4351e003201fef1", FMJ_SX = "5ba2678ad4351e44f824b344", @@ -49,8 +44,7 @@ export enum Ammo46x30 JSP_SX = "64b6979341772715af0f9c39", } -export enum Ammo57x28 -{ +export enum Ammo57x28 { SS198LF = "5cc80f79e4a949033c7343b2", R37_F = "5cc86832d7f00c000d3a6e6c", SS190 = "5cc80f38e4a949001152b560", @@ -60,8 +54,7 @@ export enum Ammo57x28 SB193 = "5cc80f67e4a949035e43bbba", } -export enum Ammo762x25 -{ +export enum Ammo762x25 { FMJ43 = "5735ff5c245977640e39ba7e", LRN = "573601b42459776410737435", P_GL = "5736026a245977644601dc61", @@ -71,8 +64,7 @@ export enum Ammo762x25 PT_GZH = "573603c924597764442bd9cb", } -export enum Ammo9x18 -{ +export enum Ammo9x18 { PM_SP8_GZH = "5737218f245977612125ba51", P_GZH = "573719762459775a626ccbc1", PSTM_GZH = "57371aab2459775a77142f22", @@ -89,8 +81,7 @@ export enum Ammo9x18 PPE_GZH = "57371b192459775a9f58a5e0", } -export enum Ammo9x19 -{ +export enum Ammo9x19 { PSO_GZH = "58864a4f2459770fcc257101", PST_GZH = "56d59d3ad2720bdb418b4577", GREEN_TRACER = "5c3df7d588a4501f290594e5", @@ -102,24 +93,21 @@ export enum Ammo9x19 FMJ_M882 = "64b7bbb74b75259c590fa897", } -export enum Ammo9x21 -{ +export enum Ammo9x21 { P_GZH = "5a26abfac4a28232980eabff", PS_GZH = "5a269f97c4a282000b151807", PE_GZH = "5a26ac06c4a282000c5a90a8", BT_GZH = "5a26ac0ec4a28200741e1e18", } -export enum Ammo9x33R -{ +export enum Ammo9x33R { FMJ = "62330b3ed4dc74626d570b95", HOLLOW_POINT = "62330bfadc5883093563729b", SOFT_POINT = "62330c40bdd19b369e1e53d1", JACKET_HP = "62330c18744e5e31df12f516", } -export enum Ammo1143x23ACP -{ +export enum Ammo1143x23ACP { MATCH_FMJ = "5e81f423763d9f754677bf2e", HYDRA_SHOK = "5efb0fc6aeb21837e749c801", LASERMATCH_FMJ = "5efb0d4f4bc50b58e81710f3", @@ -127,8 +115,7 @@ export enum Ammo1143x23ACP RIP = "5ea2a8e200685063ec28c05a", } -export enum Ammo545x39 -{ +export enum Ammo545x39 { PS_GS = "56dff3afd2720bba668b4567", SP = "56dff421d2720b5f5a8b4567", PPBS_GS_IGOLNIK = "5c0d5e4486f77478390952fe", @@ -144,8 +131,7 @@ export enum Ammo545x39 FMJ = "56dff0bed2720bb0668b4567", } -export enum Ammo556x45 -{ +export enum Ammo556x45 { M856 = "59e68f6f86f7746c9f75e846", MK255_MOD_0_RRLP = "59e6918f86f7746c9f75e849", M995 = "59e690b686f7746c9f75e848", @@ -159,8 +145,7 @@ export enum Ammo556x45 SSA_AP = "601949593ae8f707c4608daa", } -export enum Ammo762x35 -{ +export enum Ammo762x35 { M62_TRACER = "619636be6db0f2477964e710", BCP_FMJ = "5fbe3ffdf8b6a877a729ea82", AP = "5fd20ff893a8961fc660a954", @@ -169,8 +154,7 @@ export enum Ammo762x35 CBJ = "64b8725c4b75259c590fa899", } -export enum Ammo762x39 -{ +export enum Ammo762x39 { PS_GZH = "5656d7c34bdc2d9d198b4587", HP = "59e4d3d286f774176a36250a", US_GZH = "59e4d24686f7741776641ac7", @@ -182,8 +166,7 @@ export enum Ammo762x39 FMJ = "64b7af5a8532cf95ee0a0dbd", } -export enum Ammo9x39 -{ +export enum Ammo9x39 { SP5_GS = "57a0dfb82459774d3078b56c", BP_GS = "5c0d688c86f77413ae3407b2", SP6_GS = "57a0e5022459774d1673f889", @@ -191,23 +174,20 @@ export enum Ammo9x39 PAB9_GS = "61962d879bb3d20b0946d385", } -export enum Ammo366TKM -{ +export enum Ammo366TKM { FMJ = "59e6542b86f77411dc52a77a", GEKSA = "59e6658b86f77411d949b250", EKO = "59e655cb86f77411dc52a77b", APM = "5f0596629e22f464da6bbdd9", } -export enum Ammo127x55 -{ +export enum Ammo127x55 { PS12 = "5cadf6ddae9215051e1c23b2", PS12B = "5cadf6eeae921500134b2799", PS12A = "5cadf6e5ae921500113bb973", } -export enum Ammo12Gauge -{ +export enum Ammo12Gauge { BUCKSHOT_7MM = "560d5e524bdc2d25448b4571", MAGNUM_85MM = "5d6e6806a4b936088465b17e", RIP = "5c0d591486f7744c505b416f", @@ -227,8 +207,7 @@ export enum Ammo12Gauge PIRANHA = "64b8ee384b75259c590fa89b", } -export enum Ammo20Gauge -{ +export enum Ammo20Gauge { BUCKSHOT_75MM = "5a38ebd9c4a282000d722a5b", STAR_SLUG = "5d6e6a05a4b93618084f58d0", BUCKSHOT_73MM = "5d6e69c7a4b9360b6c0d54e4", @@ -239,35 +218,30 @@ export enum Ammo20Gauge BUCKSHOT_62MM = "5d6e69b9a4b9361bc8618958", } -export enum Ammo23x75 -{ +export enum Ammo23x75 { SHRAPNEL10_BUCKSHOT = "5e85a9a6eacf8c039e4e2ac1", SHRAPNEL25_BUCKSHOT = "5f647f31b6238e5dd066e196", ZVEZDA_FLASHBANG = "5e85a9f4add9fe03027d9bf1", BARRIKADA_SLUG = "5e85aa1a988a8701445df1f5", } -export enum Ammo30x29 -{ +export enum Ammo30x29 { VOG_30 = "5d70e500a4b9364de70d38ce", } -export enum Ammo127x108 -{ +export enum Ammo127x108 { B32 = "5cde8864d7f00c0010373be1", BZT_44M = "5d2f2ab648f03550091993ca", } -export enum Ammo26x75 -{ +export enum Ammo26x75 { GREEN_FLARE = "62389aaba63f32501b1b444f", RED_FLARE = "62389ba9a63f32501b1b4451", WHITE_FLARE = "62389bc9423ed1685422dc57", YELLOW_FLARE = "62389be94d5d474bf712e709", } -export enum Ammo68x51 -{ +export enum Ammo68x51 { SIG_FMJ = "6529302b8c26af6326029fb7", SIG_HYBRID = "6529243824cbe3c74a05e5c1", } diff --git a/project/src/models/enums/BackendErrorCodes.ts b/project/src/models/enums/BackendErrorCodes.ts index 3a9eff12..85c2fbe6 100644 --- a/project/src/models/enums/BackendErrorCodes.ts +++ b/project/src/models/enums/BackendErrorCodes.ts @@ -1,5 +1,4 @@ -export enum BackendErrorCodes -{ +export enum BackendErrorCodes { NONE = 0, UNKNOWN_ERROR = 200, NOT_AUTHORIZED = 201, diff --git a/project/src/models/enums/BaseClasses.ts b/project/src/models/enums/BaseClasses.ts index be37671b..0401f0cd 100644 --- a/project/src/models/enums/BaseClasses.ts +++ b/project/src/models/enums/BaseClasses.ts @@ -1,5 +1,4 @@ -export enum BaseClasses -{ +export enum BaseClasses { WEAPON = "5422acb9af1c889c16000029", UBGL = "55818b014bdc2ddc698b456b", ARMOR = "5448e54d4bdc2dcc718b4568", diff --git a/project/src/models/enums/BonusSkillType.ts b/project/src/models/enums/BonusSkillType.ts index d5621122..ff9d363f 100644 --- a/project/src/models/enums/BonusSkillType.ts +++ b/project/src/models/enums/BonusSkillType.ts @@ -1,5 +1,4 @@ -export enum BonusSkillType -{ +export enum BonusSkillType { PHYSICAL = "Physical", COMBAT = "Combat", SPECIAL = "Special", diff --git a/project/src/models/enums/BonusType.ts b/project/src/models/enums/BonusType.ts index 20a59a2e..cf32b362 100644 --- a/project/src/models/enums/BonusType.ts +++ b/project/src/models/enums/BonusType.ts @@ -1,5 +1,4 @@ -export enum BonusType -{ +export enum BonusType { ENERGY_REGENERATION = "EnergyRegeneration", HYDRATION_REGENERATION = "HydrationRegeneration", HEALTH_REGENERATION = "HealthRegeneration", diff --git a/project/src/models/enums/ConfigTypes.ts b/project/src/models/enums/ConfigTypes.ts index a229758e..ccf880d2 100644 --- a/project/src/models/enums/ConfigTypes.ts +++ b/project/src/models/enums/ConfigTypes.ts @@ -1,5 +1,4 @@ -export enum ConfigTypes -{ +export enum ConfigTypes { AIRDROP = "spt-airdrop", BOT = "spt-bot", PMC = "spt-pmc", diff --git a/project/src/models/enums/ContainerTypes.ts b/project/src/models/enums/ContainerTypes.ts index 8f4de42b..536e84c3 100644 --- a/project/src/models/enums/ContainerTypes.ts +++ b/project/src/models/enums/ContainerTypes.ts @@ -1,5 +1,4 @@ -export enum CommonContainers -{ +export enum CommonContainers { AMMO_CASE = "5aafbde786f774389d0cbc0f", DOCUMENTS_CASE = "590c60fc86f77412b13fddcf", DOGTAG_CASE = "5c093e3486f77430cb02e593", @@ -22,8 +21,7 @@ export enum CommonContainers WZ_WALLET = "60b0f6c058e0b0481a09ad11", } -export enum SecuredContainers -{ +export enum SecuredContainers { ALPHA = "544a11ac4bdc2d470e8b456a", BETA = "5857a8b324597729ab0a0e7d", EPSILON = "59db794186f77448bc595262", diff --git a/project/src/models/enums/DateTime.ts b/project/src/models/enums/DateTime.ts index 5c00969a..24ba6844 100644 --- a/project/src/models/enums/DateTime.ts +++ b/project/src/models/enums/DateTime.ts @@ -1,5 +1,4 @@ -export enum DateTime -{ +export enum DateTime { CURR = "CURR", PAST = "PAST", } diff --git a/project/src/models/enums/DogtagExchangeSide.ts b/project/src/models/enums/DogtagExchangeSide.ts index 425827a5..2179db1a 100644 --- a/project/src/models/enums/DogtagExchangeSide.ts +++ b/project/src/models/enums/DogtagExchangeSide.ts @@ -1,5 +1,4 @@ -export enum DogtagExchangeSide -{ +export enum DogtagExchangeSide { USEC = "Usec", BEAR = "Bear", ANY = "Any", diff --git a/project/src/models/enums/ELocationName.ts b/project/src/models/enums/ELocationName.ts index f51bf3fb..17b4efcb 100644 --- a/project/src/models/enums/ELocationName.ts +++ b/project/src/models/enums/ELocationName.ts @@ -1,5 +1,4 @@ -export enum ELocationName -{ +export enum ELocationName { FACTORY_DAY = "factory4_day", FACTORY_NIGHT = "factory4_night", BIGMAP = "bigmap", diff --git a/project/src/models/enums/EquipmentBuildType.ts b/project/src/models/enums/EquipmentBuildType.ts index f309a9ea..ff9709a4 100644 --- a/project/src/models/enums/EquipmentBuildType.ts +++ b/project/src/models/enums/EquipmentBuildType.ts @@ -1,5 +1,4 @@ -export enum EquipmentBuildType -{ +export enum EquipmentBuildType { CUSTOM = 0, STANDARD = 1, } diff --git a/project/src/models/enums/EquipmentSlots.ts b/project/src/models/enums/EquipmentSlots.ts index 510e97be..eea71c70 100644 --- a/project/src/models/enums/EquipmentSlots.ts +++ b/project/src/models/enums/EquipmentSlots.ts @@ -1,5 +1,4 @@ -export enum EquipmentSlots -{ +export enum EquipmentSlots { HEADWEAR = "Headwear", EARPIECE = "Earpiece", FACE_COVER = "FaceCover", diff --git a/project/src/models/enums/ExitStatis.ts b/project/src/models/enums/ExitStatis.ts index 547afa60..fd020762 100644 --- a/project/src/models/enums/ExitStatis.ts +++ b/project/src/models/enums/ExitStatis.ts @@ -1,5 +1,4 @@ -export enum ExitStatus -{ +export enum ExitStatus { SURVIVED = 0, KILLED = 1, LEFT = 2, diff --git a/project/src/models/enums/FleaOfferType.ts b/project/src/models/enums/FleaOfferType.ts index 6b9f9e6a..24ebaefd 100644 --- a/project/src/models/enums/FleaOfferType.ts +++ b/project/src/models/enums/FleaOfferType.ts @@ -1,7 +1,6 @@ -export enum FleaOfferType -{ - SINGLE, - MULTI, - PACK, - UNKNOWN, +export enum FleaOfferType { + SINGLE = 0, + MULTI = 1, + PACK = 2, + UNKNOWN = 3, } diff --git a/project/src/models/enums/GameEditions.ts b/project/src/models/enums/GameEditions.ts index 65d77a30..cc4dee68 100644 --- a/project/src/models/enums/GameEditions.ts +++ b/project/src/models/enums/GameEditions.ts @@ -1,5 +1,4 @@ -export enum GameEditions -{ +export enum GameEditions { STANDARD = "standard", LEFT_BEHIND = "left_behind", PREPARE_FOR_ESCAPE = "prepare_for_escape", diff --git a/project/src/models/enums/GiftSenderType.ts b/project/src/models/enums/GiftSenderType.ts index 9bf3f3a2..273d76d2 100644 --- a/project/src/models/enums/GiftSenderType.ts +++ b/project/src/models/enums/GiftSenderType.ts @@ -1,5 +1,4 @@ -export enum GiftSenderType -{ +export enum GiftSenderType { SYSTEM = "System", TRADER = "Trader", USER = "User", diff --git a/project/src/models/enums/GiftSentResult.ts b/project/src/models/enums/GiftSentResult.ts index 3e68390c..dbd092bc 100644 --- a/project/src/models/enums/GiftSentResult.ts +++ b/project/src/models/enums/GiftSentResult.ts @@ -1,5 +1,4 @@ -export enum GiftSentResult -{ +export enum GiftSentResult { FAILED_UNKNOWN = 1, FAILED_GIFT_ALREADY_RECEIVED = 2, FAILED_GIFT_DOESNT_EXIST = 3, diff --git a/project/src/models/enums/HideoutAreas.ts b/project/src/models/enums/HideoutAreas.ts index ba46a3cf..9573797a 100644 --- a/project/src/models/enums/HideoutAreas.ts +++ b/project/src/models/enums/HideoutAreas.ts @@ -1,5 +1,4 @@ -export enum HideoutAreas -{ +export enum HideoutAreas { NOTSET = -1, VENTS = 0, SECURITY = 1, diff --git a/project/src/models/enums/HideoutEventActions.ts b/project/src/models/enums/HideoutEventActions.ts index 4037bdf0..514e029f 100644 --- a/project/src/models/enums/HideoutEventActions.ts +++ b/project/src/models/enums/HideoutEventActions.ts @@ -1,5 +1,4 @@ -export enum HideoutEventActions -{ +export enum HideoutEventActions { HIDEOUT_UPGRADE = "HideoutUpgrade", HIDEOUT_UPGRADE_COMPLETE = "HideoutUpgradeComplete", HIDEOUT_PUT_ITEMS_IN_AREA_SLOTS = "HideoutPutItemsInAreaSlots", diff --git a/project/src/models/enums/ItemAddedResult.ts b/project/src/models/enums/ItemAddedResult.ts index baabe97f..54135157 100644 --- a/project/src/models/enums/ItemAddedResult.ts +++ b/project/src/models/enums/ItemAddedResult.ts @@ -1,5 +1,4 @@ -export enum ItemAddedResult -{ +export enum ItemAddedResult { UNKNOWN = -1, SUCCESS = 1, NO_SPACE = 2, diff --git a/project/src/models/enums/ItemEventActions.ts b/project/src/models/enums/ItemEventActions.ts index 0d573114..d12efe6d 100644 --- a/project/src/models/enums/ItemEventActions.ts +++ b/project/src/models/enums/ItemEventActions.ts @@ -1,5 +1,4 @@ -export enum ItemEventActions -{ +export enum ItemEventActions { MOVE = "Move", REMOVE = "Remove", SPLIT = "Split", diff --git a/project/src/models/enums/ItemTpl.ts b/project/src/models/enums/ItemTpl.ts index 5be3fa2c..04adadd0 100644 --- a/project/src/models/enums/ItemTpl.ts +++ b/project/src/models/enums/ItemTpl.ts @@ -1,6 +1,5 @@ // This is an auto generated file, do not modify. Re-generate with `npm run gen:items` -export enum ItemTpl -{ +export enum ItemTpl { AMMOBOX_127X55_PS12A_10RND = "65702420bfc87b3a34093219", AMMOBOX_127X55_PS12B_10RND = "648983d6b5a2df1c815a04ec", AMMOBOX_127X55_PS12_10RND = "6570241bcfc010a0f50069f5", diff --git a/project/src/models/enums/MemberCategory.ts b/project/src/models/enums/MemberCategory.ts index ac98d8c8..6a57b3a7 100644 --- a/project/src/models/enums/MemberCategory.ts +++ b/project/src/models/enums/MemberCategory.ts @@ -1,5 +1,4 @@ -export enum MemberCategory -{ // player type +export enum MemberCategory { // player type DEFAULT = 0, DEVELOPER = 1, UNIQUE_ID = 2, diff --git a/project/src/models/enums/MessageType.ts b/project/src/models/enums/MessageType.ts index 0bbffa52..9716e9a8 100644 --- a/project/src/models/enums/MessageType.ts +++ b/project/src/models/enums/MessageType.ts @@ -1,5 +1,4 @@ -export enum MessageType -{ +export enum MessageType { // if this variables are supposed to be strings for the type // then the equals value should be the name that should be // required by the client instead of an int diff --git a/project/src/models/enums/ModSpawn.ts b/project/src/models/enums/ModSpawn.ts index 9a450295..ec37c297 100644 --- a/project/src/models/enums/ModSpawn.ts +++ b/project/src/models/enums/ModSpawn.ts @@ -1,5 +1,4 @@ -export enum ModSpawn -{ +export enum ModSpawn { /** Chosen mod should be the tpl from the default weapon template */ DEFAULT_MOD = 0, /** Normal behaviour */ diff --git a/project/src/models/enums/Money.ts b/project/src/models/enums/Money.ts index 3583b286..ad09f9df 100644 --- a/project/src/models/enums/Money.ts +++ b/project/src/models/enums/Money.ts @@ -1,5 +1,4 @@ -export enum Money -{ +export enum Money { ROUBLES = "5449016a4bdc2d6f028b456f", EUROS = "569668774bdc2da2298b4568", DOLLARS = "5696686a4bdc2da3298b456a", diff --git a/project/src/models/enums/NotificationEventType.ts b/project/src/models/enums/NotificationEventType.ts index 10d947d8..216184c1 100644 --- a/project/src/models/enums/NotificationEventType.ts +++ b/project/src/models/enums/NotificationEventType.ts @@ -1,5 +1,4 @@ -export enum NotificationEventType -{ +export enum NotificationEventType { ASSORTMENT_UNLOCK_RULE = "AssortmentUnlockRule", EXAMINE_ITEMS = "ExamineItems", EXAMINE_ALL_ITEMS = "ExamineAllItems", diff --git a/project/src/models/enums/PlayerRaidEndState.ts b/project/src/models/enums/PlayerRaidEndState.ts index bb170ca2..c265667d 100644 --- a/project/src/models/enums/PlayerRaidEndState.ts +++ b/project/src/models/enums/PlayerRaidEndState.ts @@ -1,5 +1,4 @@ -export enum PlayerRaidEndState -{ +export enum PlayerRaidEndState { SURVIVED = "survived", LEFT = "left", RUNNER = "runner", diff --git a/project/src/models/enums/PlayersSpawnPlace.ts b/project/src/models/enums/PlayersSpawnPlace.ts index f0263d3c..69276ef6 100644 --- a/project/src/models/enums/PlayersSpawnPlace.ts +++ b/project/src/models/enums/PlayersSpawnPlace.ts @@ -1,5 +1,4 @@ -export enum PlayersSpawnPlace -{ +export enum PlayersSpawnPlace { SAME_PLACE = "SamePlace", DIFFERENT_PLACES = "DifferentPlaces", AT_THE_ENDS_OF_THE_MAP = "AtTheEndsOfTheMap", diff --git a/project/src/models/enums/ProfileStatus.ts b/project/src/models/enums/ProfileStatus.ts index 4d61d105..6f4bf3ba 100644 --- a/project/src/models/enums/ProfileStatus.ts +++ b/project/src/models/enums/ProfileStatus.ts @@ -1,5 +1,4 @@ -export enum ProfileStatus -{ +export enum ProfileStatus { FREE = "Free", MATCH_WAIT = "MatchWait", BUSY = "Busy", diff --git a/project/src/models/enums/QuestRewardType.ts b/project/src/models/enums/QuestRewardType.ts index 0b3daf2e..4d9c46ca 100644 --- a/project/src/models/enums/QuestRewardType.ts +++ b/project/src/models/enums/QuestRewardType.ts @@ -1,5 +1,4 @@ -export enum QuestRewardType -{ +export enum QuestRewardType { SKILL = "Skill", EXPERIENCE = "Experience", TRADER_STANDING = "TraderStanding", diff --git a/project/src/models/enums/QuestStatus.ts b/project/src/models/enums/QuestStatus.ts index 0de74a90..aa7628be 100644 --- a/project/src/models/enums/QuestStatus.ts +++ b/project/src/models/enums/QuestStatus.ts @@ -1,5 +1,4 @@ -export enum QuestStatus -{ +export enum QuestStatus { Locked = 0, AvailableForStart = 1, Started = 2, diff --git a/project/src/models/enums/QuestTypeEnum.ts b/project/src/models/enums/QuestTypeEnum.ts index c26eae7a..9386a6a8 100644 --- a/project/src/models/enums/QuestTypeEnum.ts +++ b/project/src/models/enums/QuestTypeEnum.ts @@ -1,5 +1,4 @@ -export enum QuestTypeEnum -{ +export enum QuestTypeEnum { PICKUP = "PickUp", ELIMINATION = "Elimination", DISCOVER = "Discover", diff --git a/project/src/models/enums/RagfairSort.ts b/project/src/models/enums/RagfairSort.ts index 5889e606..6540d0af 100644 --- a/project/src/models/enums/RagfairSort.ts +++ b/project/src/models/enums/RagfairSort.ts @@ -1,5 +1,4 @@ -export enum RagfairSort -{ +export enum RagfairSort { ID = 0, BARTER = 2, RATING = 3, diff --git a/project/src/models/enums/RaidMode.ts b/project/src/models/enums/RaidMode.ts index 2d9ac5aa..ec1274a3 100644 --- a/project/src/models/enums/RaidMode.ts +++ b/project/src/models/enums/RaidMode.ts @@ -1,5 +1,4 @@ -export enum RaidMode -{ +export enum RaidMode { ONLINE = "Online", LOCAL = "Local", COOP = "Coop", diff --git a/project/src/models/enums/RaidSettings/BotAmount.ts b/project/src/models/enums/RaidSettings/BotAmount.ts index dd13559f..4268e8c3 100644 --- a/project/src/models/enums/RaidSettings/BotAmount.ts +++ b/project/src/models/enums/RaidSettings/BotAmount.ts @@ -1,5 +1,4 @@ -export enum BotAmount -{ +export enum BotAmount { AS_ONLINE = "AsOnline", NO_BOTS = "NoBots", LOW = "Low", diff --git a/project/src/models/enums/RaidSettings/BotDifficulty.ts b/project/src/models/enums/RaidSettings/BotDifficulty.ts index fd21a78b..c3d1699d 100644 --- a/project/src/models/enums/RaidSettings/BotDifficulty.ts +++ b/project/src/models/enums/RaidSettings/BotDifficulty.ts @@ -1,5 +1,4 @@ -export enum BotDifficulty -{ +export enum BotDifficulty { AS_ONLINE = "AsOnline", EASY = "Easy", MEDIUM = "Medium", diff --git a/project/src/models/enums/RaidSettings/TimeAndWeather/CloudinessType.ts b/project/src/models/enums/RaidSettings/TimeAndWeather/CloudinessType.ts index eda0403b..5e125c42 100644 --- a/project/src/models/enums/RaidSettings/TimeAndWeather/CloudinessType.ts +++ b/project/src/models/enums/RaidSettings/TimeAndWeather/CloudinessType.ts @@ -1,5 +1,4 @@ -export enum CloudinessType -{ +export enum CloudinessType { CLEAR = "Clear", PARTLY_CLOUDY = "PartlyCloudy", CLOUDY = "Cloudy", diff --git a/project/src/models/enums/RaidSettings/TimeAndWeather/FogType.ts b/project/src/models/enums/RaidSettings/TimeAndWeather/FogType.ts index c6ed34c1..ce7ddc91 100644 --- a/project/src/models/enums/RaidSettings/TimeAndWeather/FogType.ts +++ b/project/src/models/enums/RaidSettings/TimeAndWeather/FogType.ts @@ -1,5 +1,4 @@ -export enum FogType -{ +export enum FogType { NO_FOG = "NoFog", FAINT = "Faint", FOG = "Fog", diff --git a/project/src/models/enums/RaidSettings/TimeAndWeather/RainType.ts b/project/src/models/enums/RaidSettings/TimeAndWeather/RainType.ts index c17f4b64..41478d8d 100644 --- a/project/src/models/enums/RaidSettings/TimeAndWeather/RainType.ts +++ b/project/src/models/enums/RaidSettings/TimeAndWeather/RainType.ts @@ -1,5 +1,4 @@ -export enum RainType -{ +export enum RainType { NO_RAIN = "NoRain", DRIZZLING = "Drizzling", RAIN = "Rain", diff --git a/project/src/models/enums/RaidSettings/TimeAndWeather/TimeFlowType.ts b/project/src/models/enums/RaidSettings/TimeAndWeather/TimeFlowType.ts index 21540363..7428330b 100644 --- a/project/src/models/enums/RaidSettings/TimeAndWeather/TimeFlowType.ts +++ b/project/src/models/enums/RaidSettings/TimeAndWeather/TimeFlowType.ts @@ -1,5 +1,4 @@ -export enum TimeFlowType -{ +export enum TimeFlowType { X0 = "x0", X0_14 = "x0_14", X0_25 = "x0_25", diff --git a/project/src/models/enums/RaidSettings/TimeAndWeather/WindSpeed.ts b/project/src/models/enums/RaidSettings/TimeAndWeather/WindSpeed.ts index d4cb5912..67f6b4e0 100644 --- a/project/src/models/enums/RaidSettings/TimeAndWeather/WindSpeed.ts +++ b/project/src/models/enums/RaidSettings/TimeAndWeather/WindSpeed.ts @@ -1,5 +1,4 @@ -export enum WindSpeed -{ +export enum WindSpeed { LIGHT = "Light", MODERATE = "Moderate", STRONG = "Strong", diff --git a/project/src/models/enums/Season.ts b/project/src/models/enums/Season.ts index 9bfbecfe..b00cf7cf 100644 --- a/project/src/models/enums/Season.ts +++ b/project/src/models/enums/Season.ts @@ -1,5 +1,4 @@ -export enum Season -{ +export enum Season { SUMMER = 0, AUTUMN = 1, WINTER = 2, diff --git a/project/src/models/enums/SeasonalEventType.ts b/project/src/models/enums/SeasonalEventType.ts index d0b62cf1..51abcfb1 100644 --- a/project/src/models/enums/SeasonalEventType.ts +++ b/project/src/models/enums/SeasonalEventType.ts @@ -1,5 +1,4 @@ -export enum SeasonalEventType -{ +export enum SeasonalEventType { NONE = "None", CHRISTMAS = "Christmas", HALLOWEEN = "Halloween", diff --git a/project/src/models/enums/SideType.ts b/project/src/models/enums/SideType.ts index 60686e0f..022e1102 100644 --- a/project/src/models/enums/SideType.ts +++ b/project/src/models/enums/SideType.ts @@ -1,5 +1,4 @@ -export enum SideType -{ +export enum SideType { PMC = "Pmc", SAVAGE = "Savage", RANDOM = "Random", diff --git a/project/src/models/enums/SkillTypes.ts b/project/src/models/enums/SkillTypes.ts index c7bea249..610aad5f 100644 --- a/project/src/models/enums/SkillTypes.ts +++ b/project/src/models/enums/SkillTypes.ts @@ -1,5 +1,4 @@ -export enum SkillTypes -{ +export enum SkillTypes { BOT_RELOAD = "BotReload", BOT_SOUND = "BotSound", HIDEOUT_MANAGEMENT = "HideoutManagement", diff --git a/project/src/models/enums/TraderServiceType.ts b/project/src/models/enums/TraderServiceType.ts index 3f8276cc..f1a29061 100644 --- a/project/src/models/enums/TraderServiceType.ts +++ b/project/src/models/enums/TraderServiceType.ts @@ -1,5 +1,4 @@ -export enum TraderServiceType -{ +export enum TraderServiceType { EXUSEC_LOYALTY = "ExUsecLoyalty", ZRYACHIY_AID = "ZryachiyAid", CULTISTS_AID = "CultistsAid", diff --git a/project/src/models/enums/Traders.ts b/project/src/models/enums/Traders.ts index 5f3dd0c8..e0aa1b2d 100644 --- a/project/src/models/enums/Traders.ts +++ b/project/src/models/enums/Traders.ts @@ -1,5 +1,4 @@ -export enum Traders -{ +export enum Traders { PRAPOR = "54cb50c76803fa8b248b4571", THERAPIST = "54cb57776803fa99248b456e", FENCE = "579dc571d53a0658a154fbec", diff --git a/project/src/models/enums/WeaponSkillTypes.ts b/project/src/models/enums/WeaponSkillTypes.ts index e2b5fe06..3baf6442 100644 --- a/project/src/models/enums/WeaponSkillTypes.ts +++ b/project/src/models/enums/WeaponSkillTypes.ts @@ -1,5 +1,4 @@ -export enum WeaponSkillTypes -{ +export enum WeaponSkillTypes { PISTOL = "Pistol", REVOLVER = "Revolver", SMG = "SMG", diff --git a/project/src/models/enums/Weapons.ts b/project/src/models/enums/Weapons.ts index dfa5a7a9..025dd53f 100644 --- a/project/src/models/enums/Weapons.ts +++ b/project/src/models/enums/Weapons.ts @@ -1,6 +1,5 @@ // This is an auto generated file, do not modify. Re-generate with `npm run gen:items` -export enum Weapons -{ +export enum Weapons { ASSAULTCARBINE_762X39_OP_SKS = "587e02ff24597743df3deaeb", ASSAULTCARBINE_762X39_SKS = "574d967124597745970e7c94", ASSAULTCARBINE_762X51_VPO_101_VEPR_HUNTER = "5c501a4d2e221602b412b540", diff --git a/project/src/models/enums/WeatherType.ts b/project/src/models/enums/WeatherType.ts index e5627a8f..500397bd 100644 --- a/project/src/models/enums/WeatherType.ts +++ b/project/src/models/enums/WeatherType.ts @@ -1,5 +1,4 @@ -export enum WeatherType -{ +export enum WeatherType { CLEAR_DAY = 0, CLEAR_WIND = 1, CLEAR_NIGHT = 2, diff --git a/project/src/models/enums/WildSpawnTypeNumber.ts b/project/src/models/enums/WildSpawnTypeNumber.ts index a37290f6..4252c089 100644 --- a/project/src/models/enums/WildSpawnTypeNumber.ts +++ b/project/src/models/enums/WildSpawnTypeNumber.ts @@ -1,5 +1,4 @@ -export enum WildSpawnTypeNumber -{ +export enum WildSpawnTypeNumber { MARKSMAN = 0, ASSAULT = 1, BOSSTEST = 2, diff --git a/project/src/models/enums/WindDirection.ts b/project/src/models/enums/WindDirection.ts index 1e03f9b8..ed257bc8 100644 --- a/project/src/models/enums/WindDirection.ts +++ b/project/src/models/enums/WindDirection.ts @@ -1,5 +1,4 @@ -export enum WindDirection -{ +export enum WindDirection { EAST = 1, NORTH = 2, WEST = 3, diff --git a/project/src/models/enums/hideout/QteActivityType.ts b/project/src/models/enums/hideout/QteActivityType.ts index 6869f8f1..bc2b48d6 100644 --- a/project/src/models/enums/hideout/QteActivityType.ts +++ b/project/src/models/enums/hideout/QteActivityType.ts @@ -1,4 +1,3 @@ -export enum QteActivityType -{ +export enum QteActivityType { GYM = 0, } diff --git a/project/src/models/enums/hideout/QteEffectType.ts b/project/src/models/enums/hideout/QteEffectType.ts index 36b0640f..dcefc1c6 100644 --- a/project/src/models/enums/hideout/QteEffectType.ts +++ b/project/src/models/enums/hideout/QteEffectType.ts @@ -1,5 +1,4 @@ -export enum QteEffectType -{ +export enum QteEffectType { FINISH_EFFECT = "FinishEffect", SINGLE_SUCCESS_EFFECT = "SingleSuccessEffect", SINGLE_FAIL_EFFECT = "SingleFailEffect", diff --git a/project/src/models/enums/hideout/QteResultType.ts b/project/src/models/enums/hideout/QteResultType.ts index f1da1981..262bb5cd 100644 --- a/project/src/models/enums/hideout/QteResultType.ts +++ b/project/src/models/enums/hideout/QteResultType.ts @@ -1,5 +1,4 @@ -export enum QteResultType -{ +export enum QteResultType { NONE = "None", EXIT = "Exit", } diff --git a/project/src/models/enums/hideout/QteRewardType.ts b/project/src/models/enums/hideout/QteRewardType.ts index 40ac2ca2..8465686d 100644 --- a/project/src/models/enums/hideout/QteRewardType.ts +++ b/project/src/models/enums/hideout/QteRewardType.ts @@ -1,5 +1,4 @@ -export enum QteRewardType -{ +export enum QteRewardType { SKILL = "Skill", HEALTH_EFFECT = "HealthEffect", MUSCLE_PAIN = "MusclePain", diff --git a/project/src/models/enums/hideout/QteType.ts b/project/src/models/enums/hideout/QteType.ts index 86a6c70e..5fc7f3bf 100644 --- a/project/src/models/enums/hideout/QteType.ts +++ b/project/src/models/enums/hideout/QteType.ts @@ -1,4 +1,3 @@ -export enum QteType -{ +export enum QteType { SHRINKING_CIRCLE = 0, } diff --git a/project/src/models/enums/hideout/RequirementType.ts b/project/src/models/enums/hideout/RequirementType.ts index 6fc544c8..ab985c1f 100644 --- a/project/src/models/enums/hideout/RequirementType.ts +++ b/project/src/models/enums/hideout/RequirementType.ts @@ -1,5 +1,4 @@ -export enum RequirementType -{ +export enum RequirementType { AREA = "Area", ITEM = "Item", TRADER_UNLOCK = "TraderUnlock", diff --git a/project/src/models/external/HttpFramework.ts b/project/src/models/external/HttpFramework.ts index e6d46cf7..3c231ccb 100644 --- a/project/src/models/external/HttpFramework.ts +++ b/project/src/models/external/HttpFramework.ts @@ -1,6 +1,6 @@ import { IncomingMessage, ServerResponse } from "node:http"; -import { injectable } from "tsyringe"; import { HttpMethods } from "@spt/servers/http/HttpMethods"; +import { injectable } from "tsyringe"; export type HandleFn = (_: string, req: IncomingMessage, resp: ServerResponse) => void; @@ -9,41 +9,32 @@ export type HandleFn = (_: string, req: IncomingMessage, resp: ServerResponse) = * @param basePath The base path * @returns The decorator that create the listener proxy */ -export const Listen = (basePath: string) => -{ - return (Base: T): T => - { +export const Listen = (basePath: string) => { + return (Base: T): T => { // Used for the base class to be able to use DI injectable()(Base); - return class extends Base - { + return class extends Base { // Record of each handler per HTTP method and path handlers: Partial>>; - constructor(...args: any[]) - { + constructor(...args: any[]) { super(...args); this.handlers = {}; // Retrieve all handlers const handlersArray = Base.prototype.handlers; - if (!handlersArray) - { + if (!handlersArray) { return; } // Add each flagged handler to the Record - for (const { handlerName, path, httpMethod } of handlersArray) - { - if (!this.handlers[httpMethod]) - { + for (const { handlerName, path, httpMethod } of handlersArray) { + if (!this.handlers[httpMethod]) { this.handlers[httpMethod] = {}; } - if (this[handlerName] !== undefined && typeof this[handlerName] === "function") - { - if (!path || path === "") - { + if (this[handlerName] !== undefined && typeof this[handlerName] === "function") { + if (!path || path === "") { this.handlers[httpMethod][`/${basePath}`] = this[handlerName]; } this.handlers[httpMethod][`/${basePath}/${path}`] = this[handlerName]; @@ -56,21 +47,18 @@ export const Listen = (basePath: string) => // The canHandle method is used to check if the Listener handles a request // Based on both the HTTP method and the route - canHandle = (_: string, req: IncomingMessage): boolean => - { + canHandle = (_: string, req: IncomingMessage): boolean => { const routesHandles = this.handlers[req.method]; return ( - Object.keys(this.handlers).some((meth) => meth === req.method) - && Object.keys(routesHandles).some((route) => new RegExp(route).test(req.url)) + Object.keys(this.handlers).some((meth) => meth === req.method) && + Object.keys(routesHandles).some((route) => new RegExp(route).test(req.url)) ); }; // The actual handle method dispatches the request to the registered handlers - handle = (sessionID: string, req: IncomingMessage, resp: ServerResponse): void => - { - if (Object.keys(this.handlers).length === 0) - { + handle = (sessionID: string, req: IncomingMessage, resp: ServerResponse): void => { + if (Object.keys(this.handlers).length === 0) { return; } @@ -83,8 +71,7 @@ export const Listen = (basePath: string) => // Filter to select valid routes but only use the first element since it's the most precise const validRoutes = routes.filter((handlerKey) => new RegExp(handlerKey).test(route)); - if (validRoutes.length > 0) - { + if (validRoutes.length > 0) { routesHandles[validRoutes[0]](sessionID, req, resp); } }; @@ -97,16 +84,12 @@ export const Listen = (basePath: string) => * @param httpMethod The HTTP method to create the decorator for * @returns The decorator */ -const createHttpDecorator = (httpMethod: HttpMethods) => -{ +const createHttpDecorator = (httpMethod: HttpMethods) => { // The handler path (ignoring the base path) - return (path = "") => - { - return (target: any, propertyKey: string) => - { + return (path = "") => { + return (target: any, propertyKey: string) => { // If the handlers array has not been initialized yet - if (!target.handlers) - { + if (!target.handlers) { target.handlers = []; } diff --git a/project/src/models/external/IPostDBLoadMod.ts b/project/src/models/external/IPostDBLoadMod.ts index 8a62f92b..87e5566c 100644 --- a/project/src/models/external/IPostDBLoadMod.ts +++ b/project/src/models/external/IPostDBLoadMod.ts @@ -1,6 +1,5 @@ import type { DependencyContainer } from "tsyringe"; -export interface IPostDBLoadMod -{ - postDBLoad(container: DependencyContainer): void +export interface IPostDBLoadMod { + postDBLoad(container: DependencyContainer): void; } diff --git a/project/src/models/external/IPostDBLoadModAsync.ts b/project/src/models/external/IPostDBLoadModAsync.ts index f05ff65e..f383385f 100644 --- a/project/src/models/external/IPostDBLoadModAsync.ts +++ b/project/src/models/external/IPostDBLoadModAsync.ts @@ -1,6 +1,5 @@ import type { DependencyContainer } from "tsyringe"; -export interface IPostDBLoadModAsync -{ - postDBLoadAsync(container: DependencyContainer): Promise +export interface IPostDBLoadModAsync { + postDBLoadAsync(container: DependencyContainer): Promise; } diff --git a/project/src/models/external/IPostSptLoadMod.ts b/project/src/models/external/IPostSptLoadMod.ts index 4e97735c..5ba9629d 100644 --- a/project/src/models/external/IPostSptLoadMod.ts +++ b/project/src/models/external/IPostSptLoadMod.ts @@ -1,6 +1,5 @@ import type { DependencyContainer } from "tsyringe"; -export interface IPostSptLoadMod -{ - postSptLoad(container: DependencyContainer): void +export interface IPostSptLoadMod { + postSptLoad(container: DependencyContainer): void; } diff --git a/project/src/models/external/IPostSptLoadModAsync.ts b/project/src/models/external/IPostSptLoadModAsync.ts index 30b1e459..87217361 100644 --- a/project/src/models/external/IPostSptLoadModAsync.ts +++ b/project/src/models/external/IPostSptLoadModAsync.ts @@ -1,6 +1,5 @@ import type { DependencyContainer } from "tsyringe"; -export interface IPostSptLoadModAsync -{ - postSptLoadAsync(container: DependencyContainer): Promise +export interface IPostSptLoadModAsync { + postSptLoadAsync(container: DependencyContainer): Promise; } diff --git a/project/src/models/external/IPreSptLoadMod.ts b/project/src/models/external/IPreSptLoadMod.ts index f798ba01..0aa0915e 100644 --- a/project/src/models/external/IPreSptLoadMod.ts +++ b/project/src/models/external/IPreSptLoadMod.ts @@ -1,6 +1,5 @@ import type { DependencyContainer } from "tsyringe"; -export interface IPreSptLoadMod -{ - preSptLoad(container: DependencyContainer): void +export interface IPreSptLoadMod { + preSptLoad(container: DependencyContainer): void; } diff --git a/project/src/models/external/IPreSptLoadModAsync.ts b/project/src/models/external/IPreSptLoadModAsync.ts index 307ab76a..d5fcd79a 100644 --- a/project/src/models/external/IPreSptLoadModAsync.ts +++ b/project/src/models/external/IPreSptLoadModAsync.ts @@ -1,6 +1,5 @@ import type { DependencyContainer } from "tsyringe"; -export interface IPreSptLoadModAsync -{ - preSptLoadAsync(container: DependencyContainer): Promise +export interface IPreSptLoadModAsync { + preSptLoadAsync(container: DependencyContainer): Promise; } diff --git a/project/src/models/spt/bindings/Route.ts b/project/src/models/spt/bindings/Route.ts index a3b0fd7c..abe8d2c6 100644 --- a/project/src/models/spt/bindings/Route.ts +++ b/project/src/models/spt/bindings/Route.ts @@ -1,4 +1,3 @@ -export interface IRoute -{ - spt: any +export interface IRoute { + spt: any; } diff --git a/project/src/models/spt/bots/BotGenerationDetails.ts b/project/src/models/spt/bots/BotGenerationDetails.ts index f6499058..24f7e740 100644 --- a/project/src/models/spt/bots/BotGenerationDetails.ts +++ b/project/src/models/spt/bots/BotGenerationDetails.ts @@ -1,28 +1,27 @@ import { MinMax } from "@spt/models/common/MinMax"; -export interface BotGenerationDetails -{ +export interface BotGenerationDetails { /** Should the bot be generated as a PMC */ - isPmc: boolean + isPmc: boolean; /** assault/pmcBot etc */ - role: string + role: string; /** Side of bot */ - side: string + side: string; /** Active players current level */ - playerLevel?: number - playerName?: string + playerLevel?: number; + playerName?: string; /** Level specific overrides for PMC level */ - locationSpecificPmcLevelOverride?: MinMax + locationSpecificPmcLevelOverride?: MinMax; /** Delta of highest level of bot e.g. 50 means 50 levels above player */ - botRelativeLevelDeltaMax: number + botRelativeLevelDeltaMax: number; /** Delta of lowest level of bot e.g. 50 means 50 levels below player */ - botRelativeLevelDeltaMin: number + botRelativeLevelDeltaMin: number; /** How many to create and store */ - botCountToGenerate: number + botCountToGenerate: number; /** Desired difficulty of the bot */ - botDifficulty: string + botDifficulty: string; /** Will the generated bot be a player scav */ - isPlayerScav: boolean - eventRole?: string - allPmcsHaveSameNameAsPlayer?: boolean + isPlayerScav: boolean; + eventRole?: string; + allPmcsHaveSameNameAsPlayer?: boolean; } diff --git a/project/src/models/spt/bots/GenerateWeaponResult.ts b/project/src/models/spt/bots/GenerateWeaponResult.ts index 5667a713..200a5e86 100644 --- a/project/src/models/spt/bots/GenerateWeaponResult.ts +++ b/project/src/models/spt/bots/GenerateWeaponResult.ts @@ -2,8 +2,7 @@ import { Mods } from "@spt/models/eft/common/tables/IBotType"; import { Item } from "@spt/models/eft/common/tables/IItem"; import { ITemplateItem } from "@spt/models/eft/common/tables/ITemplateItem"; -export class GenerateWeaponResult -{ +export class GenerateWeaponResult { weapon: Item[]; chosenAmmoTpl: string; chosenUbglAmmoTpl: string; diff --git a/project/src/models/spt/bots/IBotLootCache.ts b/project/src/models/spt/bots/IBotLootCache.ts index d4f282c3..aa352add 100644 --- a/project/src/models/spt/bots/IBotLootCache.ts +++ b/project/src/models/spt/bots/IBotLootCache.ts @@ -1,23 +1,21 @@ -export interface IBotLootCache -{ - backpackLoot: Record - pocketLoot: Record - vestLoot: Record - secureLoot: Record - combinedPoolLoot: Record +export interface IBotLootCache { + backpackLoot: Record; + pocketLoot: Record; + vestLoot: Record; + secureLoot: Record; + combinedPoolLoot: Record; - specialItems: Record - healingItems: Record - drugItems: Record - foodItems: Record - drinkItems: Record - currencyItems: Record - stimItems: Record - grenadeItems: Record + specialItems: Record; + healingItems: Record; + drugItems: Record; + foodItems: Record; + drinkItems: Record; + currencyItems: Record; + stimItems: Record; + grenadeItems: Record; } -export enum LootCacheType -{ +export enum LootCacheType { SPECIAL = "Special", BACKPACK = "Backpack", POCKET = "Pocket", diff --git a/project/src/models/spt/bots/IBots.ts b/project/src/models/spt/bots/IBots.ts index 0a4cff07..ed094262 100644 --- a/project/src/models/spt/bots/IBots.ts +++ b/project/src/models/spt/bots/IBots.ts @@ -2,9 +2,8 @@ import { IBotBase } from "@spt/models/eft/common/tables/IBotBase"; import { IBotCore } from "@spt/models/eft/common/tables/IBotCore"; import { IBotType } from "@spt/models/eft/common/tables/IBotType"; -export interface IBots -{ - types: Record - base: IBotBase - core: IBotCore +export interface IBots { + types: Record; + base: IBotBase; + core: IBotCore; } diff --git a/project/src/models/spt/bots/IChooseRandomCompatibleModResult.ts b/project/src/models/spt/bots/IChooseRandomCompatibleModResult.ts index 054394c4..6ba6630e 100644 --- a/project/src/models/spt/bots/IChooseRandomCompatibleModResult.ts +++ b/project/src/models/spt/bots/IChooseRandomCompatibleModResult.ts @@ -1,8 +1,7 @@ -export interface IChooseRandomCompatibleModResult -{ - incompatible: boolean - found?: boolean - chosenTpl?: string - reason: string - slotBlocked?: boolean +export interface IChooseRandomCompatibleModResult { + incompatible: boolean; + found?: boolean; + chosenTpl?: string; + reason: string; + slotBlocked?: boolean; } diff --git a/project/src/models/spt/bots/IFilterPlateModsForSlotByLevelResult.ts b/project/src/models/spt/bots/IFilterPlateModsForSlotByLevelResult.ts index 2edd8cd3..e2e54668 100644 --- a/project/src/models/spt/bots/IFilterPlateModsForSlotByLevelResult.ts +++ b/project/src/models/spt/bots/IFilterPlateModsForSlotByLevelResult.ts @@ -1,11 +1,9 @@ -export interface IFilterPlateModsForSlotByLevelResult -{ - result: Result - plateModTpls: string[] +export interface IFilterPlateModsForSlotByLevelResult { + result: Result; + plateModTpls: string[]; } -export enum Result -{ +export enum Result { UNKNOWN_FAILURE = -1, SUCCESS = 1, NO_DEFAULT_FILTER = 2, diff --git a/project/src/models/spt/bots/IGenerateEquipmentProperties.ts b/project/src/models/spt/bots/IGenerateEquipmentProperties.ts index 200c898a..545e7fac 100644 --- a/project/src/models/spt/bots/IGenerateEquipmentProperties.ts +++ b/project/src/models/spt/bots/IGenerateEquipmentProperties.ts @@ -2,23 +2,22 @@ import { Inventory as PmcInventory } from "@spt/models/eft/common/tables/IBotBas import { Chances, Mods } from "@spt/models/eft/common/tables/IBotType"; import { EquipmentFilters, RandomisationDetails } from "@spt/models/spt/config/IBotConfig"; -export interface IGenerateEquipmentProperties -{ +export interface IGenerateEquipmentProperties { /** Root Slot being generated */ - rootEquipmentSlot: string + rootEquipmentSlot: string; /** Equipment pool for root slot being generated */ - rootEquipmentPool: Record - modPool: Mods + rootEquipmentPool: Record; + modPool: Mods; /** Dictionary of mod items and their chance to spawn for this bot type */ - spawnChances: Chances + spawnChances: Chances; /** Role being generated for */ - botRole: string + botRole: string; /** Level of bot being generated */ - botLevel: number - inventory: PmcInventory - botEquipmentConfig: EquipmentFilters + botLevel: number; + inventory: PmcInventory; + botEquipmentConfig: EquipmentFilters; /** Settings from bot.json to adjust how item is generated */ - randomisationDetails: RandomisationDetails + randomisationDetails: RandomisationDetails; /** OPTIONAL - Do not generate mods for tpls in this array */ - generateModsBlacklist?: string[] + generateModsBlacklist?: string[]; } diff --git a/project/src/models/spt/bots/IGenerateWeaponRequest.ts b/project/src/models/spt/bots/IGenerateWeaponRequest.ts index 9b38b1cf..9c9c849e 100644 --- a/project/src/models/spt/bots/IGenerateWeaponRequest.ts +++ b/project/src/models/spt/bots/IGenerateWeaponRequest.ts @@ -3,41 +3,38 @@ import { Item } from "@spt/models/eft/common/tables/IItem"; import { ITemplateItem } from "@spt/models/eft/common/tables/ITemplateItem"; import { BotModLimits } from "@spt/services/BotWeaponModLimitService"; -export interface IGenerateWeaponRequest -{ +export interface IGenerateWeaponRequest { /** Weapon to add mods to / result that is returned */ - weapon: Item[] + weapon: Item[]; /** Pool of compatible mods to attach to weapon */ - modPool: Mods + modPool: Mods; /** ParentId of weapon */ - weaponId: string + weaponId: string; /** Weapon which mods will be generated on */ - parentTemplate: ITemplateItem + parentTemplate: ITemplateItem; /** Chance values mod will be added */ - modSpawnChances: ModsChances + modSpawnChances: ModsChances; /** Ammo tpl to use when generating magazines/cartridges */ - ammoTpl: string + ammoTpl: string; /** Bot-specific properties */ - botData: IBotData + botData: IBotData; /** limits placed on certain mod types per gun */ - modLimits: BotModLimits + modLimits: BotModLimits; /** Info related to the weapon being generated */ - weaponStats: IWeaponStats + weaponStats: IWeaponStats; } -export interface IBotData -{ +export interface IBotData { /** Role of bot weapon is generated for */ - role: string + role: string; /** Level of the bot weapon is being generated for */ - level: number + level: number; /** role of bot when accessing bot.json equipment config settings */ - equipmentRole: string + equipmentRole: string; } -export interface IWeaponStats -{ - hasOptic?: boolean - hasFrontIronSight?: boolean - hasRearIronSight?: boolean +export interface IWeaponStats { + hasOptic?: boolean; + hasFrontIronSight?: boolean; + hasRearIronSight?: boolean; } diff --git a/project/src/models/spt/bots/IItemSpawnLimitSettings.ts b/project/src/models/spt/bots/IItemSpawnLimitSettings.ts index 60b7122f..ca3e6a65 100644 --- a/project/src/models/spt/bots/IItemSpawnLimitSettings.ts +++ b/project/src/models/spt/bots/IItemSpawnLimitSettings.ts @@ -1,5 +1,4 @@ -export interface IItemSpawnLimitSettings -{ - currentLimits: Record - globalLimits: Record +export interface IItemSpawnLimitSettings { + currentLimits: Record; + globalLimits: Record; } diff --git a/project/src/models/spt/bots/IModToSpawnRequest.ts b/project/src/models/spt/bots/IModToSpawnRequest.ts index f7f7c7e4..e924cd47 100644 --- a/project/src/models/spt/bots/IModToSpawnRequest.ts +++ b/project/src/models/spt/bots/IModToSpawnRequest.ts @@ -4,26 +4,25 @@ import { ModSpawn } from "@spt/models/enums/ModSpawn"; import { IWeaponStats } from "@spt/models/spt/bots/IGenerateWeaponRequest"; import { EquipmentFilterDetails } from "@spt/models/spt/config/IBotConfig"; -export interface IModToSpawnRequest -{ +export interface IModToSpawnRequest { /** Slot mod will fit into */ - modSlot: string + modSlot: string; /** Will generate a randomised mod pool if true */ - isRandomisableSlot: boolean + isRandomisableSlot: boolean; /** Parent slot the item will be a part of */ - botWeaponSightWhitelist: Record + botWeaponSightWhitelist: Record; /** Blacklist to prevent mods from being picked */ - botEquipBlacklist: EquipmentFilterDetails + botEquipBlacklist: EquipmentFilterDetails; /** Pool of items to pick from */ - itemModPool: Record + itemModPool: Record; /** Array with only weapon tpl in it, ready for mods to be added */ - weapon: Item[] + weapon: Item[]; /** Ammo tpl to use if slot requires a cartridge to be added (e.g. mod_magazine) */ - ammoTpl: string + ammoTpl: string; /** Parent item the mod will go into */ - parentTemplate: ITemplateItem + parentTemplate: ITemplateItem; /** Should mod be spawned/skipped/use default */ - modSpawnResult: ModSpawn + modSpawnResult: ModSpawn; /** Weapon stats for weapon being generated */ - weaponStats: IWeaponStats + weaponStats: IWeaponStats; } diff --git a/project/src/models/spt/callbacks/IBotCallbacks.ts b/project/src/models/spt/callbacks/IBotCallbacks.ts index 1a448766..c98c30c8 100644 --- a/project/src/models/spt/callbacks/IBotCallbacks.ts +++ b/project/src/models/spt/callbacks/IBotCallbacks.ts @@ -3,10 +3,9 @@ import { IEmptyRequestData } from "@spt/models/eft/common/IEmptyRequestData"; import { IBotBase } from "@spt/models/eft/common/tables/IBotBase"; import { IGetBodyResponseData } from "@spt/models/eft/httpResponse/IGetBodyResponseData"; -export interface IBotCallbacks -{ - getBotLimit(url: string, info: IEmptyRequestData, sessionID: string): string - getBotDifficulty(url: string, info: IEmptyRequestData, sessionID: string): string - generateBots(url: string, info: IGenerateBotsRequestData, sessionID: string): IGetBodyResponseData - getBotCap(): string +export interface IBotCallbacks { + getBotLimit(url: string, info: IEmptyRequestData, sessionID: string): string; + getBotDifficulty(url: string, info: IEmptyRequestData, sessionID: string): string; + generateBots(url: string, info: IGenerateBotsRequestData, sessionID: string): IGetBodyResponseData; + getBotCap(): string; } diff --git a/project/src/models/spt/callbacks/IBundleCallbacks.ts b/project/src/models/spt/callbacks/IBundleCallbacks.ts index a99cadfa..7e37c6ee 100644 --- a/project/src/models/spt/callbacks/IBundleCallbacks.ts +++ b/project/src/models/spt/callbacks/IBundleCallbacks.ts @@ -1,6 +1,5 @@ -export interface IBundleCallbacks -{ - sendBundle(sessionID: string, req: any, resp: any, body: any): any - getBundles(url: string, info: any, sessionID: string): string - getBundle(url: string, info: any, sessionID: string): string +export interface IBundleCallbacks { + sendBundle(sessionID: string, req: any, resp: any, body: any): any; + getBundles(url: string, info: any, sessionID: string): string; + getBundle(url: string, info: any, sessionID: string): string; } diff --git a/project/src/models/spt/callbacks/ICustomizationCallbacks.ts b/project/src/models/spt/callbacks/ICustomizationCallbacks.ts index f3dd7205..d4381460 100644 --- a/project/src/models/spt/callbacks/ICustomizationCallbacks.ts +++ b/project/src/models/spt/callbacks/ICustomizationCallbacks.ts @@ -5,10 +5,9 @@ import { IWearClothingRequestData } from "@spt/models/eft/customization/IWearClo import { IGetBodyResponseData } from "@spt/models/eft/httpResponse/IGetBodyResponseData"; import { IItemEventRouterResponse } from "@spt/models/eft/itemEvent/IItemEventRouterResponse"; -export interface ICustomizationCallbacks -{ - getSuits(url: string, info: any, sessionID: string): IGetBodyResponseData - getTraderSuits(url: string, info: any, sessionID: string): IGetBodyResponseData - wearClothing(pmcData: IPmcData, body: IWearClothingRequestData, sessionID: string): IItemEventRouterResponse - buyClothing(pmcData: IPmcData, body: IBuyClothingRequestData, sessionID: string): IItemEventRouterResponse +export interface ICustomizationCallbacks { + getSuits(url: string, info: any, sessionID: string): IGetBodyResponseData; + getTraderSuits(url: string, info: any, sessionID: string): IGetBodyResponseData; + wearClothing(pmcData: IPmcData, body: IWearClothingRequestData, sessionID: string): IItemEventRouterResponse; + buyClothing(pmcData: IPmcData, body: IBuyClothingRequestData, sessionID: string): IItemEventRouterResponse; } diff --git a/project/src/models/spt/callbacks/IDataCallbacks.ts b/project/src/models/spt/callbacks/IDataCallbacks.ts index c7909ad5..0d7bc816 100644 --- a/project/src/models/spt/callbacks/IDataCallbacks.ts +++ b/project/src/models/spt/callbacks/IDataCallbacks.ts @@ -7,35 +7,34 @@ import { IHideoutSettingsBase } from "@spt/models/eft/hideout/IHideoutSettingsBa import { IGetBodyResponseData } from "@spt/models/eft/httpResponse/IGetBodyResponseData"; import { ISettingsBase } from "@spt/models/spt/server/ISettingsBase"; -export interface IDataCallbacks -{ - getSettings(url: string, info: IEmptyRequestData, sessionID: string): IGetBodyResponseData - getGlobals(url: string, info: IEmptyRequestData, sessionID: string): IGetBodyResponseData - getTemplateItems(url: string, info: IEmptyRequestData, sessionID: string): string - getTemplateHandbook(url: string, info: IEmptyRequestData, sessionID: string): IGetBodyResponseData - getTemplateSuits(url: string, info: IEmptyRequestData, sessionID: string): IGetBodyResponseData - getTemplateCharacter(url: string, info: IEmptyRequestData, sessionID: string): IGetBodyResponseData +export interface IDataCallbacks { + getSettings(url: string, info: IEmptyRequestData, sessionID: string): IGetBodyResponseData; + getGlobals(url: string, info: IEmptyRequestData, sessionID: string): IGetBodyResponseData; + getTemplateItems(url: string, info: IEmptyRequestData, sessionID: string): string; + getTemplateHandbook(url: string, info: IEmptyRequestData, sessionID: string): IGetBodyResponseData; + getTemplateSuits(url: string, info: IEmptyRequestData, sessionID: string): IGetBodyResponseData; + getTemplateCharacter(url: string, info: IEmptyRequestData, sessionID: string): IGetBodyResponseData; getHideoutSettings( url: string, info: IEmptyRequestData, sessionID: string, - ): IGetBodyResponseData - getHideoutAreas(url: string, info: IEmptyRequestData, sessionID: string): IGetBodyResponseData + ): IGetBodyResponseData; + getHideoutAreas(url: string, info: IEmptyRequestData, sessionID: string): IGetBodyResponseData; gethideoutProduction( url: string, info: IEmptyRequestData, sessionID: string, - ): IGetBodyResponseData + ): IGetBodyResponseData; getHideoutScavcase( url: string, info: IEmptyRequestData, sessionID: string, - ): IGetBodyResponseData + ): IGetBodyResponseData; getLocalesLanguages( url: string, info: IEmptyRequestData, sessionID: string, - ): IGetBodyResponseData> - getLocalesMenu(url: string, info: IEmptyRequestData, sessionID: string): IGetBodyResponseData - getLocalesGlobal(url: string, info: IEmptyRequestData, sessionID: string): string + ): IGetBodyResponseData>; + getLocalesMenu(url: string, info: IEmptyRequestData, sessionID: string): IGetBodyResponseData; + getLocalesGlobal(url: string, info: IEmptyRequestData, sessionID: string): string; } diff --git a/project/src/models/spt/callbacks/IDialogueCallbacks.ts b/project/src/models/spt/callbacks/IDialogueCallbacks.ts index 555f77dc..329979eb 100644 --- a/project/src/models/spt/callbacks/IDialogueCallbacks.ts +++ b/project/src/models/spt/callbacks/IDialogueCallbacks.ts @@ -16,37 +16,36 @@ import { IGetBodyResponseData } from "@spt/models/eft/httpResponse/IGetBodyRespo import { INullResponseData } from "@spt/models/eft/httpResponse/INullResponseData"; import { DialogueInfo } from "@spt/models/eft/profile/ISptProfile"; -export interface IDialogueCallbacks -{ +export interface IDialogueCallbacks { getFriendList( url: string, info: IEmptyRequestData, sessionID: string, - ): IGetBodyResponseData - getChatServerList(url: string, info: IGetChatServerListRequestData, sessionID: string): IGetBodyResponseData + ): IGetBodyResponseData; + getChatServerList(url: string, info: IGetChatServerListRequestData, sessionID: string): IGetBodyResponseData; getMailDialogList( url: string, info: IGetMailDialogListRequestData, sessionID: string, - ): IGetBodyResponseData + ): IGetBodyResponseData; getMailDialogView( url: string, info: IGetMailDialogViewRequestData, sessionID: string, - ): IGetBodyResponseData - getMailDialogInfo(url: string, info: IGetMailDialogInfoRequestData, sessionID: string): IGetBodyResponseData - removeDialog(url: string, info: IRemoveDialogRequestData, sessionID: string): IGetBodyResponseData - pinDialog(url: string, info: IPinDialogRequestData, sessionID: string): IGetBodyResponseData - unpinDialog(url: string, info: IPinDialogRequestData, sessionID: string): IGetBodyResponseData - setRead(url: string, info: ISetDialogReadRequestData, sessionID: string): IGetBodyResponseData + ): IGetBodyResponseData; + getMailDialogInfo(url: string, info: IGetMailDialogInfoRequestData, sessionID: string): IGetBodyResponseData; + removeDialog(url: string, info: IRemoveDialogRequestData, sessionID: string): IGetBodyResponseData; + pinDialog(url: string, info: IPinDialogRequestData, sessionID: string): IGetBodyResponseData; + unpinDialog(url: string, info: IPinDialogRequestData, sessionID: string): IGetBodyResponseData; + setRead(url: string, info: ISetDialogReadRequestData, sessionID: string): IGetBodyResponseData; getAllAttachments( url: string, info: IGetAllAttachmentsRequestData, sessionID: string, - ): IGetBodyResponseData - listOutbox(url: string, info: IEmptyRequestData, sessionID: string): IGetBodyResponseData - listInbox(url: string, info: IEmptyRequestData, sessionID: string): IGetBodyResponseData - sendFriendRequest(url: string, request: IFriendRequestData, sessionID: string): INullResponseData - sendMessage(url: string, request: ISendMessageRequest, sessionID: string): IGetBodyResponseData - update(): boolean + ): IGetBodyResponseData; + listOutbox(url: string, info: IEmptyRequestData, sessionID: string): IGetBodyResponseData; + listInbox(url: string, info: IEmptyRequestData, sessionID: string): IGetBodyResponseData; + sendFriendRequest(url: string, request: IFriendRequestData, sessionID: string): INullResponseData; + sendMessage(url: string, request: ISendMessageRequest, sessionID: string): IGetBodyResponseData; + update(): boolean; } diff --git a/project/src/models/spt/callbacks/IGameCallbacks.ts b/project/src/models/spt/callbacks/IGameCallbacks.ts index 9c4ca087..b812e9d7 100644 --- a/project/src/models/spt/callbacks/IGameCallbacks.ts +++ b/project/src/models/spt/callbacks/IGameCallbacks.ts @@ -5,18 +5,17 @@ import { IVersionValidateRequestData } from "@spt/models/eft/game/IVersionValida import { IGetBodyResponseData } from "@spt/models/eft/httpResponse/IGetBodyResponseData"; import { INullResponseData } from "@spt/models/eft/httpResponse/INullResponseData"; -export interface IGameCallbacks -{ - versionValidate(url: string, info: IVersionValidateRequestData, sessionID: string): INullResponseData - gameStart(url: string, info: IEmptyRequestData, sessionID: string): IGetBodyResponseData - gameLogout(url: string, info: IEmptyRequestData, sessionID: string): IGetBodyResponseData +export interface IGameCallbacks { + versionValidate(url: string, info: IVersionValidateRequestData, sessionID: string): INullResponseData; + gameStart(url: string, info: IEmptyRequestData, sessionID: string): IGetBodyResponseData; + gameLogout(url: string, info: IEmptyRequestData, sessionID: string): IGetBodyResponseData; getGameConfig( url: string, info: IGameEmptyCrcRequestData, sessionID: string, - ): IGetBodyResponseData - getServer(url: string, info: IEmptyRequestData, sessionID: string): IGetBodyResponseData - validateGameVersion(url: string, info: IEmptyRequestData, sessionID: string): IGetBodyResponseData - gameKeepalive(url: string, info: IEmptyRequestData, sessionID: string): IGetBodyResponseData - getVersion(url: string, info: IEmptyRequestData, sessionID: string): string + ): IGetBodyResponseData; + getServer(url: string, info: IEmptyRequestData, sessionID: string): IGetBodyResponseData; + validateGameVersion(url: string, info: IEmptyRequestData, sessionID: string): IGetBodyResponseData; + gameKeepalive(url: string, info: IEmptyRequestData, sessionID: string): IGetBodyResponseData; + getVersion(url: string, info: IEmptyRequestData, sessionID: string): string; } diff --git a/project/src/models/spt/callbacks/IHandbookCallbacks.ts b/project/src/models/spt/callbacks/IHandbookCallbacks.ts index 221a488d..5857a3ee 100644 --- a/project/src/models/spt/callbacks/IHandbookCallbacks.ts +++ b/project/src/models/spt/callbacks/IHandbookCallbacks.ts @@ -1,4 +1,3 @@ -export interface IHandbookCallbacks -{ - load(): void +export interface IHandbookCallbacks { + load(): void; } diff --git a/project/src/models/spt/callbacks/IHealthCallbacks.ts b/project/src/models/spt/callbacks/IHealthCallbacks.ts index 292fffaf..43f415de 100644 --- a/project/src/models/spt/callbacks/IHealthCallbacks.ts +++ b/project/src/models/spt/callbacks/IHealthCallbacks.ts @@ -5,11 +5,10 @@ import { IOffraidHealRequestData } from "@spt/models/eft/health/IOffraidHealRequ import { ISyncHealthRequestData } from "@spt/models/eft/health/ISyncHealthRequestData"; import { ISptProfile } from "@spt/models/eft/profile/ISptProfile"; -export interface IHealthCallbacks -{ - onLoad(sessionID: string): ISptProfile - syncHealth(url: string, info: ISyncHealthRequestData, sessionID: string): any - offraidEat(pmcData: IPmcData, body: IOffraidEatRequestData, sessionID: string): any - offraidHeal(pmcData: IPmcData, body: IOffraidHealRequestData, sessionID: string): any - healthTreatment(pmcData: IPmcData, info: IHealthTreatmentRequestData, sessionID: string): any +export interface IHealthCallbacks { + onLoad(sessionID: string): ISptProfile; + syncHealth(url: string, info: ISyncHealthRequestData, sessionID: string): any; + offraidEat(pmcData: IPmcData, body: IOffraidEatRequestData, sessionID: string): any; + offraidHeal(pmcData: IPmcData, body: IOffraidHealRequestData, sessionID: string): any; + healthTreatment(pmcData: IPmcData, info: IHealthTreatmentRequestData, sessionID: string): any; } diff --git a/project/src/models/spt/callbacks/IHideoutCallbacks.ts b/project/src/models/spt/callbacks/IHideoutCallbacks.ts index 2aa18b9d..eee2ba82 100644 --- a/project/src/models/spt/callbacks/IHideoutCallbacks.ts +++ b/project/src/models/spt/callbacks/IHideoutCallbacks.ts @@ -10,44 +10,43 @@ import { IHideoutUpgradeCompleteRequestData } from "@spt/models/eft/hideout/IHid import { IHideoutUpgradeRequestData } from "@spt/models/eft/hideout/IHideoutUpgradeRequestData"; import { IItemEventRouterResponse } from "@spt/models/eft/itemEvent/IItemEventRouterResponse"; -export interface IHideoutCallbacks -{ - upgrade(pmcData: IPmcData, body: IHideoutUpgradeRequestData, sessionID: string): IItemEventRouterResponse +export interface IHideoutCallbacks { + upgrade(pmcData: IPmcData, body: IHideoutUpgradeRequestData, sessionID: string): IItemEventRouterResponse; upgradeComplete( pmcData: IPmcData, body: IHideoutUpgradeCompleteRequestData, sessionID: string, - ): IItemEventRouterResponse + ): IItemEventRouterResponse; putItemsInAreaSlots( pmcData: IPmcData, body: IHideoutPutItemInRequestData, sessionID: string, - ): IItemEventRouterResponse + ): IItemEventRouterResponse; takeItemsFromAreaSlots( pmcData: IPmcData, body: IHideoutTakeItemOutRequestData, sessionID: string, - ): IItemEventRouterResponse - toggleArea(pmcData: IPmcData, body: IHideoutToggleAreaRequestData, sessionID: string): IItemEventRouterResponse + ): IItemEventRouterResponse; + toggleArea(pmcData: IPmcData, body: IHideoutToggleAreaRequestData, sessionID: string): IItemEventRouterResponse; singleProductionStart( pmcData: IPmcData, body: IHideoutSingleProductionStartRequestData, sessionID: string, - ): IItemEventRouterResponse + ): IItemEventRouterResponse; scavCaseProductionStart( pmcData: IPmcData, body: IHideoutScavCaseStartRequestData, sessionID: string, - ): IItemEventRouterResponse + ): IItemEventRouterResponse; continuousProductionStart( pmcData: IPmcData, body: IHideoutContinuousProductionStartRequestData, sessionID: string, - ): IItemEventRouterResponse + ): IItemEventRouterResponse; takeProduction( pmcData: IPmcData, body: IHideoutTakeProductionRequestData, sessionID: string, - ): IItemEventRouterResponse - update(timeSinceLastRun: number): boolean + ): IItemEventRouterResponse; + update(timeSinceLastRun: number): boolean; } diff --git a/project/src/models/spt/callbacks/IHttpCallbacks.ts b/project/src/models/spt/callbacks/IHttpCallbacks.ts index aa9843d6..3ecd9458 100644 --- a/project/src/models/spt/callbacks/IHttpCallbacks.ts +++ b/project/src/models/spt/callbacks/IHttpCallbacks.ts @@ -1,6 +1,5 @@ -export interface IHttpCallbacks -{ - load(): void - sendImage(sessionID: string, req: any, resp: any, body: any): void - getImage(): string +export interface IHttpCallbacks { + load(): void; + sendImage(sessionID: string, req: any, resp: any, body: any): void; + getImage(): string; } diff --git a/project/src/models/spt/callbacks/IInsuranceCallbacks.ts b/project/src/models/spt/callbacks/IInsuranceCallbacks.ts index 091e8778..709c220b 100644 --- a/project/src/models/spt/callbacks/IInsuranceCallbacks.ts +++ b/project/src/models/spt/callbacks/IInsuranceCallbacks.ts @@ -3,10 +3,9 @@ import { IGetInsuranceCostRequestData } from "@spt/models/eft/insurance/IGetInsu import { IInsureRequestData } from "@spt/models/eft/insurance/IInsureRequestData"; import { ISptProfile } from "@spt/models/eft/profile/ISptProfile"; -export interface IInsuranceCallbacks -{ - onLoad(sessionID: string): ISptProfile - getInsuranceCost(url: string, info: IGetInsuranceCostRequestData, sessionID: string): any - insure(pmcData: IPmcData, body: IInsureRequestData, sessionID: string): any - update(secondsSinceLastRun: number): boolean +export interface IInsuranceCallbacks { + onLoad(sessionID: string): ISptProfile; + getInsuranceCost(url: string, info: IGetInsuranceCostRequestData, sessionID: string): any; + insure(pmcData: IPmcData, body: IInsureRequestData, sessionID: string): any; + update(secondsSinceLastRun: number): boolean; } diff --git a/project/src/models/spt/callbacks/IInventoryCallbacks.ts b/project/src/models/spt/callbacks/IInventoryCallbacks.ts index 289d37ed..3e52b845 100644 --- a/project/src/models/spt/callbacks/IInventoryCallbacks.ts +++ b/project/src/models/spt/callbacks/IInventoryCallbacks.ts @@ -17,38 +17,37 @@ import { IInventoryToggleRequestData } from "@spt/models/eft/inventory/IInventor import { IInventoryTransferRequestData } from "@spt/models/eft/inventory/IInventoryTransferRequestData"; import { IItemEventRouterResponse } from "@spt/models/eft/itemEvent/IItemEventRouterResponse"; -export interface IInventoryCallbacks -{ - moveItem(pmcData: IPmcData, body: IInventoryMoveRequestData, sessionID: string): IItemEventRouterResponse - removeItem(pmcData: IPmcData, body: IInventoryRemoveRequestData, sessionID: string): IItemEventRouterResponse - splitItem(pmcData: IPmcData, body: IInventorySplitRequestData, sessionID: string): IItemEventRouterResponse - mergeItem(pmcData: IPmcData, body: IInventoryMergeRequestData, sessionID: string): IItemEventRouterResponse - transferItem(pmcData: IPmcData, body: IInventoryTransferRequestData, sessionID: string): IItemEventRouterResponse - swapItem(pmcData: IPmcData, body: IInventorySwapRequestData, sessionID: string): IItemEventRouterResponse - foldItem(pmcData: IPmcData, body: IInventoryFoldRequestData, sessionID: string): IItemEventRouterResponse - toggleItem(pmcData: IPmcData, body: IInventoryToggleRequestData, sessionID: string): IItemEventRouterResponse - tagItem(pmcData: IPmcData, body: IInventoryTagRequestData, sessionID: string): IItemEventRouterResponse - bindItem(pmcData: IPmcData, body: IInventoryBindRequestData, sessionID: string): IItemEventRouterResponse - examineItem(pmcData: IPmcData, body: IInventoryExamineRequestData, sessionID: string): IItemEventRouterResponse +export interface IInventoryCallbacks { + moveItem(pmcData: IPmcData, body: IInventoryMoveRequestData, sessionID: string): IItemEventRouterResponse; + removeItem(pmcData: IPmcData, body: IInventoryRemoveRequestData, sessionID: string): IItemEventRouterResponse; + splitItem(pmcData: IPmcData, body: IInventorySplitRequestData, sessionID: string): IItemEventRouterResponse; + mergeItem(pmcData: IPmcData, body: IInventoryMergeRequestData, sessionID: string): IItemEventRouterResponse; + transferItem(pmcData: IPmcData, body: IInventoryTransferRequestData, sessionID: string): IItemEventRouterResponse; + swapItem(pmcData: IPmcData, body: IInventorySwapRequestData, sessionID: string): IItemEventRouterResponse; + foldItem(pmcData: IPmcData, body: IInventoryFoldRequestData, sessionID: string): IItemEventRouterResponse; + toggleItem(pmcData: IPmcData, body: IInventoryToggleRequestData, sessionID: string): IItemEventRouterResponse; + tagItem(pmcData: IPmcData, body: IInventoryTagRequestData, sessionID: string): IItemEventRouterResponse; + bindItem(pmcData: IPmcData, body: IInventoryBindRequestData, sessionID: string): IItemEventRouterResponse; + examineItem(pmcData: IPmcData, body: IInventoryExamineRequestData, sessionID: string): IItemEventRouterResponse; readEncyclopedia( pmcData: IPmcData, body: IInventoryReadEncyclopediaRequestData, sessionID: string, - ): IItemEventRouterResponse - sortInventory(pmcData: IPmcData, body: IInventorySortRequestData, sessionID: string): IItemEventRouterResponse + ): IItemEventRouterResponse; + sortInventory(pmcData: IPmcData, body: IInventorySortRequestData, sessionID: string): IItemEventRouterResponse; createMapMarker( pmcData: IPmcData, body: IInventoryCreateMarkerRequestData, sessionID: string, - ): IItemEventRouterResponse + ): IItemEventRouterResponse; deleteMapMarker( pmcData: IPmcData, body: IInventoryDeleteMarkerRequestData, sessionID: string, - ): IItemEventRouterResponse + ): IItemEventRouterResponse; editMapMarker( pmcData: IPmcData, body: IInventoryEditMarkerRequestData, sessionID: string, - ): IItemEventRouterResponse + ): IItemEventRouterResponse; } diff --git a/project/src/models/spt/callbacks/IItemEventCallbacks.ts b/project/src/models/spt/callbacks/IItemEventCallbacks.ts index abac02d9..6ab91801 100644 --- a/project/src/models/spt/callbacks/IItemEventCallbacks.ts +++ b/project/src/models/spt/callbacks/IItemEventCallbacks.ts @@ -2,11 +2,10 @@ import { IGetBodyResponseData } from "@spt/models/eft/httpResponse/IGetBodyRespo import { IItemEventRouterRequest } from "@spt/models/eft/itemEvent/IItemEventRouterRequest"; import { IItemEventRouterResponse } from "@spt/models/eft/itemEvent/IItemEventRouterResponse"; -export interface IItemEventCallbacks -{ +export interface IItemEventCallbacks { handleEvents( url: string, info: IItemEventRouterRequest, sessionID: string, - ): IGetBodyResponseData + ): IGetBodyResponseData; } diff --git a/project/src/models/spt/callbacks/ILauncherCallbacks.ts b/project/src/models/spt/callbacks/ILauncherCallbacks.ts index dc33a5ac..7397b25f 100644 --- a/project/src/models/spt/callbacks/ILauncherCallbacks.ts +++ b/project/src/models/spt/callbacks/ILauncherCallbacks.ts @@ -4,19 +4,18 @@ import { ILoginRequestData } from "@spt/models/eft/launcher/ILoginRequestData"; import { IRegisterData } from "@spt/models/eft/launcher/IRegisterData"; import { IRemoveProfileData } from "@spt/models/eft/launcher/IRemoveProfileData"; -export interface ILauncherCallbacks -{ - connect(): string - login(url: string, info: ILoginRequestData, sessionID: string): string - register(url: string, info: IRegisterData, sessionID: string): "FAILED" | "OK" - get(url: string, info: ILoginRequestData, sessionID: string): string - changeUsername(url: string, info: IChangeRequestData, sessionID: string): "FAILED" | "OK" - changePassword(url: string, info: IChangeRequestData, sessionID: string): "FAILED" | "OK" - wipe(url: string, info: IRegisterData, sessionID: string): "FAILED" | "OK" - getMiniProfile(url: string, info: IGetMiniProfileRequestData, sessionID: string): string - getAllMiniProfiles(url: string, info: any, sessionID: string): string - getServerVersion(): string - ping(url: string, info: any, sessionID: string): string - removeProfile(url: string, info: IRemoveProfileData, sessionID: string): string - getCompatibleTarkovVersion(): string +export interface ILauncherCallbacks { + connect(): string; + login(url: string, info: ILoginRequestData, sessionID: string): string; + register(url: string, info: IRegisterData, sessionID: string): "FAILED" | "OK"; + get(url: string, info: ILoginRequestData, sessionID: string): string; + changeUsername(url: string, info: IChangeRequestData, sessionID: string): "FAILED" | "OK"; + changePassword(url: string, info: IChangeRequestData, sessionID: string): "FAILED" | "OK"; + wipe(url: string, info: IRegisterData, sessionID: string): "FAILED" | "OK"; + getMiniProfile(url: string, info: IGetMiniProfileRequestData, sessionID: string): string; + getAllMiniProfiles(url: string, info: any, sessionID: string): string; + getServerVersion(): string; + ping(url: string, info: any, sessionID: string): string; + removeProfile(url: string, info: IRemoveProfileData, sessionID: string): string; + getCompatibleTarkovVersion(): string; } diff --git a/project/src/models/spt/callbacks/ILocationCallbacks.ts b/project/src/models/spt/callbacks/ILocationCallbacks.ts index 89000585..d6eb062b 100644 --- a/project/src/models/spt/callbacks/ILocationCallbacks.ts +++ b/project/src/models/spt/callbacks/ILocationCallbacks.ts @@ -3,8 +3,7 @@ import { ILocationsGenerateAllResponse } from "@spt/models/eft/common/ILocations import { IGetBodyResponseData } from "@spt/models/eft/httpResponse/IGetBodyResponseData"; import { IGetLocationRequestData } from "@spt/models/eft/location/IGetLocationRequestData"; -export interface ILocationCallbacks -{ - getLocationData(url: string, info: any, sessionID: string): IGetBodyResponseData - getLocation(url: string, info: IGetLocationRequestData, sessionID: string): IGetBodyResponseData +export interface ILocationCallbacks { + getLocationData(url: string, info: any, sessionID: string): IGetBodyResponseData; + getLocation(url: string, info: IGetLocationRequestData, sessionID: string): IGetBodyResponseData; } diff --git a/project/src/models/spt/callbacks/IModCallbacks.ts b/project/src/models/spt/callbacks/IModCallbacks.ts index 2beddcaa..1a4cd7be 100644 --- a/project/src/models/spt/callbacks/IModCallbacks.ts +++ b/project/src/models/spt/callbacks/IModCallbacks.ts @@ -1,7 +1,6 @@ -export interface IModCallbacks -{ - load(): void - sendBundle(sessionID: string, req: any, resp: any, body: any): void - getBundles(url: string, info: any, sessionID: string): string - getBundle(url: string, info: any, sessionID: string): string +export interface IModCallbacks { + load(): void; + sendBundle(sessionID: string, req: any, resp: any, body: any): void; + getBundles(url: string, info: any, sessionID: string): string; + getBundle(url: string, info: any, sessionID: string): string; } diff --git a/project/src/models/spt/callbacks/INoteCallbacks.ts b/project/src/models/spt/callbacks/INoteCallbacks.ts index f8034ea8..29d1a089 100644 --- a/project/src/models/spt/callbacks/INoteCallbacks.ts +++ b/project/src/models/spt/callbacks/INoteCallbacks.ts @@ -2,9 +2,8 @@ import { IPmcData } from "@spt/models/eft/common/IPmcData"; import { IItemEventRouterResponse } from "@spt/models/eft/itemEvent/IItemEventRouterResponse"; import { INoteActionData } from "@spt/models/eft/notes/INoteActionData"; -export interface INoteCallbacks -{ - addNote(pmcData: IPmcData, body: INoteActionData, sessionID: string): IItemEventRouterResponse - editNote(pmcData: IPmcData, body: INoteActionData, sessionID: string): IItemEventRouterResponse - deleteNote(pmcData: IPmcData, body: INoteActionData, sessionID: string): IItemEventRouterResponse +export interface INoteCallbacks { + addNote(pmcData: IPmcData, body: INoteActionData, sessionID: string): IItemEventRouterResponse; + editNote(pmcData: IPmcData, body: INoteActionData, sessionID: string): IItemEventRouterResponse; + deleteNote(pmcData: IPmcData, body: INoteActionData, sessionID: string): IItemEventRouterResponse; } diff --git a/project/src/models/spt/callbacks/INotifierCallbacks.ts b/project/src/models/spt/callbacks/INotifierCallbacks.ts index 1f77bdab..2579c0b6 100644 --- a/project/src/models/spt/callbacks/INotifierCallbacks.ts +++ b/project/src/models/spt/callbacks/INotifierCallbacks.ts @@ -3,21 +3,20 @@ import { IUIDRequestData } from "@spt/models/eft/common/request/IUIDRequestData" import { IGetBodyResponseData } from "@spt/models/eft/httpResponse/IGetBodyResponseData"; import { INotifierChannel } from "@spt/models/eft/notifier/INotifier"; -export interface INotifierCallbacks -{ +export interface INotifierCallbacks { /** * If we don't have anything to send, it's ok to not send anything back * because notification requests can be long-polling. In fact, we SHOULD wait * until we actually have something to send because otherwise we'd spam the client * and the client would abort the connection due to spam. */ - sendNotification(sessionID: string, req: any, resp: any, data: any): void - getNotifier(url: string, info: any, sessionID: string): IGetBodyResponseData + sendNotification(sessionID: string, req: any, resp: any, data: any): void; + getNotifier(url: string, info: any, sessionID: string): IGetBodyResponseData; createNotifierChannel( url: string, info: IEmptyRequestData, sessionID: string, - ): IGetBodyResponseData - selectProfile(url: string, info: IUIDRequestData, sessionID: string): IGetBodyResponseData - notify(url: string, info: any, sessionID: string): string + ): IGetBodyResponseData; + selectProfile(url: string, info: IUIDRequestData, sessionID: string): IGetBodyResponseData; + notify(url: string, info: any, sessionID: string): string; } diff --git a/project/src/models/spt/callbacks/IPresetBuildCallbacks.ts b/project/src/models/spt/callbacks/IPresetBuildCallbacks.ts index f7969fb1..a5001d9f 100644 --- a/project/src/models/spt/callbacks/IPresetBuildCallbacks.ts +++ b/project/src/models/spt/callbacks/IPresetBuildCallbacks.ts @@ -4,27 +4,26 @@ import { IItemEventRouterResponse } from "@spt/models/eft/itemEvent/IItemEventRo import { IPresetBuildActionRequestData } from "@spt/models/eft/presetBuild/IPresetBuildActionRequestData"; import { IWeaponBuild } from "@spt/models/eft/profile/ISptProfile"; -export interface IPresetBuildCallbacks -{ - getHandbookUserlist(url: string, info: any, sessionID: string): IGetBodyResponseData +export interface IPresetBuildCallbacks { + getHandbookUserlist(url: string, info: any, sessionID: string): IGetBodyResponseData; saveWeaponBuild( pmcData: IPmcData, body: IPresetBuildActionRequestData, sessionID: string, - ): IItemEventRouterResponse + ): IItemEventRouterResponse; removeWeaponBuild( pmcData: IPmcData, body: IPresetBuildActionRequestData, sessionID: string, - ): IItemEventRouterResponse + ): IItemEventRouterResponse; saveEquipmentBuild( pmcData: IPmcData, body: IPresetBuildActionRequestData, sessionID: string, - ): IItemEventRouterResponse + ): IItemEventRouterResponse; removeEquipmentBuild( pmcData: IPmcData, body: IPresetBuildActionRequestData, sessionID: string, - ): IItemEventRouterResponse + ): IItemEventRouterResponse; } diff --git a/project/src/models/spt/callbacks/IPresetCallbacks.ts b/project/src/models/spt/callbacks/IPresetCallbacks.ts index 31659fdb..41698575 100644 --- a/project/src/models/spt/callbacks/IPresetCallbacks.ts +++ b/project/src/models/spt/callbacks/IPresetCallbacks.ts @@ -1,4 +1,3 @@ -export interface IPresetCallbacks -{ - load(): void +export interface IPresetCallbacks { + load(): void; } diff --git a/project/src/models/spt/callbacks/IProfileCallbacks.ts b/project/src/models/spt/callbacks/IProfileCallbacks.ts index a76d4e2a..1f216d11 100644 --- a/project/src/models/spt/callbacks/IProfileCallbacks.ts +++ b/project/src/models/spt/callbacks/IProfileCallbacks.ts @@ -8,20 +8,19 @@ import { ISearchFriendRequestData } from "@spt/models/eft/profile/ISearchFriendR import { ISearchFriendResponse } from "@spt/models/eft/profile/ISearchFriendResponse"; import { IValidateNicknameRequestData } from "@spt/models/eft/profile/IValidateNicknameRequestData"; -export interface IProfileCallbacks -{ - onLoad(sessionID: string): any - createProfile(url: string, info: IProfileCreateRequestData, sessionID: string): IGetBodyResponseData - getProfileData(url: string, info: IEmptyRequestData, sessionID: string): IGetBodyResponseData - regenerateScav(url: string, info: IEmptyRequestData, sessionID: string): IGetBodyResponseData - changeVoice(url: string, info: IProfileChangeVoiceRequestData, sessionID: string): INullResponseData - changeNickname(url: string, info: IProfileChangeNicknameRequestData, sessionID: string): IGetBodyResponseData - validateNickname(url: string, info: IValidateNicknameRequestData, sessionID: string): IGetBodyResponseData - getReservedNickname(url: string, info: IEmptyRequestData, sessionID: string): IGetBodyResponseData - getProfileStatus(url: string, info: IEmptyRequestData, sessionID: string): IGetBodyResponseData +export interface IProfileCallbacks { + onLoad(sessionID: string): any; + createProfile(url: string, info: IProfileCreateRequestData, sessionID: string): IGetBodyResponseData; + getProfileData(url: string, info: IEmptyRequestData, sessionID: string): IGetBodyResponseData; + regenerateScav(url: string, info: IEmptyRequestData, sessionID: string): IGetBodyResponseData; + changeVoice(url: string, info: IProfileChangeVoiceRequestData, sessionID: string): INullResponseData; + changeNickname(url: string, info: IProfileChangeNicknameRequestData, sessionID: string): IGetBodyResponseData; + validateNickname(url: string, info: IValidateNicknameRequestData, sessionID: string): IGetBodyResponseData; + getReservedNickname(url: string, info: IEmptyRequestData, sessionID: string): IGetBodyResponseData; + getProfileStatus(url: string, info: IEmptyRequestData, sessionID: string): IGetBodyResponseData; searchFriend( url: string, info: ISearchFriendRequestData, sessionID: string, - ): IGetBodyResponseData + ): IGetBodyResponseData; } diff --git a/project/src/models/spt/callbacks/IQuestCallbacks.ts b/project/src/models/spt/callbacks/IQuestCallbacks.ts index 0a6cbdc4..f7e772f0 100644 --- a/project/src/models/spt/callbacks/IQuestCallbacks.ts +++ b/project/src/models/spt/callbacks/IQuestCallbacks.ts @@ -10,20 +10,19 @@ import { IHandoverQuestRequestData } from "@spt/models/eft/quests/IHandoverQuest import { IListQuestsRequestData } from "@spt/models/eft/quests/IListQuestsRequestData"; import { IRepeatableQuestChangeRequest } from "@spt/models/eft/quests/IRepeatableQuestChangeRequest"; -export interface IQuestCallbacks -{ +export interface IQuestCallbacks { changeRepeatableQuest( pmcData: IPmcData, body: IRepeatableQuestChangeRequest, sessionID: string, - ): IItemEventRouterResponse - acceptQuest(pmcData: IPmcData, body: IAcceptQuestRequestData, sessionID: string): IItemEventRouterResponse - completeQuest(pmcData: IPmcData, body: ICompleteQuestRequestData, sessionID: string): IItemEventRouterResponse - handoverQuest(pmcData: IPmcData, body: IHandoverQuestRequestData, sessionID: string): IItemEventRouterResponse - listQuests(url: string, info: IListQuestsRequestData, sessionID: string): IGetBodyResponseData + ): IItemEventRouterResponse; + acceptQuest(pmcData: IPmcData, body: IAcceptQuestRequestData, sessionID: string): IItemEventRouterResponse; + completeQuest(pmcData: IPmcData, body: ICompleteQuestRequestData, sessionID: string): IItemEventRouterResponse; + handoverQuest(pmcData: IPmcData, body: IHandoverQuestRequestData, sessionID: string): IItemEventRouterResponse; + listQuests(url: string, info: IListQuestsRequestData, sessionID: string): IGetBodyResponseData; activityPeriods( url: string, info: IEmptyRequestData, sessionID: string, - ): IGetBodyResponseData + ): IGetBodyResponseData; } diff --git a/project/src/models/spt/callbacks/IRagfairCallbacks.ts b/project/src/models/spt/callbacks/IRagfairCallbacks.ts index 4ef25bf3..0bdbffb8 100644 --- a/project/src/models/spt/callbacks/IRagfairCallbacks.ts +++ b/project/src/models/spt/callbacks/IRagfairCallbacks.ts @@ -9,19 +9,18 @@ import { IGetMarketPriceRequestData } from "@spt/models/eft/ragfair/IGetMarketPr import { IRemoveOfferRequestData } from "@spt/models/eft/ragfair/IRemoveOfferRequestData"; import { ISearchRequestData } from "@spt/models/eft/ragfair/ISearchRequestData"; -export interface IRagfairCallbacks -{ - load(): void - search(url: string, info: ISearchRequestData, sessionID: string): IGetBodyResponseData +export interface IRagfairCallbacks { + load(): void; + search(url: string, info: ISearchRequestData, sessionID: string): IGetBodyResponseData; getMarketPrice( url: string, info: IGetMarketPriceRequestData, sessionID: string, - ): IGetBodyResponseData - getItemPrices(url: string, info: IEmptyRequestData, sessionID: string): IGetBodyResponseData - addOffer(pmcData: IPmcData, info: IAddOfferRequestData, sessionID: string): IItemEventRouterResponse - removeOffer(pmcData: IPmcData, info: IRemoveOfferRequestData, sessionID: string): IItemEventRouterResponse - extendOffer(pmcData: IPmcData, info: IExtendOfferRequestData, sessionID: string): IItemEventRouterResponse - update(timeSinceLastRun: number): boolean - updatePlayer(timeSinceLastRun: number): boolean + ): IGetBodyResponseData; + getItemPrices(url: string, info: IEmptyRequestData, sessionID: string): IGetBodyResponseData; + addOffer(pmcData: IPmcData, info: IAddOfferRequestData, sessionID: string): IItemEventRouterResponse; + removeOffer(pmcData: IPmcData, info: IRemoveOfferRequestData, sessionID: string): IItemEventRouterResponse; + extendOffer(pmcData: IPmcData, info: IExtendOfferRequestData, sessionID: string): IItemEventRouterResponse; + update(timeSinceLastRun: number): boolean; + updatePlayer(timeSinceLastRun: number): boolean; } diff --git a/project/src/models/spt/callbacks/IRepairCallbacks.ts b/project/src/models/spt/callbacks/IRepairCallbacks.ts index f177c851..8b6df025 100644 --- a/project/src/models/spt/callbacks/IRepairCallbacks.ts +++ b/project/src/models/spt/callbacks/IRepairCallbacks.ts @@ -3,8 +3,7 @@ import { IItemEventRouterResponse } from "@spt/models/eft/itemEvent/IItemEventRo import { IRepairActionDataRequest } from "@spt/models/eft/repair/IRepairActionDataRequest"; import { ITraderRepairActionDataRequest } from "@spt/models/eft/repair/ITraderRepairActionDataRequest"; -export interface IRepairCallbacks -{ - traderRepair(pmcData: IPmcData, body: ITraderRepairActionDataRequest, sessionID: string): IItemEventRouterResponse - repair(pmcData: IPmcData, body: IRepairActionDataRequest, sessionID: string): IItemEventRouterResponse +export interface IRepairCallbacks { + traderRepair(pmcData: IPmcData, body: ITraderRepairActionDataRequest, sessionID: string): IItemEventRouterResponse; + repair(pmcData: IPmcData, body: IRepairActionDataRequest, sessionID: string): IItemEventRouterResponse; } diff --git a/project/src/models/spt/callbacks/ISaveCallbacks.ts b/project/src/models/spt/callbacks/ISaveCallbacks.ts index b054464d..1ad3b826 100644 --- a/project/src/models/spt/callbacks/ISaveCallbacks.ts +++ b/project/src/models/spt/callbacks/ISaveCallbacks.ts @@ -1,5 +1,4 @@ -export interface ISaveCallbacks -{ - load(): void - update(secondsSinceLastRun: number): boolean +export interface ISaveCallbacks { + load(): void; + update(secondsSinceLastRun: number): boolean; } diff --git a/project/src/models/spt/callbacks/ITradeCallbacks.ts b/project/src/models/spt/callbacks/ITradeCallbacks.ts index e2564bdc..2bb1626c 100644 --- a/project/src/models/spt/callbacks/ITradeCallbacks.ts +++ b/project/src/models/spt/callbacks/ITradeCallbacks.ts @@ -3,12 +3,11 @@ import { IItemEventRouterResponse } from "@spt/models/eft/itemEvent/IItemEventRo import { IProcessBaseTradeRequestData } from "@spt/models/eft/trade/IProcessBaseTradeRequestData"; import { IProcessRagfairTradeRequestData } from "@spt/models/eft/trade/IProcessRagfairTradeRequestData"; -export interface ITradeCallbacks -{ - processTrade(pmcData: IPmcData, body: IProcessBaseTradeRequestData, sessionID: string): IItemEventRouterResponse +export interface ITradeCallbacks { + processTrade(pmcData: IPmcData, body: IProcessBaseTradeRequestData, sessionID: string): IItemEventRouterResponse; processRagfairTrade( pmcData: IPmcData, body: IProcessRagfairTradeRequestData, sessionID: string, - ): IItemEventRouterResponse + ): IItemEventRouterResponse; } diff --git a/project/src/models/spt/callbacks/ITraderCallbacks.ts b/project/src/models/spt/callbacks/ITraderCallbacks.ts index 91e6c63a..969a8cc6 100644 --- a/project/src/models/spt/callbacks/ITraderCallbacks.ts +++ b/project/src/models/spt/callbacks/ITraderCallbacks.ts @@ -6,11 +6,10 @@ import { IEmptyRequestData } from "@spt/models/eft/common/IEmptyRequestData"; import { ITraderAssort, ITraderBase } from "@spt/models/eft/common/tables/ITrader"; import { IGetBodyResponseData } from "@spt/models/eft/httpResponse/IGetBodyResponseData"; -export interface ITraderCallbacks -{ - load(): void - getTraderSettings(url: string, info: IEmptyRequestData, sessionID: string): IGetBodyResponseData - getTrader(url: string, info: IEmptyRequestData, sessionID: string): IGetBodyResponseData - getAssort(url: string, info: IEmptyRequestData, sessionID: string): IGetBodyResponseData - update(): boolean +export interface ITraderCallbacks { + load(): void; + getTraderSettings(url: string, info: IEmptyRequestData, sessionID: string): IGetBodyResponseData; + getTrader(url: string, info: IEmptyRequestData, sessionID: string): IGetBodyResponseData; + getAssort(url: string, info: IEmptyRequestData, sessionID: string): IGetBodyResponseData; + update(): boolean; } diff --git a/project/src/models/spt/callbacks/IWeatherCallbacks.ts b/project/src/models/spt/callbacks/IWeatherCallbacks.ts index 593c305a..118aec12 100644 --- a/project/src/models/spt/callbacks/IWeatherCallbacks.ts +++ b/project/src/models/spt/callbacks/IWeatherCallbacks.ts @@ -1,7 +1,6 @@ import { IEmptyRequestData } from "@spt/models/eft/common/IEmptyRequestData"; import { IGetBodyResponseData } from "@spt/models/eft/httpResponse/IGetBodyResponseData"; -export interface IWeatherCallbacks -{ - getWeather(url: string, info: IEmptyRequestData, sessionID: string): IGetBodyResponseData +export interface IWeatherCallbacks { + getWeather(url: string, info: IEmptyRequestData, sessionID: string): IGetBodyResponseData; } diff --git a/project/src/models/spt/config/IAirdropConfig.ts b/project/src/models/spt/config/IAirdropConfig.ts index 5759a606..8268fc89 100644 --- a/project/src/models/spt/config/IAirdropConfig.ts +++ b/project/src/models/spt/config/IAirdropConfig.ts @@ -2,48 +2,45 @@ import { MinMax } from "@spt/models/common/MinMax"; import { AirdropTypeEnum } from "@spt/models/enums/AirdropType"; import { IBaseConfig } from "@spt/models/spt/config/IBaseConfig"; -export interface IAirdropConfig extends IBaseConfig -{ - kind: "spt-airdrop" - airdropTypeWeightings: Record +export interface IAirdropConfig extends IBaseConfig { + kind: "spt-airdrop"; + airdropTypeWeightings: Record; /** What rewards will the loot crate contain, keyed by drop type e.g. mixed/weaponArmor/foodMedical/barter */ - loot: Record + loot: Record; } /** Chance map will have an airdrop occur out of 100 - locations not included count as 0% */ -export interface AirdropChancePercent -{ - bigmap: number - woods: number - lighthouse: number - shoreline: number - interchange: number - reserve: number - tarkovStreets: number - sandbox: number +export interface AirdropChancePercent { + bigmap: number; + woods: number; + lighthouse: number; + shoreline: number; + interchange: number; + reserve: number; + tarkovStreets: number; + sandbox: number; } /** Loot inside crate */ -export interface AirdropLoot -{ +export interface AirdropLoot { /** Min/max of weapons inside crate */ - weaponPresetCount?: MinMax + weaponPresetCount?: MinMax; /** Min/max of armors (head/chest/rig) inside crate */ - armorPresetCount?: MinMax + armorPresetCount?: MinMax; /** Min/max of items inside crate */ - itemCount: MinMax + itemCount: MinMax; /** Min/max of sealed weapon boxes inside crate */ - weaponCrateCount: MinMax + weaponCrateCount: MinMax; /** Items to never allow - tpls */ - itemBlacklist: string[] + itemBlacklist: string[]; /** Item type (parentId) to allow inside crate */ - itemTypeWhitelist: string[] + itemTypeWhitelist: string[]; /** Item type/ item tpls to limit count of inside crate - key: item base type: value: max count */ - itemLimits: Record + itemLimits: Record; /** Items to limit stack size of key: item tpl value: min/max stack size */ - itemStackLimits: Record + itemStackLimits: Record; /** Armor levels to allow inside crate e.g. [4,5,6] */ - armorLevelWhitelist?: number[] + armorLevelWhitelist?: number[]; /** Should boss items be added to airdrop crate */ - allowBossItems: boolean + allowBossItems: boolean; } diff --git a/project/src/models/spt/config/IBaseConfig.ts b/project/src/models/spt/config/IBaseConfig.ts index 11a77c73..fea523bf 100644 --- a/project/src/models/spt/config/IBaseConfig.ts +++ b/project/src/models/spt/config/IBaseConfig.ts @@ -1,10 +1,8 @@ -export interface IBaseConfig -{ - kind: string +export interface IBaseConfig { + kind: string; } -export interface IRunIntervalValues -{ - inRaid: number - outOfRaid: number +export interface IRunIntervalValues { + inRaid: number; + outOfRaid: number; } diff --git a/project/src/models/spt/config/IBotConfig.ts b/project/src/models/spt/config/IBotConfig.ts index 582987c7..dea58b63 100644 --- a/project/src/models/spt/config/IBotConfig.ts +++ b/project/src/models/spt/config/IBotConfig.ts @@ -3,215 +3,202 @@ import { GenerationData } from "@spt/models/eft/common/tables/IBotType"; import { IBaseConfig } from "@spt/models/spt/config/IBaseConfig"; import { IBotDurability } from "@spt/models/spt/config/IBotDurability"; -export interface IBotConfig extends IBaseConfig -{ - kind: "spt-bot" +export interface IBotConfig extends IBaseConfig { + kind: "spt-bot"; /** How many variants of each bot should be generated on raid start */ - presetBatch: PresetBatch + presetBatch: PresetBatch; /** Bot roles that should not have PMC types (pmcBEAR/pmcUSEC) added as enemies to */ - botsToNotAddPMCsAsEnemiesTo: string[] + botsToNotAddPMCsAsEnemiesTo: string[]; /** What bot types should be classified as bosses */ - bosses: string[] + bosses: string[]; /** Control weapon/armor durability min/max values for each bot type */ - durability: IBotDurability + durability: IBotDurability; /** Controls the percentage values of randomization item resources */ - lootItemResourceRandomization: Record + lootItemResourceRandomization: Record; /** Control what bots are added to a bots revenge list key: bottype, value: bottypes to revenge on seeing their death */ - revenge: Record + revenge: Record; /** Control how many items are allowed to spawn on a bot * key: bottype, value: */ - itemSpawnLimits: Record> + itemSpawnLimits: Record>; /** Blacklist/whitelist items on a bot */ - equipment: Record + equipment: Record; /** Show a bots botType value after their name */ - showTypeInNickname: boolean + showTypeInNickname: boolean; /** What ai brain should a normal scav use per map */ - assaultBrainType: Record> + assaultBrainType: Record>; /** What ai brain should a player scav use per map */ - playerScavBrainType: Record> + playerScavBrainType: Record>; /** Max number of bots that can be spawned in a raid at any one time */ - maxBotCap: Record + maxBotCap: Record; /** Chance scav has fake pscav name e.g. Scav name (player name) */ - chanceAssaultScavHasPlayerScavName: number + chanceAssaultScavHasPlayerScavName: number; /** How many stacks of secret ammo should a bot have in its bot secure container */ - secureContainerAmmoStackCount: number + secureContainerAmmoStackCount: number; /** Bot roles in this array will be given a dog tag on generation */ - botRolesWithDogTags: string[] + botRolesWithDogTags: string[]; /** Settings to control the items that get added into wallets on bots */ - walletLoot: IWalletLootSettings + walletLoot: IWalletLootSettings; /** Currency weights, Keyed by botrole / currency */ - currencyStackSize: Record>> + currencyStackSize: Record>>; /** Tpls for low profile gas blocks */ - lowProfileGasBlockTpls: string[] + lowProfileGasBlockTpls: string[]; /** What bottypes should be excluded from having loot generated on them (backpack/pocket/vest) does not disable food/drink/special/ */ - disableLootOnBotTypes: string[] - assaultToBossConversion: IAssaultToBossConversion + disableLootOnBotTypes: string[]; + assaultToBossConversion: IAssaultToBossConversion; } -export interface IAssaultToBossConversion -{ - bossConvertEnabled: boolean - bossesToConvertToWeights: Record - bossConvertMinMax: Record +export interface IAssaultToBossConversion { + bossConvertEnabled: boolean; + bossesToConvertToWeights: Record; + bossConvertMinMax: Record; } /** Number of bots to generate and store in cache on raid start per bot type */ -export interface PresetBatch -{ - assault: number - bossBully: number - bossGluhar: number - bossKilla: number - bossKojaniy: number - bossSanitar: number - bossTagilla: number - bossKnight: number - bossTest: number - cursedAssault: number - followerBully: number - followerGluharAssault: number - followerGluharScout: number - followerGluharSecurity: number - followerGluharSnipe: number - followerKojaniy: number - followerSanitar: number - followerTagilla: number - followerBirdEye: number - followerBigPipe: number - followerTest: number - followerBoar: number - marksman: number - pmcBot: number - sectantPriest: number - sectantWarrior: number - gifter: number - test: number - exUsec: number - arenaFighterEvent: number - arenaFighter: number - crazyAssaultEvent: number - bossBoar: number - bossBoarSniper: number - pmcUSEC: number - pmcBEAR: number +export interface PresetBatch { + assault: number; + bossBully: number; + bossGluhar: number; + bossKilla: number; + bossKojaniy: number; + bossSanitar: number; + bossTagilla: number; + bossKnight: number; + bossTest: number; + cursedAssault: number; + followerBully: number; + followerGluharAssault: number; + followerGluharScout: number; + followerGluharSecurity: number; + followerGluharSnipe: number; + followerKojaniy: number; + followerSanitar: number; + followerTagilla: number; + followerBirdEye: number; + followerBigPipe: number; + followerTest: number; + followerBoar: number; + marksman: number; + pmcBot: number; + sectantPriest: number; + sectantWarrior: number; + gifter: number; + test: number; + exUsec: number; + arenaFighterEvent: number; + arenaFighter: number; + crazyAssaultEvent: number; + bossBoar: number; + bossBoarSniper: number; + pmcUSEC: number; + pmcBEAR: number; } -export interface IWalletLootSettings -{ +export interface IWalletLootSettings { /** Chance wallets have loot in them */ - chancePercent: number - itemCount: MinMax - stackSizeWeight: Record - currencyWeight: Record + chancePercent: number; + itemCount: MinMax; + stackSizeWeight: Record; + currencyWeight: Record; /** What wallets will have money in them */ - walletTplPool: string[] + walletTplPool: string[]; } -export interface EquipmentFilters -{ +export interface EquipmentFilters { /** Limits for mod types per weapon .e.g. scopes */ - weaponModLimits: ModLimits + weaponModLimits: ModLimits; /** Whitelist for weapon sight types allowed per gun */ - weaponSightWhitelist: Record + weaponSightWhitelist: Record; /** Chance face shield is down/active */ - faceShieldIsActiveChancePercent?: number + faceShieldIsActiveChancePercent?: number; /** Chance gun flashlight is active during the day */ - lightIsActiveDayChancePercent?: number + lightIsActiveDayChancePercent?: number; /** Chance gun flashlight is active during the night */ - lightIsActiveNightChancePercent?: number + lightIsActiveNightChancePercent?: number; /** Chance gun laser is active during the day */ - laserIsActiveChancePercent?: number + laserIsActiveChancePercent?: number; /** Chance NODS are down/active during the day */ - nvgIsActiveChanceDayPercent?: number + nvgIsActiveChanceDayPercent?: number; /** Chance NODS are down/active during the night */ - nvgIsActiveChanceNightPercent?: number - forceOnlyArmoredRigWhenNoArmor?: boolean + nvgIsActiveChanceNightPercent?: number; + forceOnlyArmoredRigWhenNoArmor?: boolean; /** Should plates be filtered by level */ - filterPlatesByLevel?: boolean + filterPlatesByLevel?: boolean; /** What additional slot ids should be seen as required when choosing a mod to add to a weapon */ - weaponSlotIdsToMakeRequired?: string[] + weaponSlotIdsToMakeRequired?: string[]; /** Adjust weighting/chances of items on bot by level of bot */ - randomisation: RandomisationDetails[] + randomisation: RandomisationDetails[]; /** Blacklist equipment by level of bot */ - blacklist: EquipmentFilterDetails[] + blacklist: EquipmentFilterDetails[]; /** Whitelist equipment by level of bot */ - whitelist: EquipmentFilterDetails[] + whitelist: EquipmentFilterDetails[]; /** Adjust equipment/ammo */ - weightingAdjustmentsByBotLevel: WeightingAdjustmentDetails[] + weightingAdjustmentsByBotLevel: WeightingAdjustmentDetails[]; /** Same as weightingAdjustments but based on player level instead of bot level */ - weightingAdjustmentsByPlayerLevel?: WeightingAdjustmentDetails[] + weightingAdjustmentsByPlayerLevel?: WeightingAdjustmentDetails[]; /** Should the stock mod be forced to spawn on bot */ - forceStock?: boolean - armorPlateWeighting?: IArmorPlateWeights[] + forceStock?: boolean; + armorPlateWeighting?: IArmorPlateWeights[]; } -export interface ModLimits -{ +export interface ModLimits { /** How many scopes are allowed on a weapon - hard coded to work with OPTIC_SCOPE, ASSAULT_SCOPE, COLLIMATOR, COMPACT_COLLIMATOR */ - scopeLimit?: number + scopeLimit?: number; /** How many lasers or lights are allowed on a weapon - hard coded to work with TACTICAL_COMBO, and FLASHLIGHT */ - lightLaserLimit?: number + lightLaserLimit?: number; } -export interface RandomisationDetails -{ +export interface RandomisationDetails { /** Between what levels do these randomisation setting apply to */ - levelRange: MinMax - generation?: Record + levelRange: MinMax; + generation?: Record; /** Mod slots that should be fully randomised -ignores mods from bottype.json and instaed creates a pool using items.json */ - randomisedWeaponModSlots?: string[] + randomisedWeaponModSlots?: string[]; /** Armor slots that should be randomised e.g. 'Headwear, Armband' */ - randomisedArmorSlots?: string[] + randomisedArmorSlots?: string[]; /** Equipment chances */ - equipment?: Record + equipment?: Record; /** Weapon mod chances */ - weaponMods?: Record + weaponMods?: Record; /** Equipment mod chances */ - equipmentMods?: Record + equipmentMods?: Record; } -export interface EquipmentFilterDetails -{ +export interface EquipmentFilterDetails { /** Between what levels do these equipment filter setting apply to */ - levelRange: MinMax + levelRange: MinMax; /** Key: mod slot name e.g. mod_magazine, value: item tpls */ - equipment: Record + equipment: Record; /** Key: cartridge type e.g. Caliber23x75, value: item tpls */ - cartridge: Record + cartridge: Record; } -export interface WeightingAdjustmentDetails -{ +export interface WeightingAdjustmentDetails { /** Between what levels do these weight settings apply to */ - levelRange: MinMax + levelRange: MinMax; /** Key: ammo type e.g. Caliber556x45NATO, value: item tpl + weight */ - ammo?: IAdjustmentDetails + ammo?: IAdjustmentDetails; /** Key: equipment slot e.g. TacticalVest, value: item tpl + weight */ - equipment?: IAdjustmentDetails + equipment?: IAdjustmentDetails; /** Key: clothing slot e.g. feet, value: item tpl + weight */ - clothing?: IAdjustmentDetails + clothing?: IAdjustmentDetails; } -export interface IAdjustmentDetails -{ - add: Record> - edit: Record> +export interface IAdjustmentDetails { + add: Record>; + edit: Record>; } -export interface IArmorPlateWeights extends Record -{ - levelRange: MinMax +export interface IArmorPlateWeights extends Record { + levelRange: MinMax; } -export interface IRandomisedResourceDetails -{ - food: IRandomisedResourceValues - meds: IRandomisedResourceValues +export interface IRandomisedResourceDetails { + food: IRandomisedResourceValues; + meds: IRandomisedResourceValues; } -export interface IRandomisedResourceValues -{ +export interface IRandomisedResourceValues { /** Minimum percent of item to randomized between min and max resource */ - resourcePercent: number + resourcePercent: number; /** Chance for randomization to not occur */ - chanceMaxResourcePercent: number + chanceMaxResourcePercent: number; } diff --git a/project/src/models/spt/config/IBotDurability.ts b/project/src/models/spt/config/IBotDurability.ts index 92b25859..7cb4f015 100644 --- a/project/src/models/spt/config/IBotDurability.ts +++ b/project/src/models/spt/config/IBotDurability.ts @@ -1,61 +1,54 @@ -export interface IBotDurability -{ - default: DefaultDurability - pmc: PmcDurability - boss: BotDurability - follower: BotDurability - assault: BotDurability - cursedassault: BotDurability - marksman: BotDurability - pmcbot: BotDurability - arenafighterevent: BotDurability - arenafighter: BotDurability - crazyassaultevent: BotDurability - exusec: BotDurability - gifter: BotDurability - sectantpriest: BotDurability - sectantwarrior: BotDurability +export interface IBotDurability { + default: DefaultDurability; + pmc: PmcDurability; + boss: BotDurability; + follower: BotDurability; + assault: BotDurability; + cursedassault: BotDurability; + marksman: BotDurability; + pmcbot: BotDurability; + arenafighterevent: BotDurability; + arenafighter: BotDurability; + crazyassaultevent: BotDurability; + exusec: BotDurability; + gifter: BotDurability; + sectantpriest: BotDurability; + sectantwarrior: BotDurability; } /** Durability values to be used when a more specific bot type cant be found */ -export interface DefaultDurability -{ - armor: ArmorDurability - weapon: WeaponDurability +export interface DefaultDurability { + armor: ArmorDurability; + weapon: WeaponDurability; } -export interface PmcDurability -{ - armor: PmcDurabilityArmor - weapon: WeaponDurability +export interface PmcDurability { + armor: PmcDurabilityArmor; + weapon: WeaponDurability; } -export interface PmcDurabilityArmor -{ - lowestMaxPercent: number - highestMaxPercent: number - maxDelta: number - minDelta: number +export interface PmcDurabilityArmor { + lowestMaxPercent: number; + highestMaxPercent: number; + maxDelta: number; + minDelta: number; } -export interface BotDurability -{ - armor: ArmorDurability - weapon: WeaponDurability +export interface BotDurability { + armor: ArmorDurability; + weapon: WeaponDurability; } -export interface ArmorDurability -{ - maxDelta: number - minDelta: number - minLimitPercent: number +export interface ArmorDurability { + maxDelta: number; + minDelta: number; + minLimitPercent: number; } -export interface WeaponDurability -{ - lowestMax: number - highestMax: number - maxDelta: number - minDelta: number - minLimitPercent: number +export interface WeaponDurability { + lowestMax: number; + highestMax: number; + maxDelta: number; + minDelta: number; + minLimitPercent: number; } diff --git a/project/src/models/spt/config/ICoreConfig.ts b/project/src/models/spt/config/ICoreConfig.ts index 1b53c3f7..28863aec 100644 --- a/project/src/models/spt/config/ICoreConfig.ts +++ b/project/src/models/spt/config/ICoreConfig.ts @@ -1,29 +1,27 @@ import { IBaseConfig } from "@spt/models/spt/config/IBaseConfig"; -export interface ICoreConfig extends IBaseConfig -{ - kind: "spt-core" - sptVersion: string - projectName: string - compatibleTarkovVersion: string - serverName: string - profileSaveIntervalSeconds: number - sptFriendNickname: string - allowProfileWipe: boolean - bsgLogging: IBsgLogging - release: IRelease - fixes: IGameFixes - features: IServerFeatures +export interface ICoreConfig extends IBaseConfig { + kind: "spt-core"; + sptVersion: string; + projectName: string; + compatibleTarkovVersion: string; + serverName: string; + profileSaveIntervalSeconds: number; + sptFriendNickname: string; + allowProfileWipe: boolean; + bsgLogging: IBsgLogging; + release: IRelease; + fixes: IGameFixes; + features: IServerFeatures; /** Commit hash build server was created from */ - commit?: string + commit?: string; /** Timestamp of server build */ - buildTime?: string + buildTime?: string; /** Server locale keys that will be added to the bottom of the startup watermark */ - customWatermarkLocaleKeys?: string[] + customWatermarkLocaleKeys?: string[]; } -export interface IBsgLogging -{ +export interface IBsgLogging { /** * verbosity of what to log, yes I know this is backwards, but its how nlog deals with ordinals. * complain to them about it! In all cases, better exceptions will be logged. @@ -36,70 +34,65 @@ export interface IBsgLogging * 5 - fatal * 6 - off */ - verbosity: number + verbosity: number; // Should we send the logging to the server - sendToServer: boolean + sendToServer: boolean; } -export interface IRelease -{ +export interface IRelease { // Disclaimer outlining the intended usage of bleeding edge - betaDisclaimerText?: string + betaDisclaimerText?: string; // Text logged when users agreed to terms - betaDisclaimerAcceptText: string + betaDisclaimerAcceptText: string; // Server mods loaded message - serverModsLoadedText: string + serverModsLoadedText: string; // Server mods loaded debug message text - serverModsLoadedDebugText: string + serverModsLoadedDebugText: string; // Client mods loaded message - clientModsLoadedText: string + clientModsLoadedText: string; // Client mods loaded debug message text - clientModsLoadedDebugText: string + clientModsLoadedDebugText: string; // Illegal plugins log message - illegalPluginsLoadedText: string + illegalPluginsLoadedText: string; // Illegal plugins exception - illegalPluginsExceptionText: string + illegalPluginsExceptionText: string; // Summary of release changes - releaseSummaryText?: string + releaseSummaryText?: string; // Enables the cool watermark in-game - isBeta?: boolean + isBeta?: boolean; // Whether mods are enabled - isModdable?: boolean + isModdable?: boolean; // Are mods loaded on the server? - isModded: boolean + isModded: boolean; // How long before the messagebox times out and closes the game - betaDisclaimerTimeoutDelay: number + betaDisclaimerTimeoutDelay: number; } -export interface IGameFixes -{ +export interface IGameFixes { /** Shotguns use a different value than normal guns causing huge pellet dispersion */ - fixShotgunDispersion: boolean + fixShotgunDispersion: boolean; /** Remove items added by mods when the mod no longer exists - can fix dead profiles stuck at game load */ - removeModItemsFromProfile: boolean + removeModItemsFromProfile: boolean; /** Fix issues that cause the game to not start due to inventory item issues */ - fixProfileBreakingInventoryItemIssues: boolean + fixProfileBreakingInventoryItemIssues: boolean; } -export interface IServerFeatures -{ +export interface IServerFeatures { /* Controls whether or not the server attempts to download mod dependencies not included in the server's executable */ - autoInstallModDependencies: boolean - compressProfile: boolean - chatbotFeatures: IChatbotFeatures + autoInstallModDependencies: boolean; + compressProfile: boolean; + chatbotFeatures: IChatbotFeatures; /** Keyed to profile type e.g. "Standard" or "SPT Developer" */ - createNewProfileTypesBlacklist: string[] + createNewProfileTypesBlacklist: string[]; } -export interface IChatbotFeatures -{ - sptFriendEnabled: boolean - commandoEnabled: boolean - commandoFeatures: ICommandoFeatures - commandUseLimits: Record +export interface IChatbotFeatures { + sptFriendEnabled: boolean; + commandoEnabled: boolean; + commandoFeatures: ICommandoFeatures; + commandUseLimits: Record; } -export interface ICommandoFeatures -{ - giveCommandEnabled: boolean +export interface ICommandoFeatures { + giveCommandEnabled: boolean; } diff --git a/project/src/models/spt/config/IGiftsConfig.ts b/project/src/models/spt/config/IGiftsConfig.ts index cd35693a..fc21a913 100644 --- a/project/src/models/spt/config/IGiftsConfig.ts +++ b/project/src/models/spt/config/IGiftsConfig.ts @@ -6,31 +6,29 @@ import { Traders } from "@spt/models/enums/Traders"; import { IBaseConfig } from "@spt/models/spt/config/IBaseConfig"; import { IProfileChangeEvent } from "@spt/models/spt/dialog/ISendMessageDetails"; -export interface IGiftsConfig extends IBaseConfig -{ - kind: "spt-gifts" - gifts: Record +export interface IGiftsConfig extends IBaseConfig { + kind: "spt-gifts"; + gifts: Record; } -export interface Gift -{ +export interface Gift { /** Items to send to player */ - items: Item[] + items: Item[]; /** Who is sending the gift to player */ - sender: GiftSenderType + sender: GiftSenderType; /** Optinal - supply a users id to send from, not necessary when sending from SYSTEM or TRADER */ - senderId?: string - senderDetails: IUserDialogInfo + senderId?: string; + senderDetails: IUserDialogInfo; /** Optional - supply a trader type to send from, not necessary when sending from SYSTEM or USER */ - trader?: Traders - messageText: string + trader?: Traders; + messageText: string; /** Optional - if sending text from the client locale file */ - localeTextId?: string + localeTextId?: string; /** Optional - Used by Seasonal events to send on specific day */ - timestampToSend?: number - associatedEvent: SeasonalEventType - collectionTimeHours: number + timestampToSend?: number; + associatedEvent: SeasonalEventType; + collectionTimeHours: number; /** Optional, can be used to change profile settings like level/skills */ - profileChangeEvents?: IProfileChangeEvent[] - maxToSendPlayer?: number + profileChangeEvents?: IProfileChangeEvent[]; + maxToSendPlayer?: number; } diff --git a/project/src/models/spt/config/IHealthConfig.ts b/project/src/models/spt/config/IHealthConfig.ts index 31ea1011..3422a259 100644 --- a/project/src/models/spt/config/IHealthConfig.ts +++ b/project/src/models/spt/config/IHealthConfig.ts @@ -1,20 +1,17 @@ import { IBaseConfig } from "@spt/models/spt/config/IBaseConfig"; -export interface IHealthConfig extends IBaseConfig -{ - kind: "spt-health" - healthMultipliers: HealthMultipliers - save: Save +export interface IHealthConfig extends IBaseConfig { + kind: "spt-health"; + healthMultipliers: HealthMultipliers; + save: Save; } -export interface HealthMultipliers -{ - death: number - blacked: number +export interface HealthMultipliers { + death: number; + blacked: number; } -export interface Save -{ - health: boolean - effects: boolean +export interface Save { + health: boolean; + effects: boolean; } diff --git a/project/src/models/spt/config/IHideoutConfig.ts b/project/src/models/spt/config/IHideoutConfig.ts index e106b42c..1e4039a9 100644 --- a/project/src/models/spt/config/IHideoutConfig.ts +++ b/project/src/models/spt/config/IHideoutConfig.ts @@ -1,16 +1,15 @@ import { IBaseConfig, IRunIntervalValues } from "@spt/models/spt/config/IBaseConfig"; -export interface IHideoutConfig extends IBaseConfig -{ - kind: "spt-hideout" +export interface IHideoutConfig extends IBaseConfig { + kind: "spt-hideout"; /** How many seconds should pass before hideout crafts / fuel usage is checked and procesed */ - runIntervalSeconds: number + runIntervalSeconds: number; /** Default values used to hydrate `runIntervalSeconds` with */ - runIntervalValues: IRunIntervalValues - hoursForSkillCrafting: number - expCraftAmount: number - overrideCraftTimeSeconds: number - overrideBuildTimeSeconds: number + runIntervalValues: IRunIntervalValues; + hoursForSkillCrafting: number; + expCraftAmount: number; + overrideCraftTimeSeconds: number; + overrideBuildTimeSeconds: number; /** Only process a profiles hideout crafts when it has been active in the last x minutes */ - updateProfileHideoutWhenActiveWithinMinutes: number + updateProfileHideoutWhenActiveWithinMinutes: number; } diff --git a/project/src/models/spt/config/IHttpConfig.ts b/project/src/models/spt/config/IHttpConfig.ts index 6e7eb2ee..2fc92306 100644 --- a/project/src/models/spt/config/IHttpConfig.ts +++ b/project/src/models/spt/config/IHttpConfig.ts @@ -1,16 +1,15 @@ import { IBaseConfig } from "@spt/models/spt/config/IBaseConfig"; -export interface IHttpConfig extends IBaseConfig -{ - kind: "spt-http" +export interface IHttpConfig extends IBaseConfig { + kind: "spt-http"; /** Address used by webserver */ - ip: string - port: number + ip: string; + port: number; /** Address used by game client to connect to */ - backendIp: string - backendPort: string - webSocketPingDelayMs: number - logRequests: boolean + backendIp: string; + backendPort: string; + webSocketPingDelayMs: number; + logRequests: boolean; /** e.g. "SPT_Data/Server/images/traders/579dc571d53a0658a154fbec.png": "SPT_Data/Server/images/traders/NewTraderImage.png" */ - serverImagePathOverride: Record + serverImagePathOverride: Record; } diff --git a/project/src/models/spt/config/IInRaidConfig.ts b/project/src/models/spt/config/IInRaidConfig.ts index b8ce4608..33170d48 100644 --- a/project/src/models/spt/config/IInRaidConfig.ts +++ b/project/src/models/spt/config/IInRaidConfig.ts @@ -1,45 +1,42 @@ import { IBaseConfig } from "@spt/models/spt/config/IBaseConfig"; -export interface IInRaidConfig extends IBaseConfig -{ - kind: "spt-inraid" - MIAOnRaidEnd: boolean +export interface IInRaidConfig extends IBaseConfig { + kind: "spt-inraid"; + MIAOnRaidEnd: boolean; /** Overrides to apply to the pre-raid settings screen */ - raidMenuSettings: RaidMenuSettings + raidMenuSettings: RaidMenuSettings; /** What effects should be saved post-raid */ - save: Save + save: Save; /** Names of car extracts */ - carExtracts: string[] + carExtracts: string[]; /** Names of coop extracts */ - coopExtracts: string[] + coopExtracts: string[]; /** Fence rep gain from a single car extract */ - carExtractBaseStandingGain: number + carExtractBaseStandingGain: number; /** Fence rep gain from a single coop extract */ - coopExtractBaseStandingGain: number + coopExtractBaseStandingGain: number; /** Fence rep gain when successfully extracting as pscav */ - scavExtractGain: number + scavExtractGain: number; /** The likelihood of PMC eliminating a minimum of 2 scavs while you engage them as a pscav. */ - pmcKillProbabilityForScavGain: number + pmcKillProbabilityForScavGain: number; /** On death should items in your secure keep their Find in raid status regardless of how you finished the raid */ - keepFiRSecureContainerOnDeath: boolean + keepFiRSecureContainerOnDeath: boolean; /** Percentage chance a player scav hot is hostile to the player when scavving */ - playerScavHostileChancePercent: number + playerScavHostileChancePercent: number; } -export interface RaidMenuSettings -{ - aiAmount: string - aiDifficulty: string - bossEnabled: boolean - scavWars: boolean - taggedAndCursed: boolean - enablePve: boolean - randomWeather: boolean - randomTime: boolean +export interface RaidMenuSettings { + aiAmount: string; + aiDifficulty: string; + bossEnabled: boolean; + scavWars: boolean; + taggedAndCursed: boolean; + enablePve: boolean; + randomWeather: boolean; + randomTime: boolean; } -export interface Save -{ +export interface Save { /** Should loot gained from raid be saved */ - loot: boolean + loot: boolean; } diff --git a/project/src/models/spt/config/IInsuranceConfig.ts b/project/src/models/spt/config/IInsuranceConfig.ts index a6259ecf..a5ed5768 100644 --- a/project/src/models/spt/config/IInsuranceConfig.ts +++ b/project/src/models/spt/config/IInsuranceConfig.ts @@ -1,20 +1,19 @@ import { IBaseConfig } from "@spt/models/spt/config/IBaseConfig"; -export interface IInsuranceConfig extends IBaseConfig -{ - kind: "spt-insurance" +export interface IInsuranceConfig extends IBaseConfig { + kind: "spt-insurance"; /** Chance item is returned as insurance, keyed by trader id */ - returnChancePercent: Record + returnChancePercent: Record; /** Item slots that should never be returned as insurance */ - blacklistedEquipment: string[] + blacklistedEquipment: string[]; /** Some slots should always be removed, e.g. 'cartridges' */ - slotIdsToAlwaysRemove: string[] + slotIdsToAlwaysRemove: string[]; /** Override to control how quickly insurance is processed/returned in second */ - returnTimeOverrideSeconds: number + returnTimeOverrideSeconds: number; /** How often server should process insurance in seconds */ - runIntervalSeconds: number + runIntervalSeconds: number; // Lowest rouble price for an attachment to be allowed to be taken - minAttachmentRoublePriceToBeTaken: number + minAttachmentRoublePriceToBeTaken: number; // Chance out of 100% no attachments from a parent are taken - chanceNoAttachmentsTakenPercent: number + chanceNoAttachmentsTakenPercent: number; } diff --git a/project/src/models/spt/config/IInventoryConfig.ts b/project/src/models/spt/config/IInventoryConfig.ts index bb0977a6..8e763f9f 100644 --- a/project/src/models/spt/config/IInventoryConfig.ts +++ b/project/src/models/spt/config/IInventoryConfig.ts @@ -1,35 +1,32 @@ import { MinMax } from "@spt/models/common/MinMax"; import { IBaseConfig } from "@spt/models/spt/config/IBaseConfig"; -export interface IInventoryConfig extends IBaseConfig -{ - kind: "spt-inventory" +export interface IInventoryConfig extends IBaseConfig { + kind: "spt-inventory"; /** Should new items purchased by flagged as found in raid */ - newItemsMarkedFound: boolean - randomLootContainers: Record - sealedAirdropContainer: ISealedAirdropContainerSettings + newItemsMarkedFound: boolean; + randomLootContainers: Record; + sealedAirdropContainer: ISealedAirdropContainerSettings; /** Contains item tpls that the server should consider money and treat the same as roubles/euros/dollars */ - customMoneyTpls: string[] + customMoneyTpls: string[]; /** Multipliers for skill gain when inside menus, NOT in-game */ - skillGainMultiplers: Record + skillGainMultiplers: Record; } -export interface RewardDetails -{ - rewardCount: number - foundInRaid: boolean - rewardTplPool?: Record - rewardTypePool?: Record +export interface RewardDetails { + rewardCount: number; + foundInRaid: boolean; + rewardTplPool?: Record; + rewardTypePool?: Record; } -export interface ISealedAirdropContainerSettings -{ - weaponRewardWeight: Record - defaultPresetsOnly: boolean +export interface ISealedAirdropContainerSettings { + weaponRewardWeight: Record; + defaultPresetsOnly: boolean; /** Should contents be flagged as found in raid when opened */ - foundInRaid: boolean - weaponModRewardLimits: Record - rewardTypeLimits: Record - ammoBoxWhitelist: string[] - allowBossItems: boolean + foundInRaid: boolean; + weaponModRewardLimits: Record; + rewardTypeLimits: Record; + ammoBoxWhitelist: string[]; + allowBossItems: boolean; } diff --git a/project/src/models/spt/config/IItemConfig.ts b/project/src/models/spt/config/IItemConfig.ts index 5c78e889..cf3b38eb 100644 --- a/project/src/models/spt/config/IItemConfig.ts +++ b/project/src/models/spt/config/IItemConfig.ts @@ -1,15 +1,14 @@ import { IBaseConfig } from "@spt/models/spt/config/IBaseConfig"; -export interface IItemConfig extends IBaseConfig -{ - kind: "spt-item" +export interface IItemConfig extends IBaseConfig { + kind: "spt-item"; /** Items that should be globally blacklisted */ - blacklist: string[] + blacklist: string[]; /** Items that should not be lootable from any location */ - lootableItemBlacklist: string[] + lootableItemBlacklist: string[]; /** items that should not be given as rewards */ - rewardItemBlacklist: string[] + rewardItemBlacklist: string[]; /** Items that can only be found on bosses */ - bossItems: string[] - handbookPriceOverride: Record + bossItems: string[]; + handbookPriceOverride: Record; } diff --git a/project/src/models/spt/config/ILocaleConfig.ts b/project/src/models/spt/config/ILocaleConfig.ts index 1df8428b..f775b928 100644 --- a/project/src/models/spt/config/ILocaleConfig.ts +++ b/project/src/models/spt/config/ILocaleConfig.ts @@ -1,13 +1,12 @@ import { IBaseConfig } from "@spt/models/spt/config/IBaseConfig"; -export interface ILocaleConfig extends IBaseConfig -{ - kind: "spt-locale" +export interface ILocaleConfig extends IBaseConfig { + kind: "spt-locale"; /** e.g. ru/en/cn/fr etc, or 'system', will take computer locale setting */ - gameLocale: string + gameLocale: string; /** e.g. ru/en/cn/fr etc, or 'system', will take computer locale setting */ - serverLocale: string + serverLocale: string; /** Languages server can be translated into */ - serverSupportedLocales: string[] - fallbacks: { [locale: string]: string } + serverSupportedLocales: string[]; + fallbacks: { [locale: string]: string }; } diff --git a/project/src/models/spt/config/ILocationConfig.ts b/project/src/models/spt/config/ILocationConfig.ts index 86a8a066..d6ec94e1 100644 --- a/project/src/models/spt/config/ILocationConfig.ts +++ b/project/src/models/spt/config/ILocationConfig.ts @@ -2,145 +2,133 @@ import { MinMax } from "@spt/models/common/MinMax"; import { BossLocationSpawn, Wave } from "@spt/models/eft/common/ILocationBase"; import { IBaseConfig } from "@spt/models/spt/config/IBaseConfig"; -export interface ILocationConfig extends IBaseConfig -{ - kind: "spt-location" +export interface ILocationConfig extends IBaseConfig { + kind: "spt-location"; /** Waves with a min/max of the same value don't spawn any bots, bsg only spawn the difference between min and max */ - fixEmptyBotWavesSettings: IFixEmptyBotWavesSettings + fixEmptyBotWavesSettings: IFixEmptyBotWavesSettings; /** Rogues are classified as bosses and spawn immediatly, this can result in no scavs spawning, delay rogues spawning to allow scavs to spawn first */ - rogueLighthouseSpawnTimeSettings: IRogueLighthouseSpawnTimeSettings + rogueLighthouseSpawnTimeSettings: IRogueLighthouseSpawnTimeSettings; /** When a map has hit max alive bots, any wave that should spawn will be reduced to 1 bot in size and placed in a spawn queue, this splits waves into smaller sizes to reduce the impact of this behaviour */ - splitWaveIntoSingleSpawnsSettings: ISplitWaveSettings - looseLootMultiplier: LootMultiplier - staticLootMultiplier: LootMultiplier + splitWaveIntoSingleSpawnsSettings: ISplitWaveSettings; + looseLootMultiplier: LootMultiplier; + staticLootMultiplier: LootMultiplier; /** Custom bot waves to add to a locations base json on game start if addCustomBotWavesToMaps is true */ - customWaves: CustomWaves + customWaves: CustomWaves; /** Open zones to add to map */ - openZones: Record + openZones: Record; /** Key = map id, value = item tpls that should only have one forced loot spawn position */ - forcedLootSingleSpawnById: Record + forcedLootSingleSpawnById: Record; /** How many attempts should be taken to fit an item into a container before giving up */ - fitLootIntoContainerAttempts: number + fitLootIntoContainerAttempts: number; /** Add all possible zones to each maps `OpenZones` property */ - addOpenZonesToAllMaps: boolean + addOpenZonesToAllMaps: boolean; /** Allow addition of custom bot waves designed by SPT to be added to maps - defined in configs/location.json.customWaves */ - addCustomBotWavesToMaps: boolean + addCustomBotWavesToMaps: boolean; /** Should the limits defined inside botTypeLimits to appled to locations on game start */ - enableBotTypeLimits: boolean + enableBotTypeLimits: boolean; /** Add limits to a locations base.MinMaxBots array if enableBotTypeLimits is true */ - botTypeLimits: Record + botTypeLimits: Record; /** container randomisation settings */ - containerRandomisationSettings: IContainerRandomistionSettings + containerRandomisationSettings: IContainerRandomistionSettings; /** How full must a random loose magazine be % */ - minFillLooseMagazinePercent: number + minFillLooseMagazinePercent: number; /** How full must a random static magazine be % */ - minFillStaticMagazinePercent: number - allowDuplicateItemsInStaticContainers: boolean + minFillStaticMagazinePercent: number; + allowDuplicateItemsInStaticContainers: boolean; /** Chance loose magazines have ammo in them TODO - rename to dynamicMagazineLootHasAmmoChancePercent */ - magazineLootHasAmmoChancePercent: number + magazineLootHasAmmoChancePercent: number; /** Chance static magazines have ammo in them */ - staticMagazineLootHasAmmoChancePercent: number + staticMagazineLootHasAmmoChancePercent: number; /** Key: map, value: loose loot ids to ignore */ - looseLootBlacklist: Record + looseLootBlacklist: Record; /** Key: map, value: settings to control how long scav raids are */ - scavRaidTimeSettings: IScavRaidTimeSettings + scavRaidTimeSettings: IScavRaidTimeSettings; /** Settings to adjust mods for lootable equipment in raid */ - equipmentLootSettings: IEquipmentLootSettings + equipmentLootSettings: IEquipmentLootSettings; } -export interface IEquipmentLootSettings -{ +export interface IEquipmentLootSettings { // Percentage chance item will be added to equipment - modSpawnChancePercent: Record + modSpawnChancePercent: Record; } -export interface IFixEmptyBotWavesSettings -{ - enabled: boolean - ignoreMaps: string[] +export interface IFixEmptyBotWavesSettings { + enabled: boolean; + ignoreMaps: string[]; } -export interface IRogueLighthouseSpawnTimeSettings -{ - enabled: boolean - waitTimeSeconds: number +export interface IRogueLighthouseSpawnTimeSettings { + enabled: boolean; + waitTimeSeconds: number; } -export interface ISplitWaveSettings -{ - enabled: boolean - ignoreMaps: string[] - waveSizeThreshold: number +export interface ISplitWaveSettings { + enabled: boolean; + ignoreMaps: string[]; + waveSizeThreshold: number; } -export interface CustomWaves -{ +export interface CustomWaves { /** Bosses spawn on raid start */ - boss: Record - normal: Record + boss: Record; + normal: Record; } -export interface IBotTypeLimit extends MinMax -{ - type: string +export interface IBotTypeLimit extends MinMax { + type: string; } /** Multiplier to apply to the loot count for a given map */ -export interface LootMultiplier -{ - bigmap: number - develop: number - factory4_day: number - factory4_night: number - interchange: number - laboratory: number - rezervbase: number - shoreline: number - woods: number - hideout: number - lighthouse: number - privatearea: number - suburbs: number - tarkovstreets: number - terminal: number - town: number - sandbox: number +export interface LootMultiplier { + bigmap: number; + develop: number; + factory4_day: number; + factory4_night: number; + interchange: number; + laboratory: number; + rezervbase: number; + shoreline: number; + woods: number; + hideout: number; + lighthouse: number; + privatearea: number; + suburbs: number; + tarkovstreets: number; + terminal: number; + town: number; + sandbox: number; } -export interface IContainerRandomistionSettings -{ - enabled: boolean +export interface IContainerRandomistionSettings { + enabled: boolean; /** What maps can use the container randomisation feature */ - maps: Record + maps: Record; /** Some container types don't work when randomised */ - containerTypesToNotRandomise: string[] - containerGroupMinSizeMultiplier: number - containerGroupMaxSizeMultiplier: number + containerTypesToNotRandomise: string[]; + containerGroupMinSizeMultiplier: number; + containerGroupMaxSizeMultiplier: number; } -export interface IScavRaidTimeSettings -{ - settings: IScavRaidTimeConfigSettings - maps: Record +export interface IScavRaidTimeSettings { + settings: IScavRaidTimeConfigSettings; + maps: Record; } -export interface IScavRaidTimeConfigSettings -{ - trainArrivalDelayObservedSeconds: number +export interface IScavRaidTimeConfigSettings { + trainArrivalDelayObservedSeconds: number; } -export interface IScavRaidTimeLocationSettings -{ +export interface IScavRaidTimeLocationSettings { /** Should loot be reduced by same percent length of raid is reduced by */ - reduceLootByPercent: boolean + reduceLootByPercent: boolean; /** Smallest % of container loot that should be spawned */ - minStaticLootPercent: number + minStaticLootPercent: number; /** Smallest % of loose loot that should be spawned */ - minDynamicLootPercent: number + minDynamicLootPercent: number; /** Chance raid time is reduced */ - reducedChancePercent: number + reducedChancePercent: number; /** How much should raid time be reduced - weighted */ - reductionPercentWeights: Record + reductionPercentWeights: Record; /** Should bot waves be removed / spawn times be adjusted */ - adjustWaves: boolean + adjustWaves: boolean; } diff --git a/project/src/models/spt/config/ILootConfig.ts b/project/src/models/spt/config/ILootConfig.ts index 815aca99..bfe8f53e 100644 --- a/project/src/models/spt/config/ILootConfig.ts +++ b/project/src/models/spt/config/ILootConfig.ts @@ -1,11 +1,10 @@ import { Spawnpoint } from "@spt/models/eft/common/ILooseLoot"; import { IBaseConfig } from "@spt/models/spt/config/IBaseConfig"; -export interface ILootConfig extends IBaseConfig -{ - kind: "spt-loot" +export interface ILootConfig extends IBaseConfig { + kind: "spt-loot"; /** Spawn positions to add into a map, key=mapid */ - looseLoot: Record + looseLoot: Record; /** Loose loot probability adjustments to apply on game start */ - looseLootSpawnPointAdjustments: Record> + looseLootSpawnPointAdjustments: Record>; } diff --git a/project/src/models/spt/config/ILostOnDeathConfig.ts b/project/src/models/spt/config/ILostOnDeathConfig.ts index ec950273..ff74e03c 100644 --- a/project/src/models/spt/config/ILostOnDeathConfig.ts +++ b/project/src/models/spt/config/ILostOnDeathConfig.ts @@ -1,29 +1,27 @@ import { IBaseConfig } from "@spt/models/spt/config/IBaseConfig"; -export interface ILostOnDeathConfig extends IBaseConfig -{ - kind: "spt-lostondeath" +export interface ILostOnDeathConfig extends IBaseConfig { + kind: "spt-lostondeath"; /** What equipment in each slot should be lost on death */ - equipment: Equipment + equipment: Equipment; /** Should special slot items be removed from quest inventory on death e.g. wifi camera/markers */ - specialSlotItems: boolean + specialSlotItems: boolean; /** Should quest items be removed from quest inventory on death */ - questItems: boolean + questItems: boolean; } -export interface Equipment -{ - ArmBand: boolean - Headwear: boolean - Earpiece: boolean - FaceCover: boolean - ArmorVest: boolean - Eyewear: boolean - TacticalVest: boolean - PocketItems: boolean - Backpack: boolean - Holster: boolean - FirstPrimaryWeapon: boolean - SecondPrimaryWeapon: boolean - Scabbard: boolean +export interface Equipment { + ArmBand: boolean; + Headwear: boolean; + Earpiece: boolean; + FaceCover: boolean; + ArmorVest: boolean; + Eyewear: boolean; + TacticalVest: boolean; + PocketItems: boolean; + Backpack: boolean; + Holster: boolean; + FirstPrimaryWeapon: boolean; + SecondPrimaryWeapon: boolean; + Scabbard: boolean; } diff --git a/project/src/models/spt/config/IMatchConfig.ts b/project/src/models/spt/config/IMatchConfig.ts index 46a04763..b0926beb 100644 --- a/project/src/models/spt/config/IMatchConfig.ts +++ b/project/src/models/spt/config/IMatchConfig.ts @@ -1,7 +1,6 @@ import { IBaseConfig } from "@spt/models/spt/config/IBaseConfig"; -export interface IMatchConfig extends IBaseConfig -{ - kind: "spt-match" - enabled: boolean +export interface IMatchConfig extends IBaseConfig { + kind: "spt-match"; + enabled: boolean; } diff --git a/project/src/models/spt/config/IPlayerScavConfig.ts b/project/src/models/spt/config/IPlayerScavConfig.ts index 470d4597..21865072 100644 --- a/project/src/models/spt/config/IPlayerScavConfig.ts +++ b/project/src/models/spt/config/IPlayerScavConfig.ts @@ -1,33 +1,29 @@ import { GenerationData } from "@spt/models/eft/common/tables/IBotType"; import { IBaseConfig } from "@spt/models/spt/config/IBaseConfig"; -export interface IPlayerScavConfig extends IBaseConfig -{ - kind: "spt-playerscav" - karmaLevel: Record +export interface IPlayerScavConfig extends IBaseConfig { + kind: "spt-playerscav"; + karmaLevel: Record; } -export interface KarmaLevel -{ - botTypeForLoot: string - modifiers: Modifiers - itemLimits: ItemLimits - equipmentBlacklist: Record - lootItemsToAddChancePercent: Record +export interface KarmaLevel { + botTypeForLoot: string; + modifiers: Modifiers; + itemLimits: ItemLimits; + equipmentBlacklist: Record; + lootItemsToAddChancePercent: Record; } -export interface Modifiers -{ - equipment: Record - mod: Record +export interface Modifiers { + equipment: Record; + mod: Record; } -export interface ItemLimits -{ - healing: GenerationData - drugs: GenerationData - stims: GenerationData - looseLoot: GenerationData - magazines: GenerationData - grenades: GenerationData +export interface ItemLimits { + healing: GenerationData; + drugs: GenerationData; + stims: GenerationData; + looseLoot: GenerationData; + magazines: GenerationData; + grenades: GenerationData; } diff --git a/project/src/models/spt/config/IPmChatResponse.ts b/project/src/models/spt/config/IPmChatResponse.ts index de0f776c..11ba0b17 100644 --- a/project/src/models/spt/config/IPmChatResponse.ts +++ b/project/src/models/spt/config/IPmChatResponse.ts @@ -1,17 +1,15 @@ import { IBaseConfig } from "@spt/models/spt/config/IBaseConfig"; -export interface IPmcChatResponse extends IBaseConfig -{ - kind: "spt-pmcchatresponse" - victim: IResponseSettings - killer: IResponseSettings +export interface IPmcChatResponse extends IBaseConfig { + kind: "spt-pmcchatresponse"; + victim: IResponseSettings; + killer: IResponseSettings; } -export interface IResponseSettings -{ - responseChancePercent: number - responseTypeWeights: Record - stripCapitalisationChancePercent: number - allCapsChancePercent: number - appendBroToMessageEndChancePercent: number +export interface IResponseSettings { + responseChancePercent: number; + responseTypeWeights: Record; + stripCapitalisationChancePercent: number; + allCapsChancePercent: number; + appendBroToMessageEndChancePercent: number; } diff --git a/project/src/models/spt/config/IPmcConfig.ts b/project/src/models/spt/config/IPmcConfig.ts index 08aa17a5..a13f338e 100644 --- a/project/src/models/spt/config/IPmcConfig.ts +++ b/project/src/models/spt/config/IPmcConfig.ts @@ -2,65 +2,62 @@ import { MinMax } from "@spt/models/common/MinMax"; import { MemberCategory } from "@spt/models/enums/MemberCategory"; import { IBaseConfig } from "@spt/models/spt/config/IBaseConfig"; -export interface IPmcConfig extends IBaseConfig -{ - kind: "spt-pmc" +export interface IPmcConfig extends IBaseConfig { + kind: "spt-pmc"; /** What game version should the PMC have */ - gameVersionWeight: Record + gameVersionWeight: Record; /** What account type should the PMC have */ - accountTypeWeight: Record + accountTypeWeight: Record; /** Global whitelist/blacklist of vest loot for PMCs */ - vestLoot: SlotLootSettings + vestLoot: SlotLootSettings; /** Global whitelist/blacklist of pocket loot for PMCs */ - pocketLoot: SlotLootSettings + pocketLoot: SlotLootSettings; /** Global whitelist/blacklist of backpack loot for PMCs */ - backpackLoot: SlotLootSettings + backpackLoot: SlotLootSettings; /** Use difficulty defined in config/bot.json/difficulty instead of chosen difficulty dropdown value */ - useDifficultyOverride: boolean + useDifficultyOverride: boolean; /** Difficulty override e.g. "AsOnline/Hard" */ - difficulty: string + difficulty: string; /** Chance out of 100 to have a complete gun in backpack */ - looseWeaponInBackpackChancePercent: number + looseWeaponInBackpackChancePercent: number; /** Chance out of 100 to have an enhancement applied to PMC weapon */ - weaponHasEnhancementChancePercent: number + weaponHasEnhancementChancePercent: number; /** MinMax count of weapons to have in backpack */ - looseWeaponInBackpackLootMinMax: MinMax + looseWeaponInBackpackLootMinMax: MinMax; /** Percentage chance PMC will be USEC */ - isUsec: number + isUsec: number; /** WildSpawnType enum value USEC PMCs use */ - usecType: string + usecType: string; /** WildSpawnType enum value BEAR PMCs use */ - bearType: string - chanceSameSideIsHostilePercent: number + bearType: string; + chanceSameSideIsHostilePercent: number; /** What 'brain' does a PMC use, keyed by map and side (USEC/BEAR) key: map location, value: type for usec/bear */ - pmcType: Record>> - maxBackpackLootTotalRub: number - maxPocketLootTotalRub: number - maxVestLootTotalRub: number + pmcType: Record>>; + maxBackpackLootTotalRub: number; + maxPocketLootTotalRub: number; + maxVestLootTotalRub: number; /** Percentage chance a bot from a wave is converted into a PMC, key = bot wildspawn tpye (assault/exusec), value: min+max chance to be converted */ - convertIntoPmcChance: Record + convertIntoPmcChance: Record; /** WildSpawnType bots PMCs should see as hostile */ - enemyTypes: string[] + enemyTypes: string[]; /** How many levels above player level can a PMC be */ - botRelativeLevelDeltaMax: number + botRelativeLevelDeltaMax: number; /** How many levels below player level can a PMC be */ - botRelativeLevelDeltaMin: number + botRelativeLevelDeltaMin: number; /** Force a number of healing items into PMCs secure container to ensure they can heal */ - forceHealingItemsIntoSecure: boolean - allPMCsHavePlayerNameWithRandomPrefixChance: number - locationSpecificPmcLevelOverride: Record + forceHealingItemsIntoSecure: boolean; + allPMCsHavePlayerNameWithRandomPrefixChance: number; + locationSpecificPmcLevelOverride: Record; /** Should secure container loot from usec.json/bear.json be added to pmc bots secure */ - addSecureContainerLootFromBotConfig: boolean + addSecureContainerLootFromBotConfig: boolean; } -export interface PmcTypes -{ - usec: string - bear: string +export interface PmcTypes { + usec: string; + bear: string; } -export interface SlotLootSettings -{ - whitelist: string[] - blacklist: string[] +export interface SlotLootSettings { + whitelist: string[]; + blacklist: string[]; } diff --git a/project/src/models/spt/config/IQuestConfig.ts b/project/src/models/spt/config/IQuestConfig.ts index c2dd1d80..4ca2d9dc 100644 --- a/project/src/models/spt/config/IQuestConfig.ts +++ b/project/src/models/spt/config/IQuestConfig.ts @@ -3,183 +3,163 @@ import { ELocationName } from "@spt/models/enums/ELocationName"; import { SeasonalEventType } from "@spt/models/enums/SeasonalEventType"; import { IBaseConfig } from "@spt/models/spt/config/IBaseConfig"; -export interface IQuestConfig extends IBaseConfig -{ - kind: "spt-quest" +export interface IQuestConfig extends IBaseConfig { + kind: "spt-quest"; // Hours to get/redeem items from quest mail keyed by profile type - mailRedeemTimeHours: Record - questTemplateIds: IPlayerTypeQuestIds + mailRedeemTimeHours: Record; + questTemplateIds: IPlayerTypeQuestIds; /** Show non-seasonal quests be shown to player */ - showNonSeasonalEventQuests: boolean - eventQuests: Record - repeatableQuests: IRepeatableQuestConfig[] - locationIdMap: Record - bearOnlyQuests: string[] - usecOnlyQuests: string[] + showNonSeasonalEventQuests: boolean; + eventQuests: Record; + repeatableQuests: IRepeatableQuestConfig[]; + locationIdMap: Record; + bearOnlyQuests: string[]; + usecOnlyQuests: string[]; } -export interface IPlayerTypeQuestIds -{ - pmc: IQuestTypeIds - scav: IQuestTypeIds +export interface IPlayerTypeQuestIds { + pmc: IQuestTypeIds; + scav: IQuestTypeIds; } -export interface IQuestTypeIds -{ - Elimination: string - Completion: string - Exploration: string +export interface IQuestTypeIds { + Elimination: string; + Completion: string; + Exploration: string; } -export interface IEventQuestData -{ - name: string - season: SeasonalEventType - startTimestamp: number - endTimestamp: number - yearly: boolean +export interface IEventQuestData { + name: string; + season: SeasonalEventType; + startTimestamp: number; + endTimestamp: number; + yearly: boolean; } -export interface IRepeatableQuestConfig -{ - id: string - name: string - side: string - types: string[] - resetTime: number - numQuests: number - minPlayerLevel: number - rewardScaling: IRewardScaling - locations: Record - traderWhitelist: ITraderWhitelist[] - questConfig: IRepeatableQuestTypesConfig +export interface IRepeatableQuestConfig { + id: string; + name: string; + side: string; + types: string[]; + resetTime: number; + numQuests: number; + minPlayerLevel: number; + rewardScaling: IRewardScaling; + locations: Record; + traderWhitelist: ITraderWhitelist[]; + questConfig: IRepeatableQuestTypesConfig; /** Item base types to block when generating rewards */ - rewardBaseTypeBlacklist: string[] + rewardBaseTypeBlacklist: string[]; /** Item tplIds to ignore when generating rewards */ - rewardBlacklist: string[] - rewardAmmoStackMinSize: number - freeChangesAvailable: number - freeChanges: number + rewardBlacklist: string[]; + rewardAmmoStackMinSize: number; + freeChangesAvailable: number; + freeChanges: number; } -export interface IRewardScaling -{ - levels: number[] - experience: number[] - roubles: number[] - gpCoins: number[] - items: number[] - reputation: number[] - rewardSpread: number - skillRewardChance: number[] - skillPointReward: number[] +export interface IRewardScaling { + levels: number[]; + experience: number[]; + roubles: number[]; + gpCoins: number[]; + items: number[]; + reputation: number[]; + rewardSpread: number; + skillRewardChance: number[]; + skillPointReward: number[]; } -export interface ITraderWhitelist -{ - traderId: string - questTypes: string[] - rewardBaseWhitelist: string[] - rewardCanBeWeapon: boolean - weaponRewardChancePercent: number +export interface ITraderWhitelist { + traderId: string; + questTypes: string[]; + rewardBaseWhitelist: string[]; + rewardCanBeWeapon: boolean; + weaponRewardChancePercent: number; } -export interface IRepeatableQuestTypesConfig -{ - Exploration: IExploration - Completion: ICompletion - Pickup: IPickup - Elimination: IEliminationConfig[] +export interface IRepeatableQuestTypesConfig { + Exploration: IExploration; + Completion: ICompletion; + Pickup: IPickup; + Elimination: IEliminationConfig[]; } -export interface IExploration extends IBaseQuestConfig -{ - maxExtracts: number - maxExtractsWithSpecificExit: number - specificExits: ISpecificExits +export interface IExploration extends IBaseQuestConfig { + maxExtracts: number; + maxExtractsWithSpecificExit: number; + specificExits: ISpecificExits; } -export interface ISpecificExits -{ - probability: number - passageRequirementWhitelist: string[] +export interface ISpecificExits { + probability: number; + passageRequirementWhitelist: string[]; } -export interface ICompletion extends IBaseQuestConfig -{ - minRequestedAmount: number - maxRequestedAmount: number - uniqueItemCount: number - minRequestedBulletAmount: number - maxRequestedBulletAmount: number - useWhitelist: boolean - useBlacklist: boolean +export interface ICompletion extends IBaseQuestConfig { + minRequestedAmount: number; + maxRequestedAmount: number; + uniqueItemCount: number; + minRequestedBulletAmount: number; + maxRequestedBulletAmount: number; + useWhitelist: boolean; + useBlacklist: boolean; } -export interface IPickup extends IBaseQuestConfig -{ - ItemTypeToFetchWithMaxCount: IPickupTypeWithMaxCount[] +export interface IPickup extends IBaseQuestConfig { + ItemTypeToFetchWithMaxCount: IPickupTypeWithMaxCount[]; } -export interface IPickupTypeWithMaxCount -{ - itemType: string - maxPickupCount: number - minPickupCount: number +export interface IPickupTypeWithMaxCount { + itemType: string; + maxPickupCount: number; + minPickupCount: number; } -export interface IEliminationConfig extends IBaseQuestConfig -{ - levelRange: MinMax - targets: ITarget[] - bodyPartProb: number - bodyParts: IBodyPart[] - specificLocationProb: number - distLocationBlacklist: string[] - distProb: number - maxDist: number - minDist: number - maxKills: number - minKills: number - minBossKills: number - maxBossKills: number - minPmcKills: number - maxPmcKills: number - weaponCategoryRequirementProb: number - weaponCategoryRequirements: IWeaponRequirement[] - weaponRequirementProb: number - weaponRequirements: IWeaponRequirement[] +export interface IEliminationConfig extends IBaseQuestConfig { + levelRange: MinMax; + targets: ITarget[]; + bodyPartProb: number; + bodyParts: IBodyPart[]; + specificLocationProb: number; + distLocationBlacklist: string[]; + distProb: number; + maxDist: number; + minDist: number; + maxKills: number; + minKills: number; + minBossKills: number; + maxBossKills: number; + minPmcKills: number; + maxPmcKills: number; + weaponCategoryRequirementProb: number; + weaponCategoryRequirements: IWeaponRequirement[]; + weaponRequirementProb: number; + weaponRequirements: IWeaponRequirement[]; } -export interface IBaseQuestConfig -{ - possibleSkillRewards: string[] +export interface IBaseQuestConfig { + possibleSkillRewards: string[]; } -export interface ITarget extends IProbabilityObject -{ - data: IBossInfo +export interface ITarget extends IProbabilityObject { + data: IBossInfo; } -export interface IBossInfo -{ - isBoss: boolean - isPmc: boolean +export interface IBossInfo { + isBoss: boolean; + isPmc: boolean; } -export interface IBodyPart extends IProbabilityObject -{ - data: string[] +export interface IBodyPart extends IProbabilityObject { + data: string[]; } -export interface IWeaponRequirement extends IProbabilityObject -{ - data: string[] +export interface IWeaponRequirement extends IProbabilityObject { + data: string[]; } -export interface IProbabilityObject -{ - key: string - relativeProbability: number - data?: any +export interface IProbabilityObject { + key: string; + relativeProbability: number; + data?: any; } diff --git a/project/src/models/spt/config/IRagfairConfig.ts b/project/src/models/spt/config/IRagfairConfig.ts index fca429d7..62fc47a1 100644 --- a/project/src/models/spt/config/IRagfairConfig.ts +++ b/project/src/models/spt/config/IRagfairConfig.ts @@ -1,185 +1,172 @@ import { MinMax } from "@spt/models/common/MinMax"; import { IBaseConfig, IRunIntervalValues } from "@spt/models/spt/config/IBaseConfig"; -export interface IRagfairConfig extends IBaseConfig -{ - kind: "spt-ragfair" +export interface IRagfairConfig extends IBaseConfig { + kind: "spt-ragfair"; /** How many seconds should pass before expired offers and procesed + player offers checked if sold */ - runIntervalSeconds: number + runIntervalSeconds: number; /** Default values used to hydrate `runIntervalSeconds` with */ - runIntervalValues: IRunIntervalValues + runIntervalValues: IRunIntervalValues; /** Player listing settings */ - sell: Sell + sell: Sell; /** Trader ids + should their assorts be listed on flea */ - traders: Record - dynamic: Dynamic + traders: Record; + dynamic: Dynamic; } -export interface Sell -{ +export interface Sell { /** Should a fee be deducted from player when liting an item for sale */ - fees: boolean + fees: boolean; /** Settings to control chances of offer being sold */ - chance: Chance + chance: Chance; /** Settings to control how long it takes for a player offer to sell */ - time: MinMax + time: MinMax; /** Seconds from clicking remove to remove offer from market */ - expireSeconds: number + expireSeconds: number; } -export interface Chance -{ +export interface Chance { /** Base chance percent to sell an item */ - base: number + base: number; /** Value to multiply the sell chance by */ - sellMultiplier: number + sellMultiplier: number; /** Max possible sell chance % for a player listed offer */ - maxSellChancePercent: number + maxSellChancePercent: number; /** Min possible sell chance % for a player listed offer */ - minSellChancePercent: number + minSellChancePercent: number; } -export interface Dynamic -{ +export interface Dynamic { // Should a purchased dynamic offers items be flagged as found in raid - purchasesAreFoundInRaid: boolean + purchasesAreFoundInRaid: boolean; /** Use the highest trader price for an offer if its greater than the price in templates/prices.json */ - useTraderPriceForOffersIfHigher: boolean + useTraderPriceForOffersIfHigher: boolean; /** Barter offer specific settings */ - barter: IBarterDetails - pack: IPackDetails + barter: IBarterDetails; + pack: IPackDetails; /** Dynamic offer price below handbook adjustment values */ - offerAdjustment: OfferAdjustment + offerAdjustment: OfferAdjustment; /** How many offers should expire before an offer regeneration occurs */ - expiredOfferThreshold: number + expiredOfferThreshold: number; /** How many offers should be listed */ - offerItemCount: MinMax + offerItemCount: MinMax; /** How much should the price of an offer vary by (percent 0.8 = 80%, 1.2 = 120%) */ - priceRanges: IPriceRanges + priceRanges: IPriceRanges; /** Should default presets to listed only or should non-standard presets found in globals.json be listed too */ - showDefaultPresetsOnly: boolean - endTimeSeconds: MinMax + showDefaultPresetsOnly: boolean; + endTimeSeconds: MinMax; /** Settings to control the durability range of item items listed on flea */ - condition: Condition + condition: Condition; /** Size stackable items should be listed for in percent of max stack size */ - stackablePercent: MinMax + stackablePercent: MinMax; /** Items that cannot be stacked can have multiples sold in one offer, what range of values can be listed */ - nonStackableCount: MinMax + nonStackableCount: MinMax; /** Range of rating offers for items being listed */ - rating: MinMax + rating: MinMax; /** Armor specific flea settings */ - armor: IArmorSettings + armor: IArmorSettings; /** A multipler to apply to individual tpls price just prior to item quality adjustment */ - itemPriceMultiplier: Record + itemPriceMultiplier: Record; /** Percentages to sell offers in each currency */ - currencies: Record + currencies: Record; /** Item tpls that should be forced to sell as a single item */ - showAsSingleStack: string[] + showAsSingleStack: string[]; /** Should christmas/halloween items be removed from flea when not within the seasonal bounds */ - removeSeasonalItemsWhenNotInEvent: boolean + removeSeasonalItemsWhenNotInEvent: boolean; /** Flea blacklist settings */ - blacklist: Blacklist + blacklist: Blacklist; /** Dict of price limits keyed by item type */ - unreasonableModPrices: Record + unreasonableModPrices: Record; } -export interface IPriceRanges -{ - default: MinMax - preset: MinMax - pack: MinMax +export interface IPriceRanges { + default: MinMax; + preset: MinMax; + pack: MinMax; } -export interface IBarterDetails -{ +export interface IBarterDetails { /** Percentage change an offer is listed as a barter */ - chancePercent: number + chancePercent: number; /** Min number of required items for a barter requirement */ - itemCountMin: number + itemCountMin: number; /** Max number of required items for a barter requirement */ - itemCountMax: number + itemCountMax: number; /** How much can the total price of requested items vary from the item offered */ - priceRangeVariancePercent: number + priceRangeVariancePercent: number; /** Min rouble price for an offer to be considered for turning into a barter */ - minRoubleCostToBecomeBarter: number + minRoubleCostToBecomeBarter: number; /** Item Tpls to never be turned into a barter */ - itemTypeBlacklist: string[] + itemTypeBlacklist: string[]; } -export interface IPackDetails -{ +export interface IPackDetails { /** Percentage change an offer is listed as a pack */ - chancePercent: number + chancePercent: number; /** Min number of required items for a pack */ - itemCountMin: number + itemCountMin: number; /** Max number of required items for a pack */ - itemCountMax: number + itemCountMax: number; /** item types to allow being a pack */ - itemTypeWhitelist: string[] + itemTypeWhitelist: string[]; } -export interface OfferAdjustment -{ +export interface OfferAdjustment { /** Shuld offer price be adjusted when below handbook price */ - adjustPriceWhenBelowHandbookPrice: boolean + adjustPriceWhenBelowHandbookPrice: boolean; /** How big a percentage difference does price need to vary from handbook to be considered for adjustment */ - maxPriceDifferenceBelowHandbookPercent: number + maxPriceDifferenceBelowHandbookPercent: number; /** How much to multiply the handbook price to get the new price */ - handbookPriceMultipier: number + handbookPriceMultipier: number; /** What is the minimum rouble price to consider adjusting price of item */ - priceThreshholdRub: number + priceThreshholdRub: number; } -export interface Condition -{ +export interface Condition { /** Percentage change durability is altered */ - conditionChance: number - current: MinMax - max: MinMax + conditionChance: number; + current: MinMax; + max: MinMax; } -export interface Blacklist -{ +export interface Blacklist { /** Damaged ammo packs */ - damagedAmmoPacks: boolean + damagedAmmoPacks: boolean; /** Custom blacklist for item Tpls */ - custom: string[] + custom: string[]; /** BSG blacklist a large number of items from flea, true = use blacklist */ - enableBsgList: boolean + enableBsgList: boolean; /** Should quest items be blacklisted from flea */ - enableQuestList: boolean + enableQuestList: boolean; /** Should trader items that are blacklisted by bsg be listed on flea */ - traderItems: boolean + traderItems: boolean; /** Maximum level an armor plate can be found in a flea-listed armor item */ - armorPlate: IArmorPlateBlacklistSettings + armorPlate: IArmorPlateBlacklistSettings; /** Should specific categories be blacklisted from the flea, true = use blacklist */ - enableCustomItemCategoryList: boolean + enableCustomItemCategoryList: boolean; /** Custom category blacklist for parent Ids */ - customItemCategoryList: string[] + customItemCategoryList: string[]; } -export interface IArmorPlateBlacklistSettings -{ +export interface IArmorPlateBlacklistSettings { /** Max level of plates an armor can have without being removed */ - maxProtectionLevel: number + maxProtectionLevel: number; /** Item slots to NOT remove from items on flea */ - ignoreSlots: string[] + ignoreSlots: string[]; } -export interface IUnreasonableModPrices -{ +export interface IUnreasonableModPrices { /** Enable a system that adjusts very high ragfair prices to be below a max multiple of items the handbook values */ - enabled: boolean + enabled: boolean; /** Multipler to start adjusting item values from, e.g. a value of 10 means any value over 10x the handbook price gets adjusted */ - handbookPriceOverMultiplier: number + handbookPriceOverMultiplier: number; /** The new multiplier for items found using above property, e.g. a value of 4 means set items price to 4x handbook price */ - newPriceHandbookMultiplier: number + newPriceHandbookMultiplier: number; } -export interface IArmorSettings -{ +export interface IArmorSettings { /** % chance / 100 that armor plates will be removed from an offer before listing */ - removeRemovablePlateChance: number + removeRemovablePlateChance: number; /** What slots are to be removed when removeRemovablePlateChance is true */ - plateSlotIdToRemovePool: string[] + plateSlotIdToRemovePool: string[]; } diff --git a/project/src/models/spt/config/IRepairConfig.ts b/project/src/models/spt/config/IRepairConfig.ts index 64496f27..c8690d8d 100644 --- a/project/src/models/spt/config/IRepairConfig.ts +++ b/project/src/models/spt/config/IRepairConfig.ts @@ -1,62 +1,55 @@ import { MinMax } from "@spt/models/common/MinMax"; import { IBaseConfig } from "@spt/models/spt/config/IBaseConfig"; -export interface IRepairConfig extends IBaseConfig -{ - kind: "spt-repair" - priceMultiplier: number - applyRandomizeDurabilityLoss: boolean - weaponSkillRepairGain: number - armorKitSkillPointGainPerRepairPointMultiplier: number +export interface IRepairConfig extends IBaseConfig { + kind: "spt-repair"; + priceMultiplier: number; + applyRandomizeDurabilityLoss: boolean; + weaponSkillRepairGain: number; + armorKitSkillPointGainPerRepairPointMultiplier: number; /** INT gain multiplier per repaired item type */ - repairKitIntellectGainMultiplier: IIntellectGainValues + repairKitIntellectGainMultiplier: IIntellectGainValues; // ** How much INT can be given to player per repair action */ - maxIntellectGainPerRepair: IMaxIntellectGainValues - weaponTreatment: IWeaponTreatmentRepairValues - repairKit: RepairKit + maxIntellectGainPerRepair: IMaxIntellectGainValues; + weaponTreatment: IWeaponTreatmentRepairValues; + repairKit: RepairKit; } -export interface IIntellectGainValues -{ - weapon: number - armor: number +export interface IIntellectGainValues { + weapon: number; + armor: number; } -export interface IMaxIntellectGainValues -{ - kit: number - trader: number +export interface IMaxIntellectGainValues { + kit: number; + trader: number; } -export interface IWeaponTreatmentRepairValues -{ +export interface IWeaponTreatmentRepairValues { /** The chance to gain more weapon maintenance skill */ - critSuccessChance: number - critSuccessAmount: number + critSuccessChance: number; + critSuccessAmount: number; /** The chance to gain less weapon maintenance skill */ - critFailureChance: number - critFailureAmount: number + critFailureChance: number; + critFailureAmount: number; /** The multiplier used for calculating weapon maintenance XP */ - pointGainMultiplier: number + pointGainMultiplier: number; } -export interface RepairKit -{ - armor: BonusSettings - weapon: BonusSettings +export interface RepairKit { + armor: BonusSettings; + weapon: BonusSettings; } -export interface BonusSettings -{ - rarityWeight: Record - bonusTypeWeight: Record - common: Record - rare: Record +export interface BonusSettings { + rarityWeight: Record; + bonusTypeWeight: Record; + common: Record; + rare: Record; } -export interface BonusValues -{ - valuesMinMax: MinMax +export interface BonusValues { + valuesMinMax: MinMax; /** What dura is buff active between (min max of current max) */ - activeDurabilityPercentMinMax: MinMax + activeDurabilityPercentMinMax: MinMax; } diff --git a/project/src/models/spt/config/IScavCaseConfig.ts b/project/src/models/spt/config/IScavCaseConfig.ts index 0eae0e4b..ad8430a1 100644 --- a/project/src/models/spt/config/IScavCaseConfig.ts +++ b/project/src/models/spt/config/IScavCaseConfig.ts @@ -1,39 +1,35 @@ import { MinMax } from "@spt/models/common/MinMax"; import { IBaseConfig } from "@spt/models/spt/config/IBaseConfig"; -export interface IScavCaseConfig extends IBaseConfig -{ - kind: "spt-scavcase" - rewardItemValueRangeRub: Record - moneyRewards: MoneyRewards - ammoRewards: AmmoRewards - rewardItemParentBlacklist: string[] - rewardItemBlacklist: string[] - allowMultipleMoneyRewardsPerRarity: boolean - allowMultipleAmmoRewardsPerRarity: boolean - allowBossItemsAsRewards: boolean +export interface IScavCaseConfig extends IBaseConfig { + kind: "spt-scavcase"; + rewardItemValueRangeRub: Record; + moneyRewards: MoneyRewards; + ammoRewards: AmmoRewards; + rewardItemParentBlacklist: string[]; + rewardItemBlacklist: string[]; + allowMultipleMoneyRewardsPerRarity: boolean; + allowMultipleAmmoRewardsPerRarity: boolean; + allowBossItemsAsRewards: boolean; } -export interface MoneyRewards -{ - moneyRewardChancePercent: number - rubCount: MoneyLevels - usdCount: MoneyLevels - eurCount: MoneyLevels - gpCount: MoneyLevels +export interface MoneyRewards { + moneyRewardChancePercent: number; + rubCount: MoneyLevels; + usdCount: MoneyLevels; + eurCount: MoneyLevels; + gpCount: MoneyLevels; } -export interface MoneyLevels -{ - common: MinMax - rare: MinMax - superrare: MinMax +export interface MoneyLevels { + common: MinMax; + rare: MinMax; + superrare: MinMax; } -export interface AmmoRewards -{ - ammoRewardChancePercent: number - ammoRewardBlacklist: Record - ammoRewardValueRangeRub: Record - minStackSize: number +export interface AmmoRewards { + ammoRewardChancePercent: number; + ammoRewardBlacklist: Record; + ammoRewardValueRangeRub: Record; + minStackSize: number; } diff --git a/project/src/models/spt/config/ISeasonalEventConfig.ts b/project/src/models/spt/config/ISeasonalEventConfig.ts index 7172aeb7..c20e7ee8 100644 --- a/project/src/models/spt/config/ISeasonalEventConfig.ts +++ b/project/src/models/spt/config/ISeasonalEventConfig.ts @@ -2,31 +2,28 @@ import { BossLocationSpawn } from "@spt/models/eft/common/ILocationBase"; import { SeasonalEventType } from "@spt/models/enums/SeasonalEventType"; import { IBaseConfig } from "@spt/models/spt/config/IBaseConfig"; -export interface ISeasonalEventConfig extends IBaseConfig -{ - kind: "spt-seasonalevents" - enableSeasonalEventDetection: boolean +export interface ISeasonalEventConfig extends IBaseConfig { + kind: "spt-seasonalevents"; + enableSeasonalEventDetection: boolean; /** event / botType / equipSlot / itemid */ - eventGear: Record>>> - events: ISeasonalEvent[] - eventBotMapping: Record - eventBossSpawns: Record> - gifterSettings: GifterSetting[] + eventGear: Record>>>; + events: ISeasonalEvent[]; + eventBotMapping: Record; + eventBossSpawns: Record>; + gifterSettings: GifterSetting[]; } -export interface ISeasonalEvent -{ - name: string - type: SeasonalEventType - startDay: number - startMonth: number - endDay: number - endMonth: number +export interface ISeasonalEvent { + name: string; + type: SeasonalEventType; + startDay: number; + startMonth: number; + endDay: number; + endMonth: number; } -export interface GifterSetting -{ - map: string - zones: string - spawnChance: number +export interface GifterSetting { + map: string; + zones: string; + spawnChance: number; } diff --git a/project/src/models/spt/config/ITraderConfig.ts b/project/src/models/spt/config/ITraderConfig.ts index 8409ac58..02de25e5 100644 --- a/project/src/models/spt/config/ITraderConfig.ts +++ b/project/src/models/spt/config/ITraderConfig.ts @@ -2,76 +2,70 @@ import { MinMax } from "@spt/models/common/MinMax"; import { IBaseConfig } from "@spt/models/spt/config/IBaseConfig"; import { LootRequest } from "@spt/models/spt/services/LootRequest"; -export interface ITraderConfig extends IBaseConfig -{ - kind: "spt-trader" - updateTime: UpdateTime[] - purchasesAreFoundInRaid: boolean +export interface ITraderConfig extends IBaseConfig { + kind: "spt-trader"; + updateTime: UpdateTime[]; + purchasesAreFoundInRaid: boolean; /** Should trader reset times be set based on server start time (false = bsg time - on the hour) */ - tradersResetFromServerStart: boolean - updateTimeDefault: number - traderPriceMultipler: number - fence: FenceConfig + tradersResetFromServerStart: boolean; + updateTimeDefault: number; + traderPriceMultipler: number; + fence: FenceConfig; } -export interface UpdateTime -{ - traderId: string +export interface UpdateTime { + traderId: string; /** Seconds between trader resets */ - seconds: MinMax + seconds: MinMax; } -export interface FenceConfig -{ - discountOptions: DiscountOptions - partialRefreshTimeSeconds: number - partialRefreshChangePercent: number - assortSize: number - weaponPresetMinMax: MinMax - equipmentPresetMinMax: MinMax - itemPriceMult: number - presetPriceMult: number - armorMaxDurabilityPercentMinMax: IItemDurabilityCurrentMax - weaponDurabilityPercentMinMax: IItemDurabilityCurrentMax +export interface FenceConfig { + discountOptions: DiscountOptions; + partialRefreshTimeSeconds: number; + partialRefreshChangePercent: number; + assortSize: number; + weaponPresetMinMax: MinMax; + equipmentPresetMinMax: MinMax; + itemPriceMult: number; + presetPriceMult: number; + armorMaxDurabilityPercentMinMax: IItemDurabilityCurrentMax; + weaponDurabilityPercentMinMax: IItemDurabilityCurrentMax; /** Keyed to plate protection level */ - chancePlateExistsInArmorPercent: Record + chancePlateExistsInArmorPercent: Record; /** Key: item tpl */ - itemStackSizeOverrideMinMax: Record - itemTypeLimits: Record + itemStackSizeOverrideMinMax: Record; + itemTypeLimits: Record; /** Prevent duplicate offers of items of specific categories by parentId */ - preventDuplicateOffersOfCategory: string[] - regenerateAssortsOnRefresh: boolean + preventDuplicateOffersOfCategory: string[]; + regenerateAssortsOnRefresh: boolean; /** Max rouble price before item is not listed on flea */ - itemCategoryRoublePriceLimit: Record + itemCategoryRoublePriceLimit: Record; /** Each slotid with % to be removed prior to listing on fence */ - presetSlotsToRemoveChancePercent: Record + presetSlotsToRemoveChancePercent: Record; /** Block seasonal items from appearing when season is inactive */ - blacklistSeasonalItems: boolean + blacklistSeasonalItems: boolean; /** Max pen value allowed to be listed on flea - affects ammo + ammo boxes */ - ammoMaxPenLimit: number - blacklist: string[] - coopExtractGift: CoopExtractReward - btrDeliveryExpireHours: number + ammoMaxPenLimit: number; + blacklist: string[]; + coopExtractGift: CoopExtractReward; + btrDeliveryExpireHours: number; } -export interface IItemDurabilityCurrentMax -{ - current: MinMax - max: MinMax +export interface IItemDurabilityCurrentMax { + current: MinMax; + max: MinMax; } -export interface CoopExtractReward extends LootRequest -{ - sendGift: boolean - messageLocaleIds: string[] - giftExpiryHours: number +export interface CoopExtractReward extends LootRequest { + sendGift: boolean; + messageLocaleIds: string[]; + giftExpiryHours: number; } -export interface DiscountOptions -{ - assortSize: number - itemPriceMult: number - presetPriceMult: number - weaponPresetMinMax: MinMax - equipmentPresetMinMax: MinMax +export interface DiscountOptions { + assortSize: number; + itemPriceMult: number; + presetPriceMult: number; + weaponPresetMinMax: MinMax; + equipmentPresetMinMax: MinMax; } diff --git a/project/src/models/spt/config/IWeatherConfig.ts b/project/src/models/spt/config/IWeatherConfig.ts index c1808f86..2a4513e2 100644 --- a/project/src/models/spt/config/IWeatherConfig.ts +++ b/project/src/models/spt/config/IWeatherConfig.ts @@ -3,40 +3,36 @@ import { Season } from "@spt/models/enums/Season"; import { WindDirection } from "@spt/models/enums/WindDirection"; import { IBaseConfig } from "@spt/models/spt/config/IBaseConfig"; -export interface IWeatherConfig extends IBaseConfig -{ - kind: "spt-weather" - acceleration: number - weather: Weather - seasonDates: ISeasonDateTimes[] - overrideSeason?: Season +export interface IWeatherConfig extends IBaseConfig { + kind: "spt-weather"; + acceleration: number; + weather: Weather; + seasonDates: ISeasonDateTimes[]; + overrideSeason?: Season; } -export interface ISeasonDateTimes -{ - seasonType: Season - name: string - startDay: number - startMonth: number - endDay: number - endMonth: number +export interface ISeasonDateTimes { + seasonType: Season; + name: string; + startDay: number; + startMonth: number; + endDay: number; + endMonth: number; } -export interface Weather -{ - clouds: WeatherSettings - windSpeed: WeatherSettings - windDirection: WeatherSettings - windGustiness: MinMax - rain: WeatherSettings - rainIntensity: MinMax - fog: WeatherSettings - temp: MinMax - pressure: MinMax +export interface Weather { + clouds: WeatherSettings; + windSpeed: WeatherSettings; + windDirection: WeatherSettings; + windGustiness: MinMax; + rain: WeatherSettings; + rainIntensity: MinMax; + fog: WeatherSettings; + temp: MinMax; + pressure: MinMax; } -export interface WeatherSettings -{ - values: T[] - weights: number[] +export interface WeatherSettings { + values: T[]; + weights: number[]; } diff --git a/project/src/models/spt/controllers/IBotController.ts b/project/src/models/spt/controllers/IBotController.ts index 9bed3e55..f18d02d8 100644 --- a/project/src/models/spt/controllers/IBotController.ts +++ b/project/src/models/spt/controllers/IBotController.ts @@ -3,13 +3,12 @@ import { IBotBase } from "@spt/models/eft/common/tables/IBotBase"; import { IBotCore } from "@spt/models/eft/common/tables/IBotCore"; import { Difficulty } from "@spt/models/eft/common/tables/IBotType"; -export interface IBotController -{ - getBotLimit(type: string): number - getBotDifficulty(type: string, difficulty: string): IBotCore | Difficulty - isBotPmc(botRole: string): boolean - isBotBoss(botRole: string): boolean - isBotFollower(botRole: string): boolean - generate(info: IGenerateBotsRequestData, playerScav: boolean): IBotBase[] - getBotCap(): number +export interface IBotController { + getBotLimit(type: string): number; + getBotDifficulty(type: string, difficulty: string): IBotCore | Difficulty; + isBotPmc(botRole: string): boolean; + isBotBoss(botRole: string): boolean; + isBotFollower(botRole: string): boolean; + generate(info: IGenerateBotsRequestData, playerScav: boolean): IBotBase[]; + getBotCap(): number; } diff --git a/project/src/models/spt/dialog/ISendMessageDetails.ts b/project/src/models/spt/dialog/ISendMessageDetails.ts index 96d460db..4223d7c9 100644 --- a/project/src/models/spt/dialog/ISendMessageDetails.ts +++ b/project/src/models/spt/dialog/ISendMessageDetails.ts @@ -3,44 +3,41 @@ import { ISystemData, IUserDialogInfo, MessageContentRagfair } from "@spt/models import { MessageType } from "@spt/models/enums/MessageType"; import { Traders } from "@spt/models/enums/Traders"; -export interface ISendMessageDetails -{ +export interface ISendMessageDetails { /** Player id */ - recipientId: string + recipientId: string; /** Who is sending this message */ - sender: MessageType + sender: MessageType; /** Optional - leave blank to use sender value */ - dialogType?: MessageType + dialogType?: MessageType; /** Optional - if sender is USER these details are used */ - senderDetails?: IUserDialogInfo + senderDetails?: IUserDialogInfo; /** Optional - the trader sending the message */ - trader?: Traders + trader?: Traders; /** Optional - used in player/system messages, otherwise templateId is used */ - messageText?: string + messageText?: string; /** Optinal - Items to send to player */ - items?: Item[] + items?: Item[]; /** Optional - How long items will be stored in mail before expiry */ - itemsMaxStorageLifetimeSeconds?: number + itemsMaxStorageLifetimeSeconds?: number; /** Optional - Used when sending messages from traders who send text from locale json */ - templateId?: string + templateId?: string; /** Optional - ragfair related */ - systemData?: ISystemData + systemData?: ISystemData; /** Optional - Used by ragfair messages */ - ragfairDetails?: MessageContentRagfair + ragfairDetails?: MessageContentRagfair; /** OPTIONAL - allows modification of profile settings via mail */ - profileChangeEvents?: IProfileChangeEvent[] + profileChangeEvents?: IProfileChangeEvent[]; } -export interface IProfileChangeEvent -{ - _id: string - Type: ProfileChangeEventType - value: number - entity?: string +export interface IProfileChangeEvent { + _id: string; + Type: ProfileChangeEventType; + value: number; + entity?: string; } -export enum ProfileChangeEventType -{ +export enum ProfileChangeEventType { TRADER_SALES_SUM = "TraderSalesSum", TRADER_STANDING = "TraderStanding", PROFILE_LEVEL = "ProfileLevel", diff --git a/project/src/models/spt/fence/ICreateFenceAssortsResult.ts b/project/src/models/spt/fence/ICreateFenceAssortsResult.ts index 71c4239f..67ae328e 100644 --- a/project/src/models/spt/fence/ICreateFenceAssortsResult.ts +++ b/project/src/models/spt/fence/ICreateFenceAssortsResult.ts @@ -1,9 +1,8 @@ import { Item } from "@spt/models/eft/common/tables/IItem"; import { IBarterScheme } from "@spt/models/eft/common/tables/ITrader"; -export interface ICreateFenceAssortsResult -{ - sptItems: Item[][] - barter_scheme: Record - loyal_level_items: Record +export interface ICreateFenceAssortsResult { + sptItems: Item[][]; + barter_scheme: Record; + loyal_level_items: Record; } diff --git a/project/src/models/spt/fence/IFenceAssortGenerationValues.ts b/project/src/models/spt/fence/IFenceAssortGenerationValues.ts index cfb9474a..3e0d8306 100644 --- a/project/src/models/spt/fence/IFenceAssortGenerationValues.ts +++ b/project/src/models/spt/fence/IFenceAssortGenerationValues.ts @@ -1,12 +1,10 @@ -export interface IFenceAssortGenerationValues -{ - normal: IGenerationAssortValues - discount: IGenerationAssortValues +export interface IFenceAssortGenerationValues { + normal: IGenerationAssortValues; + discount: IGenerationAssortValues; } -export interface IGenerationAssortValues -{ - item: number - weaponPreset: number - equipmentPreset: number +export interface IGenerationAssortValues { + item: number; + weaponPreset: number; + equipmentPreset: number; } diff --git a/project/src/models/spt/generators/IBotGenerator.ts b/project/src/models/spt/generators/IBotGenerator.ts index cb61fec4..3f47e573 100644 --- a/project/src/models/spt/generators/IBotGenerator.ts +++ b/project/src/models/spt/generators/IBotGenerator.ts @@ -1,13 +1,12 @@ import { Inventory as PmcInventory } from "@spt/models/eft/common/tables/IBotBase"; import { Chances, Generation, Inventory } from "@spt/models/eft/common/tables/IBotType"; -export interface IBotGenerator -{ +export interface IBotGenerator { generateInventory( templateInventory: Inventory, equipmentChances: Chances, generation: Generation, botRole: string, isPmc: boolean, - ): PmcInventory + ): PmcInventory; } diff --git a/project/src/models/spt/generators/ILocationGenerator.ts b/project/src/models/spt/generators/ILocationGenerator.ts index 5693a54b..5e9a51dd 100644 --- a/project/src/models/spt/generators/ILocationGenerator.ts +++ b/project/src/models/spt/generators/ILocationGenerator.ts @@ -6,18 +6,17 @@ import { } from "@spt/models/eft/common/ILocation"; import { ILooseLoot, SpawnpointTemplate } from "@spt/models/eft/common/ILooseLoot"; -export interface ILocationGenerator -{ +export interface ILocationGenerator { generateContainerLoot( containerIn: IStaticContainerProps, staticForced: IStaticForcedProps[], staticLootDist: Record, staticAmmoDist: Record, locationName: string, - ): IStaticContainerProps + ): IStaticContainerProps; generateDynamicLoot( dynamicLootDist: ILooseLoot, staticAmmoDist: Record, locationName: string, - ): SpawnpointTemplate[] + ): SpawnpointTemplate[]; } diff --git a/project/src/models/spt/generators/IPMCLootGenerator.ts b/project/src/models/spt/generators/IPMCLootGenerator.ts index 60a5126d..a9db89ba 100644 --- a/project/src/models/spt/generators/IPMCLootGenerator.ts +++ b/project/src/models/spt/generators/IPMCLootGenerator.ts @@ -1,5 +1,4 @@ -export interface IPMCLootGenerator -{ - generatePMCPocketLootPool(): string[] - generatePMCBackpackLootPool(): string[] +export interface IPMCLootGenerator { + generatePMCPocketLootPool(): string[]; + generatePMCBackpackLootPool(): string[]; } diff --git a/project/src/models/spt/generators/IRagfairAssortGenerator.ts b/project/src/models/spt/generators/IRagfairAssortGenerator.ts index 99dc16ff..442fc09e 100644 --- a/project/src/models/spt/generators/IRagfairAssortGenerator.ts +++ b/project/src/models/spt/generators/IRagfairAssortGenerator.ts @@ -1,6 +1,5 @@ import { Item } from "@spt/models/eft/common/tables/IItem"; -export interface IRagfairAssortGenerator -{ - getAssortItems(): Item[] +export interface IRagfairAssortGenerator { + getAssortItems(): Item[]; } diff --git a/project/src/models/spt/generators/IRagfairOfferGenerator.ts b/project/src/models/spt/generators/IRagfairOfferGenerator.ts index 755292d2..72ea0d95 100644 --- a/project/src/models/spt/generators/IRagfairOfferGenerator.ts +++ b/project/src/models/spt/generators/IRagfairOfferGenerator.ts @@ -2,8 +2,7 @@ import { Item } from "@spt/models/eft/common/tables/IItem"; import { IBarterScheme } from "@spt/models/eft/common/tables/ITrader"; import { IRagfairOffer } from "@spt/models/eft/ragfair/IRagfairOffer"; -export interface IRagfairOfferGenerator -{ +export interface IRagfairOfferGenerator { createOffer( userID: string, time: number, @@ -12,5 +11,5 @@ export interface IRagfairOfferGenerator loyalLevel: number, price: number, sellInOnePiece: boolean, - ): IRagfairOffer + ): IRagfairOffer; } diff --git a/project/src/models/spt/hideout/IHideout.ts b/project/src/models/spt/hideout/IHideout.ts index 21e25070..94e3df22 100644 --- a/project/src/models/spt/hideout/IHideout.ts +++ b/project/src/models/spt/hideout/IHideout.ts @@ -4,11 +4,10 @@ import { IHideoutScavCase } from "@spt/models/eft/hideout/IHideoutScavCase"; import { IHideoutSettingsBase } from "@spt/models/eft/hideout/IHideoutSettingsBase"; import { IQteData } from "@spt/models/eft/hideout/IQteData"; -export interface IHideout -{ - areas: IHideoutArea[] - production: IHideoutProduction[] - scavcase: IHideoutScavCase[] - settings: IHideoutSettingsBase - qte: IQteData[] +export interface IHideout { + areas: IHideoutArea[]; + production: IHideoutProduction[]; + scavcase: IHideoutScavCase[]; + settings: IHideoutSettingsBase; + qte: IQteData[]; } diff --git a/project/src/models/spt/hideout/ScavCaseRewardCountsAndPrices.ts b/project/src/models/spt/hideout/ScavCaseRewardCountsAndPrices.ts index a8647713..830c08c0 100644 --- a/project/src/models/spt/hideout/ScavCaseRewardCountsAndPrices.ts +++ b/project/src/models/spt/hideout/ScavCaseRewardCountsAndPrices.ts @@ -1,14 +1,12 @@ -export interface ScavCaseRewardCountsAndPrices -{ - Common: RewardCountAndPriceDetails - Rare: RewardCountAndPriceDetails - Superrare: RewardCountAndPriceDetails +export interface ScavCaseRewardCountsAndPrices { + Common: RewardCountAndPriceDetails; + Rare: RewardCountAndPriceDetails; + Superrare: RewardCountAndPriceDetails; } -export interface RewardCountAndPriceDetails -{ - minCount: number - maxCount: number - minPriceRub: number - maxPriceRub: number +export interface RewardCountAndPriceDetails { + minCount: number; + maxCount: number; + minPriceRub: number; + maxPriceRub: number; } diff --git a/project/src/models/spt/inventory/IOwnerInventoryItems.ts b/project/src/models/spt/inventory/IOwnerInventoryItems.ts index 7c3ffbcf..854c9ddd 100644 --- a/project/src/models/spt/inventory/IOwnerInventoryItems.ts +++ b/project/src/models/spt/inventory/IOwnerInventoryItems.ts @@ -1,11 +1,10 @@ import { Item } from "@spt/models/eft/common/tables/IItem"; -export interface IOwnerInventoryItems -{ +export interface IOwnerInventoryItems { /** Inventory items from source */ - from: Item[] + from: Item[]; /** Inventory items at destination */ - to: Item[] - sameInventory: boolean - isMail: boolean + to: Item[]; + sameInventory: boolean; + isMail: boolean; } diff --git a/project/src/models/spt/location/IRaidChanges.ts b/project/src/models/spt/location/IRaidChanges.ts index bc06c304..b7a989b6 100644 --- a/project/src/models/spt/location/IRaidChanges.ts +++ b/project/src/models/spt/location/IRaidChanges.ts @@ -1,9 +1,8 @@ -export interface IRaidChanges -{ +export interface IRaidChanges { /** What percentage of dynamic loot should the map contain */ - dynamicLootPercent: number + dynamicLootPercent: number; /** What percentage of static loot should the map contain */ - staticLootPercent: number + staticLootPercent: number; /** How many seconds into the raid is the player simulated to spawn in at */ - simulatedRaidStartSeconds: number + simulatedRaidStartSeconds: number; } diff --git a/project/src/models/spt/logging/IClientLogRequest.ts b/project/src/models/spt/logging/IClientLogRequest.ts index 887c46ce..cf43c080 100644 --- a/project/src/models/spt/logging/IClientLogRequest.ts +++ b/project/src/models/spt/logging/IClientLogRequest.ts @@ -1,10 +1,9 @@ import { LogLevel } from "@spt/models/spt/logging/LogLevel"; -export interface IClientLogRequest -{ - Source: string - Level: LogLevel | string - Message: string - Color?: string - BackgroundColor?: string +export interface IClientLogRequest { + Source: string; + Level: LogLevel | string; + Message: string; + Color?: string; + BackgroundColor?: string; } diff --git a/project/src/models/spt/logging/LogBackgroundColor.ts b/project/src/models/spt/logging/LogBackgroundColor.ts index 56dd102a..01c4d78c 100644 --- a/project/src/models/spt/logging/LogBackgroundColor.ts +++ b/project/src/models/spt/logging/LogBackgroundColor.ts @@ -1,5 +1,4 @@ -export enum LogBackgroundColor -{ +export enum LogBackgroundColor { DEFAULT = "", BLACK = "blackBG", RED = "redBG", diff --git a/project/src/models/spt/logging/LogLevel.ts b/project/src/models/spt/logging/LogLevel.ts index 0723f167..a8a5425d 100644 --- a/project/src/models/spt/logging/LogLevel.ts +++ b/project/src/models/spt/logging/LogLevel.ts @@ -1,5 +1,4 @@ -export enum LogLevel -{ +export enum LogLevel { ERROR = 0, WARN = 1, SUCCESS = 2, diff --git a/project/src/models/spt/logging/LogTextColor.ts b/project/src/models/spt/logging/LogTextColor.ts index 4a85620f..1b9df23d 100644 --- a/project/src/models/spt/logging/LogTextColor.ts +++ b/project/src/models/spt/logging/LogTextColor.ts @@ -1,5 +1,4 @@ -export enum LogTextColor -{ +export enum LogTextColor { BLACK = "black", RED = "red", GREEN = "green", diff --git a/project/src/models/spt/logging/SptLogger.ts b/project/src/models/spt/logging/SptLogger.ts index 85bf4ad0..ea1b3d85 100644 --- a/project/src/models/spt/logging/SptLogger.ts +++ b/project/src/models/spt/logging/SptLogger.ts @@ -1,8 +1,7 @@ -export interface SptLogger -{ - error: (msg: string | Record) => void - warn: (msg: string | Record) => void - succ?: (msg: string | Record) => void - info: (msg: string | Record) => void - debug: (msg: string | Record) => void +export interface SptLogger { + error: (msg: string | Record) => void; + warn: (msg: string | Record) => void; + succ?: (msg: string | Record) => void; + info: (msg: string | Record) => void; + debug: (msg: string | Record) => void; } diff --git a/project/src/models/spt/mod/IModLoader.ts b/project/src/models/spt/mod/IModLoader.ts index 5636e91a..81814eb6 100644 --- a/project/src/models/spt/mod/IModLoader.ts +++ b/project/src/models/spt/mod/IModLoader.ts @@ -1,8 +1,7 @@ import { DependencyContainer } from "tsyringe"; -export interface IModLoader -{ - load(container: DependencyContainer): void +export interface IModLoader { + load(container: DependencyContainer): void; - getModPath(mod: string): string + getModPath(mod: string): string; } diff --git a/project/src/models/spt/mod/IPackageJsonData.ts b/project/src/models/spt/mod/IPackageJsonData.ts index 9563d867..d21e5f14 100644 --- a/project/src/models/spt/mod/IPackageJsonData.ts +++ b/project/src/models/spt/mod/IPackageJsonData.ts @@ -1,20 +1,19 @@ -export interface IPackageJsonData -{ - incompatibilities?: string[] - loadBefore?: string[] - loadAfter?: string[] - dependencies?: Record - modDependencies?: Record - name: string - url: string - author: string - version: string - sptVersion: string +export interface IPackageJsonData { + incompatibilities?: string[]; + loadBefore?: string[]; + loadAfter?: string[]; + dependencies?: Record; + modDependencies?: Record; + name: string; + url: string; + author: string; + version: string; + sptVersion: string; /** We deliberately purge this data */ - scripts: Record - devDependencies: Record - licence: string - main: string - isBundleMod: boolean - contributors: string[] + scripts: Record; + devDependencies: Record; + licence: string; + main: string; + isBundleMod: boolean; + contributors: string[]; } diff --git a/project/src/models/spt/mod/NewItemDetails.ts b/project/src/models/spt/mod/NewItemDetails.ts index b991a794..6534cd0c 100644 --- a/project/src/models/spt/mod/NewItemDetails.ts +++ b/project/src/models/spt/mod/NewItemDetails.ts @@ -1,7 +1,6 @@ import { ITemplateItem, Props } from "@spt/models/eft/common/tables/ITemplateItem"; -export abstract class NewItemDetailsBase -{ +export abstract class NewItemDetailsBase { /** Price of the item on flea market */ fleaPriceRoubles: number; @@ -18,8 +17,7 @@ export abstract class NewItemDetailsBase locales: Record; } -export class NewItemFromCloneDetails extends NewItemDetailsBase -{ +export class NewItemFromCloneDetails extends NewItemDetailsBase { /** Id of the item to copy and use as a base */ itemTplToClone: string; @@ -36,22 +34,18 @@ export class NewItemFromCloneDetails extends NewItemDetailsBase newId = ""; } -export class NewItemDetails extends NewItemDetailsBase -{ +export class NewItemDetails extends NewItemDetailsBase { newItem: ITemplateItem; } -export class LocaleDetails -{ +export class LocaleDetails { name: string; shortName: string; description: string; } -export class CreateItemResult -{ - constructor() - { +export class CreateItemResult { + constructor() { this.success = false; this.errors = []; } diff --git a/project/src/models/spt/quests/IGetRepeatableByIdResult.ts b/project/src/models/spt/quests/IGetRepeatableByIdResult.ts index 1b4dd7a7..e0f01e86 100644 --- a/project/src/models/spt/quests/IGetRepeatableByIdResult.ts +++ b/project/src/models/spt/quests/IGetRepeatableByIdResult.ts @@ -1,7 +1,6 @@ import { IPmcDataRepeatableQuest, IRepeatableQuest } from "@spt/models/eft/common/tables/IRepeatableQuests"; -export interface IGetRepeatableByIdResult -{ - quest: IRepeatableQuest - repeatableType: IPmcDataRepeatableQuest +export interface IGetRepeatableByIdResult { + quest: IRepeatableQuest; + repeatableType: IPmcDataRepeatableQuest; } diff --git a/project/src/models/spt/ragfair/IRagfairServerPrices.ts b/project/src/models/spt/ragfair/IRagfairServerPrices.ts index 31d45fe3..c7d246ac 100644 --- a/project/src/models/spt/ragfair/IRagfairServerPrices.ts +++ b/project/src/models/spt/ragfair/IRagfairServerPrices.ts @@ -1,5 +1,4 @@ -export interface IRagfairServerPrices -{ - static: Record - dynamic: Record +export interface IRagfairServerPrices { + static: Record; + dynamic: Record; } diff --git a/project/src/models/spt/repeatable/IQuestRewardValues.ts b/project/src/models/spt/repeatable/IQuestRewardValues.ts index fe31fd4f..bcee532e 100644 --- a/project/src/models/spt/repeatable/IQuestRewardValues.ts +++ b/project/src/models/spt/repeatable/IQuestRewardValues.ts @@ -1,11 +1,9 @@ -export interface IQuestRewardValues -{ - skillPointReward: number - skillRewardChance: number - rewardReputation: number - rewardNumItems: number - rewardRoubles: number - gpCoinRewardCount: number - rewardXP: number - +export interface IQuestRewardValues { + skillPointReward: number; + skillRewardChance: number; + rewardReputation: number; + rewardNumItems: number; + rewardRoubles: number; + gpCoinRewardCount: number; + rewardXP: number; } diff --git a/project/src/models/spt/repeatable/IQuestTypePool.ts b/project/src/models/spt/repeatable/IQuestTypePool.ts index ce0a7104..1f64a5ed 100644 --- a/project/src/models/spt/repeatable/IQuestTypePool.ts +++ b/project/src/models/spt/repeatable/IQuestTypePool.ts @@ -1,44 +1,38 @@ import { ELocationName } from "@spt/models/enums/ELocationName"; -export interface IQuestTypePool -{ - types: string[] - pool: IQuestPool +export interface IQuestTypePool { + types: string[]; + pool: IQuestPool; } -export interface IQuestPool -{ - Exploration: IExplorationPool - Elimination: IEliminationPool - Pickup: IExplorationPool +export interface IQuestPool { + Exploration: IExplorationPool; + Elimination: IEliminationPool; + Pickup: IExplorationPool; } -export interface IExplorationPool -{ - locations: Partial> +export interface IExplorationPool { + locations: Partial>; } -export interface IEliminationPool -{ - targets: IEliminationTargetPool +export interface IEliminationPool { + targets: IEliminationTargetPool; } -export interface IEliminationTargetPool -{ - Savage?: ITargetLocation - AnyPmc?: ITargetLocation - bossBully?: ITargetLocation - bossGluhar?: ITargetLocation - bossKilla?: ITargetLocation - bossSanitar?: ITargetLocation - bossTagilla?: ITargetLocation - bossKnight?: ITargetLocation - bossZryachiy?: ITargetLocation - bossBoar?: ITargetLocation - bossBoarSniper?: ITargetLocation +export interface IEliminationTargetPool { + Savage?: ITargetLocation; + AnyPmc?: ITargetLocation; + bossBully?: ITargetLocation; + bossGluhar?: ITargetLocation; + bossKilla?: ITargetLocation; + bossSanitar?: ITargetLocation; + bossTagilla?: ITargetLocation; + bossKnight?: ITargetLocation; + bossZryachiy?: ITargetLocation; + bossBoar?: ITargetLocation; + bossBoarSniper?: ITargetLocation; } -export interface ITargetLocation -{ - locations: string[] +export interface ITargetLocation { + locations: string[]; } diff --git a/project/src/models/spt/server/ExhaustableArray.ts b/project/src/models/spt/server/ExhaustableArray.ts index 85a18c65..7ebd396a 100644 --- a/project/src/models/spt/server/ExhaustableArray.ts +++ b/project/src/models/spt/server/ExhaustableArray.ts @@ -1,23 +1,19 @@ -import { ICloner } from "@spt/utils/cloners/ICloner"; import { RandomUtil } from "@spt/utils/RandomUtil"; +import { ICloner } from "@spt/utils/cloners/ICloner"; -export class ExhaustableArray implements IExhaustableArray -{ +export class ExhaustableArray implements IExhaustableArray { private pool: T[]; constructor( private itemPool: T[], private randomUtil: RandomUtil, private cloner: ICloner, - ) - { + ) { this.pool = this.cloner.clone(itemPool); } - public getRandomValue(): T | undefined - { - if (!this.pool?.length) - { + public getRandomValue(): T | undefined { + if (!this.pool?.length) { return undefined; } @@ -27,10 +23,8 @@ export class ExhaustableArray implements IExhaustableArray return toReturn; } - public getFirstValue(): T | undefined - { - if (!this.pool?.length) - { + public getFirstValue(): T | undefined { + if (!this.pool?.length) { return undefined; } @@ -39,10 +33,8 @@ export class ExhaustableArray implements IExhaustableArray return toReturn; } - public hasValues(): boolean - { - if (this.pool?.length) - { + public hasValues(): boolean { + if (this.pool?.length) { return true; } @@ -50,9 +42,8 @@ export class ExhaustableArray implements IExhaustableArray } } -export interface IExhaustableArray -{ - getRandomValue(): T | undefined - getFirstValue(): T | undefined - hasValues(): boolean +export interface IExhaustableArray { + getRandomValue(): T | undefined; + getFirstValue(): T | undefined; + hasValues(): boolean; } diff --git a/project/src/models/spt/server/IDatabaseTables.ts b/project/src/models/spt/server/IDatabaseTables.ts index be74a701..d3a64e97 100644 --- a/project/src/models/spt/server/IDatabaseTables.ts +++ b/project/src/models/spt/server/IDatabaseTables.ts @@ -9,17 +9,16 @@ import { IServerBase } from "@spt/models/spt/server/IServerBase"; import { ISettingsBase } from "@spt/models/spt/server/ISettingsBase"; import { ITemplates } from "@spt/models/spt/templates/ITemplates"; -export interface IDatabaseTables -{ - bots?: IBots - hideout?: IHideout - locales?: ILocaleBase - locations?: ILocations - match?: IMatch - templates?: ITemplates - traders?: Record +export interface IDatabaseTables { + bots?: IBots; + hideout?: IHideout; + locales?: ILocaleBase; + locations?: ILocations; + match?: IMatch; + templates?: ITemplates; + traders?: Record; - globals?: IGlobals - server?: IServerBase - settings?: ISettingsBase + globals?: IGlobals; + server?: IServerBase; + settings?: ISettingsBase; } diff --git a/project/src/models/spt/server/ILocaleBase.ts b/project/src/models/spt/server/ILocaleBase.ts index 960f5ded..3004cb8d 100644 --- a/project/src/models/spt/server/ILocaleBase.ts +++ b/project/src/models/spt/server/ILocaleBase.ts @@ -1,7 +1,6 @@ -export interface ILocaleBase -{ - global: Record> - menu: Record - languages: Record - server: Record> +export interface ILocaleBase { + global: Record>; + menu: Record; + languages: Record; + server: Record>; } diff --git a/project/src/models/spt/server/ILocations.ts b/project/src/models/spt/server/ILocations.ts index 2abf69c5..7f28917c 100644 --- a/project/src/models/spt/server/ILocations.ts +++ b/project/src/models/spt/server/ILocations.ts @@ -1,26 +1,25 @@ import { ILocation } from "@spt/models/eft/common/ILocation"; import { ILocationsBase } from "@spt/models/eft/common/tables/ILocationsBase"; -export interface ILocations -{ - bigmap?: ILocation - develop?: ILocation - factory4_day?: ILocation - factory4_night?: ILocation - hideout?: ILocation - interchange?: ILocation - laboratory?: ILocation - lighthouse?: ILocation - privatearea?: ILocation - rezervbase?: ILocation - shoreline?: ILocation - suburbs?: ILocation - tarkovstreets?: ILocation - terminal?: ILocation - town?: ILocation - woods?: ILocation - sandbox?: ILocation - sandbox_high?: ILocation +export interface ILocations { + bigmap?: ILocation; + develop?: ILocation; + factory4_day?: ILocation; + factory4_night?: ILocation; + hideout?: ILocation; + interchange?: ILocation; + laboratory?: ILocation; + lighthouse?: ILocation; + privatearea?: ILocation; + rezervbase?: ILocation; + shoreline?: ILocation; + suburbs?: ILocation; + tarkovstreets?: ILocation; + terminal?: ILocation; + town?: ILocation; + woods?: ILocation; + sandbox?: ILocation; + sandbox_high?: ILocation; /** Holds a mapping of the linkages between locations on the UI */ - base?: ILocationsBase + base?: ILocationsBase; } diff --git a/project/src/models/spt/server/IServerBase.ts b/project/src/models/spt/server/IServerBase.ts index 80ba5603..d033db3e 100644 --- a/project/src/models/spt/server/IServerBase.ts +++ b/project/src/models/spt/server/IServerBase.ts @@ -1,5 +1,4 @@ -export interface IServerBase -{ - ip: string - port: number +export interface IServerBase { + ip: string; + port: number; } diff --git a/project/src/models/spt/server/ISettingsBase.ts b/project/src/models/spt/server/ISettingsBase.ts index 57c8e50a..17082d7d 100644 --- a/project/src/models/spt/server/ISettingsBase.ts +++ b/project/src/models/spt/server/ISettingsBase.ts @@ -1,65 +1,59 @@ -export interface ISettingsBase -{ - config: Config +export interface ISettingsBase { + config: Config; } -export interface Config -{ - AFKTimeoutSeconds: number - AdditionalRandomDelaySeconds: number - ClientSendRateLimit: number - CriticalRetriesCount: number - DefaultRetriesCount: number - FirstCycleDelaySeconds: number - FramerateLimit: FramerateLimit - GroupStatusInterval: number - GroupStatusButtonInterval: number - KeepAliveInterval: number - LobbyKeepAliveInterval: number - Mark502and504AsNonImportant: boolean - MemoryManagementSettings: MemoryManagementSettings - NVidiaHighlights: boolean - NextCycleDelaySeconds: number - PingServerResultSendInterval: number - PingServersInterval: number - ReleaseProfiler: ReleaseProfiler - RequestConfirmationTimeouts: number[] - RequestsMadeThroughLobby: string[] - SecondCycleDelaySeconds: number - ShouldEstablishLobbyConnection: boolean - TurnOffLogging: boolean - WeaponOverlapDistanceCulling: number - WebDiagnosticsEnabled: boolean - NetworkStateView: INetworkStateView - WsReconnectionDelays: string[] +export interface Config { + AFKTimeoutSeconds: number; + AdditionalRandomDelaySeconds: number; + ClientSendRateLimit: number; + CriticalRetriesCount: number; + DefaultRetriesCount: number; + FirstCycleDelaySeconds: number; + FramerateLimit: FramerateLimit; + GroupStatusInterval: number; + GroupStatusButtonInterval: number; + KeepAliveInterval: number; + LobbyKeepAliveInterval: number; + Mark502and504AsNonImportant: boolean; + MemoryManagementSettings: MemoryManagementSettings; + NVidiaHighlights: boolean; + NextCycleDelaySeconds: number; + PingServerResultSendInterval: number; + PingServersInterval: number; + ReleaseProfiler: ReleaseProfiler; + RequestConfirmationTimeouts: number[]; + RequestsMadeThroughLobby: string[]; + SecondCycleDelaySeconds: number; + ShouldEstablishLobbyConnection: boolean; + TurnOffLogging: boolean; + WeaponOverlapDistanceCulling: number; + WebDiagnosticsEnabled: boolean; + NetworkStateView: INetworkStateView; + WsReconnectionDelays: string[]; } -export interface FramerateLimit -{ - MaxFramerateGameLimit: number - MaxFramerateLobbyLimit: number - MinFramerateLimit: number +export interface FramerateLimit { + MaxFramerateGameLimit: number; + MaxFramerateLobbyLimit: number; + MinFramerateLimit: number; } -export interface MemoryManagementSettings -{ - AggressiveGC: boolean - GigabytesRequiredToDisableGCDuringRaid: number - HeapPreAllocationEnabled: boolean - HeapPreAllocationMB: number - OverrideRamCleanerSettings: boolean - RamCleanerEnabled: boolean +export interface MemoryManagementSettings { + AggressiveGC: boolean; + GigabytesRequiredToDisableGCDuringRaid: number; + HeapPreAllocationEnabled: boolean; + HeapPreAllocationMB: number; + OverrideRamCleanerSettings: boolean; + RamCleanerEnabled: boolean; } -export interface ReleaseProfiler -{ - Enabled: boolean - MaxRecords: number - RecordTriggerValue: number +export interface ReleaseProfiler { + Enabled: boolean; + MaxRecords: number; + RecordTriggerValue: number; } -export interface INetworkStateView -{ - LossThreshold: number - RttThreshold: number +export interface INetworkStateView { + LossThreshold: number; + RttThreshold: number; } diff --git a/project/src/models/spt/services/CustomPreset.ts b/project/src/models/spt/services/CustomPreset.ts index da00ddc3..550e51be 100644 --- a/project/src/models/spt/services/CustomPreset.ts +++ b/project/src/models/spt/services/CustomPreset.ts @@ -1,7 +1,6 @@ import { IPreset } from "@spt/models/eft/common/IGlobals"; -export interface CustomPreset -{ - key: string - preset: IPreset +export interface CustomPreset { + key: string; + preset: IPreset; } diff --git a/project/src/models/spt/services/CustomTraderAssortData.ts b/project/src/models/spt/services/CustomTraderAssortData.ts index e27fe344..e865442a 100644 --- a/project/src/models/spt/services/CustomTraderAssortData.ts +++ b/project/src/models/spt/services/CustomTraderAssortData.ts @@ -1,8 +1,7 @@ import { ITraderAssort } from "@spt/models/eft/common/tables/ITrader"; import { Traders } from "@spt/models/enums/Traders"; -export interface CustomTraderAssortData -{ - traderId: Traders - assorts: ITraderAssort +export interface CustomTraderAssortData { + traderId: Traders; + assorts: ITraderAssort; } diff --git a/project/src/models/spt/services/IInsuranceEquipmentPkg.ts b/project/src/models/spt/services/IInsuranceEquipmentPkg.ts index 4b35672f..524c96a8 100644 --- a/project/src/models/spt/services/IInsuranceEquipmentPkg.ts +++ b/project/src/models/spt/services/IInsuranceEquipmentPkg.ts @@ -1,10 +1,9 @@ import { IPmcData } from "@spt/models/eft/common/IPmcData"; import { Item } from "@spt/models/eft/common/tables/IItem"; -export interface IInsuranceEquipmentPkg -{ - sessionID: string - pmcData: IPmcData - itemToReturnToPlayer: Item - traderId: string +export interface IInsuranceEquipmentPkg { + sessionID: string; + pmcData: IPmcData; + itemToReturnToPlayer: Item; + traderId: string; } diff --git a/project/src/models/spt/services/ITraderServiceModel.ts b/project/src/models/spt/services/ITraderServiceModel.ts index 2e24982b..52e8ca03 100644 --- a/project/src/models/spt/services/ITraderServiceModel.ts +++ b/project/src/models/spt/services/ITraderServiceModel.ts @@ -1,16 +1,14 @@ import { TraderServiceType } from "@spt/models/enums/TraderServiceType"; -export interface ITraderServiceModel -{ - serviceType: TraderServiceType - itemsToPay?: { [key: string]: number } - itemsToReceive?: string[] - subServices?: { [key: string]: number } - requirements?: ITraderServiceRequirementsModel +export interface ITraderServiceModel { + serviceType: TraderServiceType; + itemsToPay?: { [key: string]: number }; + itemsToReceive?: string[]; + subServices?: { [key: string]: number }; + requirements?: ITraderServiceRequirementsModel; } -export interface ITraderServiceRequirementsModel -{ - completedQuests?: string[] - standings?: { [key: string]: number } +export interface ITraderServiceRequirementsModel { + completedQuests?: string[]; + standings?: { [key: string]: number }; } diff --git a/project/src/models/spt/services/LootItem.ts b/project/src/models/spt/services/LootItem.ts index e75dd0d8..91851ca7 100644 --- a/project/src/models/spt/services/LootItem.ts +++ b/project/src/models/spt/services/LootItem.ts @@ -1,5 +1,4 @@ -export class LootItem -{ +export class LootItem { id?: string; tpl: string; isPreset: boolean; diff --git a/project/src/models/spt/services/LootRequest.ts b/project/src/models/spt/services/LootRequest.ts index 29a610f9..652b2d5e 100644 --- a/project/src/models/spt/services/LootRequest.ts +++ b/project/src/models/spt/services/LootRequest.ts @@ -1,17 +1,16 @@ import { MinMax } from "@spt/models/common/MinMax"; -export interface LootRequest -{ - weaponPresetCount: MinMax - armorPresetCount: MinMax - itemCount: MinMax - weaponCrateCount: MinMax - itemBlacklist: string[] - itemTypeWhitelist: string[] +export interface LootRequest { + weaponPresetCount: MinMax; + armorPresetCount: MinMax; + itemCount: MinMax; + weaponCrateCount: MinMax; + itemBlacklist: string[]; + itemTypeWhitelist: string[]; /** key: item base type: value: max count */ - itemLimits: Record - itemStackLimits: Record - armorLevelWhitelist: number[] - allowBossItems: boolean - useRewarditemBlacklist?: boolean + itemLimits: Record; + itemStackLimits: Record; + armorLevelWhitelist: number[]; + allowBossItems: boolean; + useRewarditemBlacklist?: boolean; } diff --git a/project/src/models/spt/templates/ITemplates.ts b/project/src/models/spt/templates/ITemplates.ts index f00578aa..21e6ee9e 100644 --- a/project/src/models/spt/templates/ITemplates.ts +++ b/project/src/models/spt/templates/ITemplates.ts @@ -8,27 +8,26 @@ import { IRepeatableQuestDatabase } from "@spt/models/eft/common/tables/IRepeata import { ITemplateItem } from "@spt/models/eft/common/tables/ITemplateItem"; import { IDefaultEquipmentPreset } from "@spt/models/eft/profile/ISptProfile"; -export interface ITemplates -{ - character: string[] - items: Record - quests: Record - repeatableQuests: IRepeatableQuestDatabase - handbook: IHandbookBase - customization: Record +export interface ITemplates { + character: string[]; + items: Record; + quests: Record; + repeatableQuests: IRepeatableQuestDatabase; + handbook: IHandbookBase; + customization: Record; /** The profile templates listed in the launcher on profile creation, split by account type (e.g. Standard) then side (e.g. bear/usec) */ - profiles: IProfileTemplates + profiles: IProfileTemplates; /** Flea prices of items - gathered from online flea market dump */ - prices: Record + prices: Record; /** Default equipment loadouts that show on main inventory screen */ - defaultEquipmentPresets: IDefaultEquipmentPreset[] + defaultEquipmentPresets: IDefaultEquipmentPreset[]; /** Achievements */ - achievements: IAchievement[] + achievements: IAchievement[]; /** Location services data */ - locationServices: ILocationServices + locationServices: ILocationServices; } diff --git a/project/src/models/spt/utils/IAsyncQueue.ts b/project/src/models/spt/utils/IAsyncQueue.ts index 7c64f0e8..79872ac6 100644 --- a/project/src/models/spt/utils/IAsyncQueue.ts +++ b/project/src/models/spt/utils/IAsyncQueue.ts @@ -1,6 +1,5 @@ import { ICommand } from "@spt/models/spt/utils/ICommand"; -export interface IAsyncQueue -{ - waitFor(command: ICommand): Promise +export interface IAsyncQueue { + waitFor(command: ICommand): Promise; } diff --git a/project/src/models/spt/utils/ICommand.ts b/project/src/models/spt/utils/ICommand.ts index efe231da..696bb839 100644 --- a/project/src/models/spt/utils/ICommand.ts +++ b/project/src/models/spt/utils/ICommand.ts @@ -1,5 +1,4 @@ -export interface ICommand -{ - uuid: string - cmd: () => Promise +export interface ICommand { + uuid: string; + cmd: () => Promise; } diff --git a/project/src/models/spt/utils/ILogger.ts b/project/src/models/spt/utils/ILogger.ts index 886e08bd..c2f9ad8b 100644 --- a/project/src/models/spt/utils/ILogger.ts +++ b/project/src/models/spt/utils/ILogger.ts @@ -2,21 +2,20 @@ import { Daum } from "@spt/models/eft/itemEvent/IItemEventRouterRequest"; import { LogBackgroundColor } from "@spt/models/spt/logging/LogBackgroundColor"; import { LogTextColor } from "@spt/models/spt/logging/LogTextColor"; -export interface ILogger -{ - writeToLogFile(data: string | Daum): void - log(data: string | Record | Error, color: string, backgroundColor?: string): void +export interface ILogger { + writeToLogFile(data: string | Daum): void; + log(data: string | Record | Error, color: string, backgroundColor?: string): void; logWithColor( data: string | Record, textColor: LogTextColor, backgroundColor?: LogBackgroundColor, - ): void + ): void; - error(data: string): void + error(data: string): void; - warning(data: string): void - success(data: string): void + warning(data: string): void; + success(data: string): void; - info(data: string): void - debug(data: string | Record, onlyShowInConsole?: boolean): void + info(data: string): void; + debug(data: string | Record, onlyShowInConsole?: boolean): void; } diff --git a/project/src/models/spt/weather/IGetLocalWeatherResponseData.ts b/project/src/models/spt/weather/IGetLocalWeatherResponseData.ts index 6b263c7c..a7ef01bb 100644 --- a/project/src/models/spt/weather/IGetLocalWeatherResponseData.ts +++ b/project/src/models/spt/weather/IGetLocalWeatherResponseData.ts @@ -1,7 +1,6 @@ import { IWeather } from "@spt/models/eft/weather/IWeatherData"; -export interface IGetLocalWeatherResponseData -{ +export interface IGetLocalWeatherResponseData { season: number; weather: IWeather[]; -} \ No newline at end of file +} diff --git a/project/src/routers/EventOutputHolder.ts b/project/src/routers/EventOutputHolder.ts index 893fe7b0..8d6954da 100644 --- a/project/src/routers/EventOutputHolder.ts +++ b/project/src/routers/EventOutputHolder.ts @@ -1,19 +1,18 @@ -import { inject, injectable } from "tsyringe"; import { ProfileHelper } from "@spt/helpers/ProfileHelper"; import { IPmcData } from "@spt/models/eft/common/IPmcData"; import { IHideoutImprovement, Productive, TraderInfo } from "@spt/models/eft/common/tables/IBotBase"; import { ProfileChange, TraderData } from "@spt/models/eft/itemEvent/IItemEventRouterBase"; import { IItemEventRouterResponse } from "@spt/models/eft/itemEvent/IItemEventRouterResponse"; -import { ICloner } from "@spt/utils/cloners/ICloner"; import { TimeUtil } from "@spt/utils/TimeUtil"; +import { ICloner } from "@spt/utils/cloners/ICloner"; +import { inject, injectable } from "tsyringe"; @injectable() -export class EventOutputHolder -{ +export class EventOutputHolder { /** * What has client been informed of this game session * Key = sessionId, then second key is prod id - */ + */ protected clientActiveSessionStorage: Record> = {}; protected outputStore: Record = {}; @@ -21,13 +20,10 @@ export class EventOutputHolder @inject("ProfileHelper") protected profileHelper: ProfileHelper, @inject("TimeUtil") protected timeUtil: TimeUtil, @inject("PrimaryCloner") protected cloner: ICloner, - ) - {} + ) {} - public getOutput(sessionID: string): IItemEventRouterResponse - { - if (!this.outputStore[sessionID]?.profileChanges[sessionID]) - { + public getOutput(sessionID: string): IItemEventRouterResponse { + if (!this.outputStore[sessionID]?.profileChanges[sessionID]) { this.resetOutput(sessionID); } @@ -39,8 +35,7 @@ export class EventOutputHolder * Occurs prior to event being handled by server * @param sessionID Players id */ - public resetOutput(sessionID: string): void - { + public resetOutput(sessionID: string): void { const pmcData: IPmcData = this.profileHelper.getPmcProfile(sessionID); this.outputStore[sessionID] = { warnings: [], profileChanges: {} }; @@ -67,8 +62,7 @@ export class EventOutputHolder * Update output object with most recent values from player profile * @param sessionId Session id */ - public updateOutputProperties(sessionId: string): void - { + public updateOutputProperties(sessionId: string): void { const pmcData: IPmcData = this.profileHelper.getPmcProfile(sessionId); const profileChanges: ProfileChange = this.outputStore[sessionId].profileChanges[sessionId]; @@ -94,12 +88,10 @@ export class EventOutputHolder * @param traderData server data for traders * @returns dict of trader id + TraderData */ - protected constructTraderRelations(traderData: Record): Record - { + protected constructTraderRelations(traderData: Record): Record { const result: Record = {}; - for (const traderId in traderData) - { + for (const traderId in traderData) { const baseData = traderData[traderId]; result[traderId] = { salesSum: baseData.salesSum, @@ -118,20 +110,16 @@ export class EventOutputHolder * @param pmcData Player profile * @returns dictionary of hideout improvements */ - protected getImprovementsFromProfileAndFlagComplete(pmcData: IPmcData): Record - { - for (const improvementKey in pmcData.Hideout.Improvement) - { + protected getImprovementsFromProfileAndFlagComplete(pmcData: IPmcData): Record { + for (const improvementKey in pmcData.Hideout.Improvement) { const improvement = pmcData.Hideout.Improvement[improvementKey]; // Skip completed - if (improvement.completed) - { + if (improvement.completed) { continue; } - if (improvement.improveCompleteTimestamp < this.timeUtil.getTimestamp()) - { + if (improvement.improveCompleteTimestamp < this.timeUtil.getTimestamp()) { improvement.completed = true; } } @@ -147,48 +135,40 @@ export class EventOutputHolder protected getProductionsFromProfileAndFlagComplete( productions: Record, sessionId: string, - ): Record | undefined - { - for (const productionKey in productions) - { + ): Record | undefined { + for (const productionKey in productions) { const production = productions[productionKey]; - if (!production) - { + if (!production) { // Could be cancelled production, skip item to save processing continue; } // Complete and is Continuous e.g. water collector - if (production.sptIsComplete && production.sptIsContinuous) - { + if (production.sptIsComplete && production.sptIsContinuous) { continue; } // Skip completed - if (!production.inProgress) - { + if (!production.inProgress) { continue; } // Client informed of craft, remove from data returned let storageForSessionId = this.clientActiveSessionStorage[sessionId]; - if (typeof storageForSessionId === "undefined") - { + if (typeof storageForSessionId === "undefined") { this.clientActiveSessionStorage[sessionId] = {}; storageForSessionId = this.clientActiveSessionStorage[sessionId]; } // Ensure we don't inform client of production again - if (storageForSessionId[productionKey]?.clientInformed) - { + if (storageForSessionId[productionKey]?.clientInformed) { delete productions[productionKey]; continue; } // Flag started craft as having been seen by client so it won't happen subsequent times - if (production.Progress > 0 && !storageForSessionId[productionKey]?.clientInformed) - { + if (production.Progress > 0 && !storageForSessionId[productionKey]?.clientInformed) { storageForSessionId[productionKey] = { clientInformed: true }; } } @@ -201,20 +181,15 @@ export class EventOutputHolder * Required as continuous productions don't reset and stay at 100% completion but client thinks it hasn't started * @param productions Productions in a profile */ - protected cleanUpCompleteCraftsInProfile(productions: Record): void - { - for (const productionKey in productions) - { + protected cleanUpCompleteCraftsInProfile(productions: Record): void { + for (const productionKey in productions) { const production = productions[productionKey]; - if (production?.sptIsComplete && production?.sptIsContinuous) - { + if (production?.sptIsComplete && production?.sptIsContinuous) { // Water collector / Bitcoin etc production.sptIsComplete = false; production.Progress = 0; production.StartTimestamp = this.timeUtil.getTimestamp(); - } - else if (!production?.inProgress) - { + } else if (!production?.inProgress) { // Normal completed craft, delete delete productions[productionKey]; } diff --git a/project/src/routers/HttpRouter.ts b/project/src/routers/HttpRouter.ts index ac8e7017..92558868 100644 --- a/project/src/routers/HttpRouter.ts +++ b/project/src/routers/HttpRouter.ts @@ -1,54 +1,43 @@ import { IncomingMessage } from "node:http"; -import { injectAll, injectable } from "tsyringe"; import { DynamicRouter, Router, StaticRouter } from "@spt/di/Router"; +import { injectAll, injectable } from "tsyringe"; @injectable() -export class HttpRouter -{ +export class HttpRouter { constructor( @injectAll("StaticRoutes") protected staticRouters: StaticRouter[], @injectAll("DynamicRoutes") protected dynamicRoutes: DynamicRouter[], - ) - {} + ) {} - protected groupBy(list: T[], keyGetter: (t: T) => string): Map - { + protected groupBy(list: T[], keyGetter: (t: T) => string): Map { const map: Map = new Map(); - for (const item of list) - { + for (const item of list) { const key = keyGetter(item); const collection = map.get(key); - if (!collection) - { + if (!collection) { map.set(key, [item]); - } - else - { + } else { collection.push(item); } } return map; } - public async getResponse(req: IncomingMessage, info: any, sessionID: string): Promise - { + public async getResponse(req: IncomingMessage, info: any, sessionID: string): Promise { const wrapper: ResponseWrapper = new ResponseWrapper(""); let url = req.url; // remove retry from url - if (url?.includes("?retry=")) - { + if (url?.includes("?retry=")) { url = url.split("?retry=")[0]; } const handled = await this.handleRoute(url, info, sessionID, wrapper, this.staticRouters, false); - if (!handled) - { + if (!handled) { await this.handleRoute(url, info, sessionID, wrapper, this.dynamicRoutes, true); } // TODO: Temporary hack to change ItemEventRouter response sessionID binding to what client expects - if (wrapper.output?.includes('"profileChanges":{')) - { + if (wrapper.output?.includes('"profileChanges":{')) { wrapper.output = wrapper.output.replace(sessionID, sessionID); } @@ -62,19 +51,13 @@ export class HttpRouter wrapper: ResponseWrapper, routers: Router[], dynamic: boolean, - ): Promise - { + ): Promise { let matched = false; - for (const route of routers) - { - if (route.canHandle(url, dynamic)) - { - if (dynamic) - { + for (const route of routers) { + if (route.canHandle(url, dynamic)) { + if (dynamic) { wrapper.output = await (route as DynamicRouter).handleDynamic(url, info, sessionID, wrapper.output); - } - else - { + } else { wrapper.output = await (route as StaticRouter).handleStatic(url, info, sessionID, wrapper.output); } matched = true; @@ -84,8 +67,6 @@ export class HttpRouter } } -class ResponseWrapper -{ - constructor(public output: string) - {} +class ResponseWrapper { + constructor(public output: string) {} } diff --git a/project/src/routers/ImageRouter.ts b/project/src/routers/ImageRouter.ts index d6419b08..1958ad9a 100644 --- a/project/src/routers/ImageRouter.ts +++ b/project/src/routers/ImageRouter.ts @@ -1,38 +1,32 @@ import { IncomingMessage, ServerResponse } from "node:http"; -import { inject, injectable } from "tsyringe"; import { ImageRouteService } from "@spt/services/mod/image/ImageRouteService"; import { HttpFileUtil } from "@spt/utils/HttpFileUtil"; import { VFS } from "@spt/utils/VFS"; +import { inject, injectable } from "tsyringe"; @injectable() -export class ImageRouter -{ +export class ImageRouter { constructor( @inject("VFS") protected vfs: VFS, @inject("ImageRouteService") protected imageRouteService: ImageRouteService, @inject("HttpFileUtil") protected httpFileUtil: HttpFileUtil, - ) - {} + ) {} - public addRoute(key: string, valueToAdd: string): void - { + public addRoute(key: string, valueToAdd: string): void { this.imageRouteService.addRoute(key, valueToAdd); } - public sendImage(sessionID: string, req: IncomingMessage, resp: ServerResponse, body: any): void - { + public sendImage(sessionID: string, req: IncomingMessage, resp: ServerResponse, body: any): void { // remove file extension const url = this.vfs.stripExtension(req.url); // send image - if (this.imageRouteService.existsByKey(url)) - { + if (this.imageRouteService.existsByKey(url)) { this.httpFileUtil.sendFile(resp, this.imageRouteService.getByKey(url)); } } - public getImage(): string - { + public getImage(): string { return "IMAGE"; } } diff --git a/project/src/routers/ItemEventRouter.ts b/project/src/routers/ItemEventRouter.ts index 1f323bd0..6cfe740d 100644 --- a/project/src/routers/ItemEventRouter.ts +++ b/project/src/routers/ItemEventRouter.ts @@ -1,4 +1,3 @@ -import { inject, injectAll, injectable } from "tsyringe"; import { ItemEventRouterDefinition } from "@spt/di/Router"; import { ProfileHelper } from "@spt/helpers/ProfileHelper"; import { IItemEventRouterRequest } from "@spt/models/eft/itemEvent/IItemEventRouterRequest"; @@ -7,10 +6,10 @@ import { ILogger } from "@spt/models/spt/utils/ILogger"; import { EventOutputHolder } from "@spt/routers/EventOutputHolder"; import { LocalisationService } from "@spt/services/LocalisationService"; import { ICloner } from "@spt/utils/cloners/ICloner"; +import { inject, injectAll, injectable } from "tsyringe"; @injectable() -export class ItemEventRouter -{ +export class ItemEventRouter { constructor( @inject("PrimaryLogger") protected logger: ILogger, @inject("ProfileHelper") protected profileHelper: ProfileHelper, @@ -18,34 +17,27 @@ export class ItemEventRouter @inject("LocalisationService") protected localisationService: LocalisationService, @inject("EventOutputHolder") protected eventOutputHolder: EventOutputHolder, @inject("PrimaryCloner") protected cloner: ICloner, - ) - {} + ) {} /** * @param info Event request * @param sessionID Session id * @returns Item response */ - public async handleEvents(info: IItemEventRouterRequest, sessionID: string): Promise - { + public async handleEvents(info: IItemEventRouterRequest, sessionID: string): Promise { const output = this.eventOutputHolder.getOutput(sessionID); - for (const body of info.data) - { + for (const body of info.data) { const pmcData = this.profileHelper.getPmcProfile(sessionID); const eventRouter = this.itemEventRouters.find((r) => r.canHandle(body.Action)); - if (eventRouter) - { + if (eventRouter) { this.logger.debug(`event: ${body.Action}`); await eventRouter.handleItemEvent(body.Action, pmcData, body, sessionID, output); - if (output.warnings.length > 0) - { + if (output.warnings.length > 0) { break; } - } - else - { + } else { this.logger.error(this.localisationService.getText("event-unhandled_event", body.Action)); this.logger.writeToLogFile(body); } diff --git a/project/src/routers/dynamic/BotDynamicRouter.ts b/project/src/routers/dynamic/BotDynamicRouter.ts index b3612a84..a195c34f 100644 --- a/project/src/routers/dynamic/BotDynamicRouter.ts +++ b/project/src/routers/dynamic/BotDynamicRouter.ts @@ -1,25 +1,21 @@ -import { inject, injectable } from "tsyringe"; import { BotCallbacks } from "@spt/callbacks/BotCallbacks"; import { DynamicRouter, RouteAction } from "@spt/di/Router"; import { Difficulties } from "@spt/models/eft/common/tables/IBotType"; +import { inject, injectable } from "tsyringe"; @injectable() -export class BotDynamicRouter extends DynamicRouter -{ - constructor(@inject("BotCallbacks") protected botCallbacks: BotCallbacks) - { +export class BotDynamicRouter extends DynamicRouter { + constructor(@inject("BotCallbacks") protected botCallbacks: BotCallbacks) { super([ new RouteAction( "/singleplayer/settings/bot/limit/", - async (url: string, info: any, sessionID: string, output: string): Promise => - { + async (url: string, info: any, sessionID: string, output: string): Promise => { return this.botCallbacks.getBotLimit(url, info, sessionID); }, ), new RouteAction( "/singleplayer/settings/bot/difficulty/", - async (url: string, info: any, sessionID: string, output: string): Promise => - { + async (url: string, info: any, sessionID: string, output: string): Promise => { return this.botCallbacks.getBotDifficulty(url, info, sessionID); }, ), @@ -30,22 +26,19 @@ export class BotDynamicRouter extends DynamicRouter info: any, sessionID: string, output: string, - ): Promise> => - { + ): Promise> => { return this.botCallbacks.getAllBotDifficulties(url, info, sessionID); }, ), new RouteAction( "/singleplayer/settings/bot/maxCap", - async (url: string, info: any, sessionID: string, output: string): Promise => - { + async (url: string, info: any, sessionID: string, output: string): Promise => { return this.botCallbacks.getBotCap(url, info, sessionID); }, ), new RouteAction( "/singleplayer/settings/bot/getBotBehaviours/", - async (url: string, info: any, sessionID: string, output: string): Promise => - { + async (url: string, info: any, sessionID: string, output: string): Promise => { return this.botCallbacks.getBotBehaviours(); }, ), diff --git a/project/src/routers/dynamic/BundleDynamicRouter.ts b/project/src/routers/dynamic/BundleDynamicRouter.ts index 7b96f5a3..148c639d 100644 --- a/project/src/routers/dynamic/BundleDynamicRouter.ts +++ b/project/src/routers/dynamic/BundleDynamicRouter.ts @@ -1,15 +1,12 @@ -import { inject, injectable } from "tsyringe"; import { BundleCallbacks } from "@spt/callbacks/BundleCallbacks"; import { DynamicRouter, RouteAction } from "@spt/di/Router"; +import { inject, injectable } from "tsyringe"; @injectable() -export class BundleDynamicRouter extends DynamicRouter -{ - constructor(@inject("BundleCallbacks") protected bundleCallbacks: BundleCallbacks) - { +export class BundleDynamicRouter extends DynamicRouter { + constructor(@inject("BundleCallbacks") protected bundleCallbacks: BundleCallbacks) { super([ - new RouteAction("/files/bundle", (url: string, info: any, sessionID: string, output: string): any => - { + new RouteAction("/files/bundle", (url: string, info: any, sessionID: string, output: string): any => { return this.bundleCallbacks.getBundle(url, info, sessionID); }), ]); diff --git a/project/src/routers/dynamic/CustomizationDynamicRouter.ts b/project/src/routers/dynamic/CustomizationDynamicRouter.ts index fcd2bced..73e628a8 100644 --- a/project/src/routers/dynamic/CustomizationDynamicRouter.ts +++ b/project/src/routers/dynamic/CustomizationDynamicRouter.ts @@ -1,14 +1,12 @@ -import { inject, injectable } from "tsyringe"; import { CustomizationCallbacks } from "@spt/callbacks/CustomizationCallbacks"; import { DynamicRouter, RouteAction } from "@spt/di/Router"; import { ISuit } from "@spt/models/eft/common/tables/ITrader"; import { IGetBodyResponseData } from "@spt/models/eft/httpResponse/IGetBodyResponseData"; +import { inject, injectable } from "tsyringe"; @injectable() -export class CustomizationDynamicRouter extends DynamicRouter -{ - constructor(@inject("CustomizationCallbacks") protected customizationCallbacks: CustomizationCallbacks) - { +export class CustomizationDynamicRouter extends DynamicRouter { + constructor(@inject("CustomizationCallbacks") protected customizationCallbacks: CustomizationCallbacks) { super([ new RouteAction( "/client/trading/customization/", @@ -17,8 +15,7 @@ export class CustomizationDynamicRouter extends DynamicRouter info: any, sessionID: string, output: string, - ): Promise> => - { + ): Promise> => { return this.customizationCallbacks.getTraderSuits(url, info, sessionID); }, ), diff --git a/project/src/routers/dynamic/DataDynamicRouter.ts b/project/src/routers/dynamic/DataDynamicRouter.ts index a2420bf8..20b7485f 100644 --- a/project/src/routers/dynamic/DataDynamicRouter.ts +++ b/project/src/routers/dynamic/DataDynamicRouter.ts @@ -1,14 +1,12 @@ -import { inject, injectable } from "tsyringe"; import { DataCallbacks } from "@spt/callbacks/DataCallbacks"; import { DynamicRouter, RouteAction } from "@spt/di/Router"; import { IGetItemPricesResponse } from "@spt/models/eft/game/IGetItemPricesResponse"; import { IGetBodyResponseData } from "@spt/models/eft/httpResponse/IGetBodyResponseData"; +import { inject, injectable } from "tsyringe"; @injectable() -export class DataDynamicRouter extends DynamicRouter -{ - constructor(@inject("DataCallbacks") protected dataCallbacks: DataCallbacks) - { +export class DataDynamicRouter extends DynamicRouter { + constructor(@inject("DataCallbacks") protected dataCallbacks: DataCallbacks) { super([ new RouteAction( "/client/menu/locale/", @@ -17,15 +15,13 @@ export class DataDynamicRouter extends DynamicRouter info: any, sessionID: string, output: string, - ): Promise> => - { + ): Promise> => { return this.dataCallbacks.getLocalesMenu(url, info, sessionID); }, ), new RouteAction( "/client/locale/", - async (url: string, info: any, sessionID: string, output: string): Promise => - { + async (url: string, info: any, sessionID: string, output: string): Promise => { return this.dataCallbacks.getLocalesGlobal(url, info, sessionID); }, ), @@ -36,8 +32,7 @@ export class DataDynamicRouter extends DynamicRouter info: any, sessionID: string, output: string, - ): Promise> => - { + ): Promise> => { return this.dataCallbacks.getItemPrices(url, info, sessionID); }, ), diff --git a/project/src/routers/dynamic/HttpDynamicRouter.ts b/project/src/routers/dynamic/HttpDynamicRouter.ts index f8fedca4..9840aea3 100644 --- a/project/src/routers/dynamic/HttpDynamicRouter.ts +++ b/project/src/routers/dynamic/HttpDynamicRouter.ts @@ -1,31 +1,26 @@ -import { inject, injectable } from "tsyringe"; import { DynamicRouter, RouteAction } from "@spt/di/Router"; import { ImageRouter } from "@spt/routers/ImageRouter"; +import { inject, injectable } from "tsyringe"; @injectable() -export class HttpDynamicRouter extends DynamicRouter -{ - constructor(@inject("ImageRouter") protected imageRouter: ImageRouter) - { +export class HttpDynamicRouter extends DynamicRouter { + constructor(@inject("ImageRouter") protected imageRouter: ImageRouter) { super([ new RouteAction( ".jpg", - async (url: string, info: any, sessionID: string, output: string): Promise => - { + async (url: string, info: any, sessionID: string, output: string): Promise => { return this.imageRouter.getImage(); }, ), new RouteAction( ".png", - async (url: string, info: any, sessionID: string, output: string): Promise => - { + async (url: string, info: any, sessionID: string, output: string): Promise => { return this.imageRouter.getImage(); }, ), new RouteAction( ".ico", - async (url: string, info: any, sessionID: string, output: string): Promise => - { + async (url: string, info: any, sessionID: string, output: string): Promise => { return this.imageRouter.getImage(); }, ), diff --git a/project/src/routers/dynamic/InraidDynamicRouter.ts b/project/src/routers/dynamic/InraidDynamicRouter.ts index ef118b6f..997d606d 100644 --- a/project/src/routers/dynamic/InraidDynamicRouter.ts +++ b/project/src/routers/dynamic/InraidDynamicRouter.ts @@ -1,26 +1,22 @@ -import { inject, injectable } from "tsyringe"; import { InraidCallbacks } from "@spt/callbacks/InraidCallbacks"; import { DynamicRouter, RouteAction } from "@spt/di/Router"; import { INullResponseData } from "@spt/models/eft/httpResponse/INullResponseData"; +import { inject, injectable } from "tsyringe"; @injectable() -export class InraidDynamicRouter extends DynamicRouter -{ - constructor(@inject("InraidCallbacks") protected inraidCallbacks: InraidCallbacks) - { +export class InraidDynamicRouter extends DynamicRouter { + constructor(@inject("InraidCallbacks") protected inraidCallbacks: InraidCallbacks) { super([ new RouteAction( "/client/location/getLocalloot", - async (url: string, info: any, sessionID: string, output: string): Promise => - { + async (url: string, info: any, sessionID: string, output: string): Promise => { return this.inraidCallbacks.registerPlayer(url, info, sessionID); }, ), ]); } - public override getTopLevelRoute(): string - { + public override getTopLevelRoute(): string { return "spt-name"; } } diff --git a/project/src/routers/dynamic/LocationDynamicRouter.ts b/project/src/routers/dynamic/LocationDynamicRouter.ts index 3330070f..c66238c0 100644 --- a/project/src/routers/dynamic/LocationDynamicRouter.ts +++ b/project/src/routers/dynamic/LocationDynamicRouter.ts @@ -1,17 +1,14 @@ -import { inject, injectable } from "tsyringe"; import { LocationCallbacks } from "@spt/callbacks/LocationCallbacks"; import { DynamicRouter } from "@spt/di/Router"; +import { inject, injectable } from "tsyringe"; @injectable() -export class LocationDynamicRouter extends DynamicRouter -{ - constructor(@inject("LocationCallbacks") protected locationCallbacks: LocationCallbacks) - { +export class LocationDynamicRouter extends DynamicRouter { + constructor(@inject("LocationCallbacks") protected locationCallbacks: LocationCallbacks) { super([]); } - public override getTopLevelRoute(): string - { + public override getTopLevelRoute(): string { return "spt-loot"; } } diff --git a/project/src/routers/dynamic/NotifierDynamicRouter.ts b/project/src/routers/dynamic/NotifierDynamicRouter.ts index bb3397b4..2c80e884 100644 --- a/project/src/routers/dynamic/NotifierDynamicRouter.ts +++ b/project/src/routers/dynamic/NotifierDynamicRouter.ts @@ -1,25 +1,21 @@ -import { inject, injectable } from "tsyringe"; import { NotifierCallbacks } from "@spt/callbacks/NotifierCallbacks"; import { DynamicRouter, RouteAction } from "@spt/di/Router"; import { IGetBodyResponseData } from "@spt/models/eft/httpResponse/IGetBodyResponseData"; +import { inject, injectable } from "tsyringe"; @injectable() -export class NotifierDynamicRouter extends DynamicRouter -{ - constructor(@inject("NotifierCallbacks") protected notifierCallbacks: NotifierCallbacks) - { +export class NotifierDynamicRouter extends DynamicRouter { + constructor(@inject("NotifierCallbacks") protected notifierCallbacks: NotifierCallbacks) { super([ new RouteAction( "/?last_id", - async (url: string, info: any, sessionID: string, output: string): Promise => - { + async (url: string, info: any, sessionID: string, output: string): Promise => { return this.notifierCallbacks.notify(url, info, sessionID); }, ), new RouteAction( "/notifierServer", - async (url: string, info: any, sessionID: string, output: string): Promise => - { + async (url: string, info: any, sessionID: string, output: string): Promise => { return this.notifierCallbacks.notify(url, info, sessionID); }, ), @@ -30,8 +26,7 @@ export class NotifierDynamicRouter extends DynamicRouter info: any, sessionID: string, output: string, - ): Promise> => - { + ): Promise> => { return this.notifierCallbacks.getNotifier(url, info, sessionID); }, ), @@ -42,8 +37,7 @@ export class NotifierDynamicRouter extends DynamicRouter info: any, sessionID: string, output: string, - ): Promise> => - { + ): Promise> => { return this.notifierCallbacks.getNotifier(url, info, sessionID); }, ), diff --git a/project/src/routers/dynamic/TraderDynamicRouter.ts b/project/src/routers/dynamic/TraderDynamicRouter.ts index c215672f..de810b39 100644 --- a/project/src/routers/dynamic/TraderDynamicRouter.ts +++ b/project/src/routers/dynamic/TraderDynamicRouter.ts @@ -1,14 +1,12 @@ -import { inject, injectable } from "tsyringe"; import { TraderCallbacks } from "@spt/callbacks/TraderCallbacks"; import { DynamicRouter, RouteAction } from "@spt/di/Router"; import { ITraderAssort, ITraderBase } from "@spt/models/eft/common/tables/ITrader"; import { IGetBodyResponseData } from "@spt/models/eft/httpResponse/IGetBodyResponseData"; +import { inject, injectable } from "tsyringe"; @injectable() -export class TraderDynamicRouter extends DynamicRouter -{ - constructor(@inject("TraderCallbacks") protected traderCallbacks: TraderCallbacks) - { +export class TraderDynamicRouter extends DynamicRouter { + constructor(@inject("TraderCallbacks") protected traderCallbacks: TraderCallbacks) { super([ new RouteAction( "/client/trading/api/getTrader/", @@ -17,8 +15,7 @@ export class TraderDynamicRouter extends DynamicRouter info: any, sessionID: string, output: string, - ): Promise> => - { + ): Promise> => { return this.traderCallbacks.getTrader(url, info, sessionID); }, ), @@ -29,8 +26,7 @@ export class TraderDynamicRouter extends DynamicRouter info: any, sessionID: string, output: string, - ): Promise> => - { + ): Promise> => { return this.traderCallbacks.getAssort(url, info, sessionID); }, ), diff --git a/project/src/routers/item_events/CustomizationItemEventRouter.ts b/project/src/routers/item_events/CustomizationItemEventRouter.ts index 3da445bd..aabb8217 100644 --- a/project/src/routers/item_events/CustomizationItemEventRouter.ts +++ b/project/src/routers/item_events/CustomizationItemEventRouter.ts @@ -1,21 +1,18 @@ -import { inject, injectable } from "tsyringe"; import { CustomizationCallbacks } from "@spt/callbacks/CustomizationCallbacks"; import { HandledRoute, ItemEventRouterDefinition } from "@spt/di/Router"; import { IPmcData } from "@spt/models/eft/common/IPmcData"; import { IItemEventRouterResponse } from "@spt/models/eft/itemEvent/IItemEventRouterResponse"; +import { inject, injectable } from "tsyringe"; @injectable() -export class CustomizationItemEventRouter extends ItemEventRouterDefinition -{ +export class CustomizationItemEventRouter extends ItemEventRouterDefinition { constructor( @inject("CustomizationCallbacks") protected customizationCallbacks: CustomizationCallbacks, // TODO: delay required - ) - { + ) { super(); } - public override getHandledRoutes(): HandledRoute[] - { + public override getHandledRoutes(): HandledRoute[] { return [new HandledRoute("CustomizationWear", false), new HandledRoute("CustomizationBuy", false)]; } @@ -24,10 +21,8 @@ export class CustomizationItemEventRouter extends ItemEventRouterDefinition pmcData: IPmcData, body: any, sessionID: string, - ): Promise - { - switch (url) - { + ): Promise { + switch (url) { case "CustomizationWear": return this.customizationCallbacks.wearClothing(pmcData, body, sessionID); case "CustomizationBuy": diff --git a/project/src/routers/item_events/HealthItemEventRouter.ts b/project/src/routers/item_events/HealthItemEventRouter.ts index 67051c54..30b6c57a 100644 --- a/project/src/routers/item_events/HealthItemEventRouter.ts +++ b/project/src/routers/item_events/HealthItemEventRouter.ts @@ -1,21 +1,18 @@ -import { inject, injectable } from "tsyringe"; import { HealthCallbacks } from "@spt/callbacks/HealthCallbacks"; import { HandledRoute, ItemEventRouterDefinition } from "@spt/di/Router"; import { IPmcData } from "@spt/models/eft/common/IPmcData"; import { IItemEventRouterResponse } from "@spt/models/eft/itemEvent/IItemEventRouterResponse"; +import { inject, injectable } from "tsyringe"; @injectable() -export class HealthItemEventRouter extends ItemEventRouterDefinition -{ +export class HealthItemEventRouter extends ItemEventRouterDefinition { constructor( @inject("HealthCallbacks") protected healthCallbacks: HealthCallbacks, // TODO: delay required - ) - { + ) { super(); } - public override getHandledRoutes(): HandledRoute[] - { + public override getHandledRoutes(): HandledRoute[] { return [ new HandledRoute("Eat", false), new HandledRoute("Heal", false), @@ -28,10 +25,8 @@ export class HealthItemEventRouter extends ItemEventRouterDefinition pmcData: IPmcData, body: any, sessionID: string, - ): Promise - { - switch (url) - { + ): Promise { + switch (url) { case "Eat": return this.healthCallbacks.offraidEat(pmcData, body, sessionID); case "Heal": diff --git a/project/src/routers/item_events/HideoutItemEventRouter.ts b/project/src/routers/item_events/HideoutItemEventRouter.ts index a0fa3384..07c0bf5a 100644 --- a/project/src/routers/item_events/HideoutItemEventRouter.ts +++ b/project/src/routers/item_events/HideoutItemEventRouter.ts @@ -1,20 +1,17 @@ -import { inject, injectable } from "tsyringe"; import { HideoutCallbacks } from "@spt/callbacks/HideoutCallbacks"; import { HandledRoute, ItemEventRouterDefinition } from "@spt/di/Router"; import { IPmcData } from "@spt/models/eft/common/IPmcData"; import { IItemEventRouterResponse } from "@spt/models/eft/itemEvent/IItemEventRouterResponse"; import { HideoutEventActions } from "@spt/models/enums/HideoutEventActions"; +import { inject, injectable } from "tsyringe"; @injectable() -export class HideoutItemEventRouter extends ItemEventRouterDefinition -{ - constructor(@inject("HideoutCallbacks") protected hideoutCallbacks: HideoutCallbacks) - { +export class HideoutItemEventRouter extends ItemEventRouterDefinition { + constructor(@inject("HideoutCallbacks") protected hideoutCallbacks: HideoutCallbacks) { super(); } - public override getHandledRoutes(): HandledRoute[] - { + public override getHandledRoutes(): HandledRoute[] { return [ new HandledRoute(HideoutEventActions.HIDEOUT_UPGRADE, false), new HandledRoute(HideoutEventActions.HIDEOUT_UPGRADE_COMPLETE, false), @@ -37,10 +34,8 @@ export class HideoutItemEventRouter extends ItemEventRouterDefinition body: any, sessionID: string, output: IItemEventRouterResponse, - ): Promise - { - switch (url) - { + ): Promise { + switch (url) { case HideoutEventActions.HIDEOUT_UPGRADE: return this.hideoutCallbacks.upgrade(pmcData, body, sessionID, output); case HideoutEventActions.HIDEOUT_UPGRADE_COMPLETE: diff --git a/project/src/routers/item_events/InsuranceItemEventRouter.ts b/project/src/routers/item_events/InsuranceItemEventRouter.ts index 3d50e98f..2a068728 100644 --- a/project/src/routers/item_events/InsuranceItemEventRouter.ts +++ b/project/src/routers/item_events/InsuranceItemEventRouter.ts @@ -1,21 +1,18 @@ -import { inject, injectable } from "tsyringe"; import { InsuranceCallbacks } from "@spt/callbacks/InsuranceCallbacks"; import { HandledRoute, ItemEventRouterDefinition } from "@spt/di/Router"; import { IPmcData } from "@spt/models/eft/common/IPmcData"; import { IItemEventRouterResponse } from "@spt/models/eft/itemEvent/IItemEventRouterResponse"; +import { inject, injectable } from "tsyringe"; @injectable() -export class InsuranceItemEventRouter extends ItemEventRouterDefinition -{ +export class InsuranceItemEventRouter extends ItemEventRouterDefinition { constructor( @inject("InsuranceCallbacks") protected insuranceCallbacks: InsuranceCallbacks, // TODO: delay required - ) - { + ) { super(); } - public override getHandledRoutes(): HandledRoute[] - { + public override getHandledRoutes(): HandledRoute[] { return [new HandledRoute("Insure", false)]; } @@ -24,10 +21,8 @@ export class InsuranceItemEventRouter extends ItemEventRouterDefinition pmcData: IPmcData, body: any, sessionID: string, - ): Promise - { - switch (url) - { + ): Promise { + switch (url) { case "Insure": return this.insuranceCallbacks.insure(pmcData, body, sessionID); } diff --git a/project/src/routers/item_events/InventoryItemEventRouter.ts b/project/src/routers/item_events/InventoryItemEventRouter.ts index 4a86e9d1..2d34ce6b 100644 --- a/project/src/routers/item_events/InventoryItemEventRouter.ts +++ b/project/src/routers/item_events/InventoryItemEventRouter.ts @@ -1,24 +1,21 @@ -import { inject, injectable } from "tsyringe"; import { HideoutCallbacks } from "@spt/callbacks/HideoutCallbacks"; import { InventoryCallbacks } from "@spt/callbacks/InventoryCallbacks"; import { HandledRoute, ItemEventRouterDefinition } from "@spt/di/Router"; import { IPmcData } from "@spt/models/eft/common/IPmcData"; import { IItemEventRouterResponse } from "@spt/models/eft/itemEvent/IItemEventRouterResponse"; import { ItemEventActions } from "@spt/models/enums/ItemEventActions"; +import { inject, injectable } from "tsyringe"; @injectable() -export class InventoryItemEventRouter extends ItemEventRouterDefinition -{ +export class InventoryItemEventRouter extends ItemEventRouterDefinition { constructor( @inject("InventoryCallbacks") protected inventoryCallbacks: InventoryCallbacks, @inject("HideoutCallbacks") protected hideoutCallbacks: HideoutCallbacks, - ) - { + ) { super(); } - public override getHandledRoutes(): HandledRoute[] - { + public override getHandledRoutes(): HandledRoute[] { return [ new HandledRoute(ItemEventActions.MOVE, false), new HandledRoute(ItemEventActions.REMOVE, false), @@ -51,10 +48,8 @@ export class InventoryItemEventRouter extends ItemEventRouterDefinition body: any, sessionID: string, output: IItemEventRouterResponse, - ): Promise - { - switch (url) - { + ): Promise { + switch (url) { case ItemEventActions.MOVE: return this.inventoryCallbacks.moveItem(pmcData, body, sessionID, output); case ItemEventActions.REMOVE: diff --git a/project/src/routers/item_events/NoteItemEventRouter.ts b/project/src/routers/item_events/NoteItemEventRouter.ts index 98b8837b..c96d03e4 100644 --- a/project/src/routers/item_events/NoteItemEventRouter.ts +++ b/project/src/routers/item_events/NoteItemEventRouter.ts @@ -1,22 +1,19 @@ -import { inject, injectable } from "tsyringe"; import { NoteCallbacks } from "@spt/callbacks/NoteCallbacks"; import { HandledRoute, ItemEventRouterDefinition } from "@spt/di/Router"; import { IPmcData } from "@spt/models/eft/common/IPmcData"; import { IItemEventRouterResponse } from "@spt/models/eft/itemEvent/IItemEventRouterResponse"; import { INoteActionData } from "@spt/models/eft/notes/INoteActionData"; +import { inject, injectable } from "tsyringe"; @injectable() -export class NoteItemEventRouter extends ItemEventRouterDefinition -{ +export class NoteItemEventRouter extends ItemEventRouterDefinition { constructor( @inject("NoteCallbacks") protected noteCallbacks: NoteCallbacks, // TODO: delay required - ) - { + ) { super(); } - public override getHandledRoutes(): HandledRoute[] - { + public override getHandledRoutes(): HandledRoute[] { return [ new HandledRoute("AddNote", false), new HandledRoute("EditNote", false), @@ -29,10 +26,8 @@ export class NoteItemEventRouter extends ItemEventRouterDefinition pmcData: IPmcData, body: INoteActionData, sessionID: string, - ): Promise - { - switch (url) - { + ): Promise { + switch (url) { case "AddNote": return this.noteCallbacks.addNote(pmcData, body, sessionID); case "EditNote": diff --git a/project/src/routers/item_events/QuestItemEventRouter.ts b/project/src/routers/item_events/QuestItemEventRouter.ts index d50f028f..551d8cbf 100644 --- a/project/src/routers/item_events/QuestItemEventRouter.ts +++ b/project/src/routers/item_events/QuestItemEventRouter.ts @@ -1,23 +1,20 @@ -import { inject, injectable } from "tsyringe"; import { QuestCallbacks } from "@spt/callbacks/QuestCallbacks"; import { HandledRoute, ItemEventRouterDefinition } from "@spt/di/Router"; import { IPmcData } from "@spt/models/eft/common/IPmcData"; import { IItemEventRouterResponse } from "@spt/models/eft/itemEvent/IItemEventRouterResponse"; import { ILogger } from "@spt/models/spt/utils/ILogger"; +import { inject, injectable } from "tsyringe"; @injectable() -export class QuestItemEventRouter extends ItemEventRouterDefinition -{ +export class QuestItemEventRouter extends ItemEventRouterDefinition { constructor( @inject("PrimaryLogger") protected logger: ILogger, @inject("QuestCallbacks") protected questCallbacks: QuestCallbacks, - ) - { + ) { super(); } - public override getHandledRoutes(): HandledRoute[] - { + public override getHandledRoutes(): HandledRoute[] { return [ new HandledRoute("QuestAccept", false), new HandledRoute("QuestComplete", false), @@ -31,11 +28,9 @@ export class QuestItemEventRouter extends ItemEventRouterDefinition pmcData: IPmcData, body: any, sessionID: string, - ): Promise - { + ): Promise { this.logger.debug(`${eventAction} ${body.qid}`); - switch (eventAction) - { + switch (eventAction) { case "QuestAccept": return this.questCallbacks.acceptQuest(pmcData, body, sessionID); case "QuestComplete": diff --git a/project/src/routers/item_events/RagfairItemEventRouter.ts b/project/src/routers/item_events/RagfairItemEventRouter.ts index 61b16182..cb363ccd 100644 --- a/project/src/routers/item_events/RagfairItemEventRouter.ts +++ b/project/src/routers/item_events/RagfairItemEventRouter.ts @@ -1,19 +1,16 @@ -import { inject, injectable } from "tsyringe"; import { RagfairCallbacks } from "@spt/callbacks/RagfairCallbacks"; import { HandledRoute, ItemEventRouterDefinition } from "@spt/di/Router"; import { IPmcData } from "@spt/models/eft/common/IPmcData"; import { IItemEventRouterResponse } from "@spt/models/eft/itemEvent/IItemEventRouterResponse"; +import { inject, injectable } from "tsyringe"; @injectable() -export class RagfairItemEventRouter extends ItemEventRouterDefinition -{ - constructor(@inject("RagfairCallbacks") protected ragfairCallbacks: RagfairCallbacks) - { +export class RagfairItemEventRouter extends ItemEventRouterDefinition { + constructor(@inject("RagfairCallbacks") protected ragfairCallbacks: RagfairCallbacks) { super(); } - public override getHandledRoutes(): HandledRoute[] - { + public override getHandledRoutes(): HandledRoute[] { return [ new HandledRoute("RagFairAddOffer", false), new HandledRoute("RagFairRemoveOffer", false), @@ -26,10 +23,8 @@ export class RagfairItemEventRouter extends ItemEventRouterDefinition pmcData: IPmcData, body: any, sessionID: string, - ): Promise - { - switch (url) - { + ): Promise { + switch (url) { case "RagFairAddOffer": return this.ragfairCallbacks.addOffer(pmcData, body, sessionID); case "RagFairRemoveOffer": diff --git a/project/src/routers/item_events/RepairItemEventRouter.ts b/project/src/routers/item_events/RepairItemEventRouter.ts index 04a52fea..8fe17929 100644 --- a/project/src/routers/item_events/RepairItemEventRouter.ts +++ b/project/src/routers/item_events/RepairItemEventRouter.ts @@ -1,19 +1,16 @@ -import { inject, injectable } from "tsyringe"; import { RepairCallbacks } from "@spt/callbacks/RepairCallbacks"; import { HandledRoute, ItemEventRouterDefinition } from "@spt/di/Router"; import { IPmcData } from "@spt/models/eft/common/IPmcData"; import { IItemEventRouterResponse } from "@spt/models/eft/itemEvent/IItemEventRouterResponse"; +import { inject, injectable } from "tsyringe"; @injectable() -export class RepairItemEventRouter extends ItemEventRouterDefinition -{ - constructor(@inject("RepairCallbacks") protected repairCallbacks: RepairCallbacks) - { +export class RepairItemEventRouter extends ItemEventRouterDefinition { + constructor(@inject("RepairCallbacks") protected repairCallbacks: RepairCallbacks) { super(); } - public override getHandledRoutes(): HandledRoute[] - { + public override getHandledRoutes(): HandledRoute[] { return [new HandledRoute("Repair", false), new HandledRoute("TraderRepair", false)]; } @@ -22,10 +19,8 @@ export class RepairItemEventRouter extends ItemEventRouterDefinition pmcData: IPmcData, body: any, sessionID: string, - ): Promise - { - switch (url) - { + ): Promise { + switch (url) { case "Repair": return this.repairCallbacks.repair(pmcData, body, sessionID); case "TraderRepair": diff --git a/project/src/routers/item_events/TradeItemEventRouter.ts b/project/src/routers/item_events/TradeItemEventRouter.ts index edc60b29..f88fed7d 100644 --- a/project/src/routers/item_events/TradeItemEventRouter.ts +++ b/project/src/routers/item_events/TradeItemEventRouter.ts @@ -1,19 +1,16 @@ -import { inject, injectable } from "tsyringe"; import { TradeCallbacks } from "@spt/callbacks/TradeCallbacks"; import { HandledRoute, ItemEventRouterDefinition } from "@spt/di/Router"; import { IPmcData } from "@spt/models/eft/common/IPmcData"; import { IItemEventRouterResponse } from "@spt/models/eft/itemEvent/IItemEventRouterResponse"; +import { inject, injectable } from "tsyringe"; @injectable() -export class TradeItemEventRouter extends ItemEventRouterDefinition -{ - constructor(@inject("TradeCallbacks") protected tradeCallbacks: TradeCallbacks) - { +export class TradeItemEventRouter extends ItemEventRouterDefinition { + constructor(@inject("TradeCallbacks") protected tradeCallbacks: TradeCallbacks) { super(); } - public override getHandledRoutes(): HandledRoute[] - { + public override getHandledRoutes(): HandledRoute[] { return [ new HandledRoute("TradingConfirm", false), new HandledRoute("RagFairBuyOffer", false), @@ -26,10 +23,8 @@ export class TradeItemEventRouter extends ItemEventRouterDefinition pmcData: IPmcData, body: any, sessionID: string, - ): Promise - { - switch (url) - { + ): Promise { + switch (url) { case "TradingConfirm": return this.tradeCallbacks.processTrade(pmcData, body, sessionID); case "RagFairBuyOffer": diff --git a/project/src/routers/item_events/WishlistItemEventRouter.ts b/project/src/routers/item_events/WishlistItemEventRouter.ts index dfa1cd8f..14af7117 100644 --- a/project/src/routers/item_events/WishlistItemEventRouter.ts +++ b/project/src/routers/item_events/WishlistItemEventRouter.ts @@ -1,19 +1,16 @@ -import { inject, injectable } from "tsyringe"; import { WishlistCallbacks } from "@spt/callbacks/WishlistCallbacks"; import { HandledRoute, ItemEventRouterDefinition } from "@spt/di/Router"; import { IPmcData } from "@spt/models/eft/common/IPmcData"; import { IItemEventRouterResponse } from "@spt/models/eft/itemEvent/IItemEventRouterResponse"; +import { inject, injectable } from "tsyringe"; @injectable() -export class WishlistItemEventRouter extends ItemEventRouterDefinition -{ - constructor(@inject("WishlistCallbacks") protected wishlistCallbacks: WishlistCallbacks) - { +export class WishlistItemEventRouter extends ItemEventRouterDefinition { + constructor(@inject("WishlistCallbacks") protected wishlistCallbacks: WishlistCallbacks) { super(); } - public override getHandledRoutes(): HandledRoute[] - { + public override getHandledRoutes(): HandledRoute[] { return [ new HandledRoute("AddToWishList", false), new HandledRoute("RemoveFromWishList", false), @@ -26,10 +23,8 @@ export class WishlistItemEventRouter extends ItemEventRouterDefinition pmcData: IPmcData, request: any, sessionID: string, - ): Promise - { - switch (url) - { + ): Promise { + switch (url) { case "AddToWishList": return this.wishlistCallbacks.addToWishlist(pmcData, request, sessionID); case "RemoveFromWishList": diff --git a/project/src/routers/save_load/HealthSaveLoadRouter.ts b/project/src/routers/save_load/HealthSaveLoadRouter.ts index 9adb96ed..014aa215 100644 --- a/project/src/routers/save_load/HealthSaveLoadRouter.ts +++ b/project/src/routers/save_load/HealthSaveLoadRouter.ts @@ -1,19 +1,15 @@ -import { injectable } from "tsyringe"; import { HandledRoute, SaveLoadRouter } from "@spt/di/Router"; import { ISptProfile } from "@spt/models/eft/profile/ISptProfile"; +import { injectable } from "tsyringe"; @injectable() -export class HealthSaveLoadRouter extends SaveLoadRouter -{ - public override getHandledRoutes(): HandledRoute[] - { +export class HealthSaveLoadRouter extends SaveLoadRouter { + public override getHandledRoutes(): HandledRoute[] { return [new HandledRoute("spt-health", false)]; } - public override handleLoad(profile: ISptProfile): ISptProfile - { - if (!profile.vitality) - { + public override handleLoad(profile: ISptProfile): ISptProfile { + if (!profile.vitality) { // Occurs on newly created profiles profile.vitality = { health: undefined!, effects: undefined! }; } diff --git a/project/src/routers/save_load/InraidSaveLoadRouter.ts b/project/src/routers/save_load/InraidSaveLoadRouter.ts index 157d0969..fb50166f 100644 --- a/project/src/routers/save_load/InraidSaveLoadRouter.ts +++ b/project/src/routers/save_load/InraidSaveLoadRouter.ts @@ -1,19 +1,15 @@ -import { injectable } from "tsyringe"; import { HandledRoute, SaveLoadRouter } from "@spt/di/Router"; import { ISptProfile } from "@spt/models/eft/profile/ISptProfile"; +import { injectable } from "tsyringe"; @injectable() -export class InraidSaveLoadRouter extends SaveLoadRouter -{ - public override getHandledRoutes(): HandledRoute[] - { +export class InraidSaveLoadRouter extends SaveLoadRouter { + public override getHandledRoutes(): HandledRoute[] { return [new HandledRoute("spt-inraid", false)]; } - public override handleLoad(profile: ISptProfile): ISptProfile - { - if (profile.inraid === undefined) - { + public override handleLoad(profile: ISptProfile): ISptProfile { + if (profile.inraid === undefined) { profile.inraid = { location: "none", character: "none" }; } diff --git a/project/src/routers/save_load/InsuranceSaveLoadRouter.ts b/project/src/routers/save_load/InsuranceSaveLoadRouter.ts index c8976784..3917e4fc 100644 --- a/project/src/routers/save_load/InsuranceSaveLoadRouter.ts +++ b/project/src/routers/save_load/InsuranceSaveLoadRouter.ts @@ -1,19 +1,15 @@ -import { injectable } from "tsyringe"; import { HandledRoute, SaveLoadRouter } from "@spt/di/Router"; import { ISptProfile } from "@spt/models/eft/profile/ISptProfile"; +import { injectable } from "tsyringe"; @injectable() -export class InsuranceSaveLoadRouter extends SaveLoadRouter -{ - public override getHandledRoutes(): HandledRoute[] - { +export class InsuranceSaveLoadRouter extends SaveLoadRouter { + public override getHandledRoutes(): HandledRoute[] { return [new HandledRoute("spt-insurance", false)]; } - public override handleLoad(profile: ISptProfile): ISptProfile - { - if (profile.insurance === undefined) - { + public override handleLoad(profile: ISptProfile): ISptProfile { + if (profile.insurance === undefined) { profile.insurance = []; } return profile; diff --git a/project/src/routers/save_load/ProfileSaveLoadRouter.ts b/project/src/routers/save_load/ProfileSaveLoadRouter.ts index b5bdcddc..074d082b 100644 --- a/project/src/routers/save_load/ProfileSaveLoadRouter.ts +++ b/project/src/routers/save_load/ProfileSaveLoadRouter.ts @@ -1,20 +1,16 @@ -import { injectable } from "tsyringe"; import { HandledRoute, SaveLoadRouter } from "@spt/di/Router"; import { IPmcData } from "@spt/models/eft/common/IPmcData"; import { ISptProfile } from "@spt/models/eft/profile/ISptProfile"; +import { injectable } from "tsyringe"; @injectable() -export class ProfileSaveLoadRouter extends SaveLoadRouter -{ - public override getHandledRoutes(): HandledRoute[] - { +export class ProfileSaveLoadRouter extends SaveLoadRouter { + public override getHandledRoutes(): HandledRoute[] { return [new HandledRoute("spt-profile", false)]; } - public override handleLoad(profile: ISptProfile): ISptProfile - { - if (!profile.characters) - { + public override handleLoad(profile: ISptProfile): ISptProfile { + if (!profile.characters) { profile.characters = { pmc: {} as IPmcData, scav: {} as IPmcData }; } return profile; diff --git a/project/src/routers/serializers/BundleSerializer.ts b/project/src/routers/serializers/BundleSerializer.ts index dfd51dce..14e6756f 100644 --- a/project/src/routers/serializers/BundleSerializer.ts +++ b/project/src/routers/serializers/BundleSerializer.ts @@ -1,34 +1,29 @@ import { IncomingMessage, ServerResponse } from "node:http"; -import { inject, injectable } from "tsyringe"; import { Serializer } from "@spt/di/Serializer"; import { BundleLoader } from "@spt/loaders/BundleLoader"; import { ILogger } from "@spt/models/spt/utils/ILogger"; import { HttpFileUtil } from "@spt/utils/HttpFileUtil"; +import { inject, injectable } from "tsyringe"; @injectable() -export class BundleSerializer extends Serializer -{ +export class BundleSerializer extends Serializer { constructor( @inject("PrimaryLogger") protected logger: ILogger, @inject("BundleLoader") protected bundleLoader: BundleLoader, @inject("HttpFileUtil") protected httpFileUtil: HttpFileUtil, - ) - { + ) { super(); } - public override serialize(sessionID: string, req: IncomingMessage, resp: ServerResponse, body: any): void - { + public override serialize(sessionID: string, req: IncomingMessage, resp: ServerResponse, body: any): void { const key = decodeURI(req.url.split("/bundle/")[1]); const bundle = this.bundleLoader.getBundle(key); - if (!bundle) - { + if (!bundle) { return; } this.logger.info(`[BUNDLE]: ${req.url}`); - if (!bundle.modpath) - { + if (!bundle.modpath) { this.logger.error(`Mod: ${key} lacks a modPath property, skipped loading`); return; @@ -37,8 +32,7 @@ export class BundleSerializer extends Serializer this.httpFileUtil.sendFile(resp, `${bundle.modpath}/bundles/${bundle.filename}`); } - public override canHandle(route: string): boolean - { + public override canHandle(route: string): boolean { return route === "BUNDLE"; } } diff --git a/project/src/routers/serializers/ImageSerializer.ts b/project/src/routers/serializers/ImageSerializer.ts index 4ac0d611..690c15e7 100644 --- a/project/src/routers/serializers/ImageSerializer.ts +++ b/project/src/routers/serializers/ImageSerializer.ts @@ -1,23 +1,19 @@ import { IncomingMessage, ServerResponse } from "node:http"; -import { inject, injectable } from "tsyringe"; import { Serializer } from "@spt/di/Serializer"; import { ImageRouter } from "@spt/routers/ImageRouter"; +import { inject, injectable } from "tsyringe"; @injectable() -export class ImageSerializer extends Serializer -{ - constructor(@inject("ImageRouter") protected imageRouter: ImageRouter) - { +export class ImageSerializer extends Serializer { + constructor(@inject("ImageRouter") protected imageRouter: ImageRouter) { super(); } - public override serialize(sessionID: string, req: IncomingMessage, resp: ServerResponse, body: any): void - { + public override serialize(sessionID: string, req: IncomingMessage, resp: ServerResponse, body: any): void { this.imageRouter.sendImage(sessionID, req, resp, body); } - public override canHandle(route: string): boolean - { + public override canHandle(route: string): boolean { return route === "IMAGE"; } } diff --git a/project/src/routers/serializers/NotifySerializer.ts b/project/src/routers/serializers/NotifySerializer.ts index 45e30f69..b27b9d80 100644 --- a/project/src/routers/serializers/NotifySerializer.ts +++ b/project/src/routers/serializers/NotifySerializer.ts @@ -1,24 +1,21 @@ import { IncomingMessage, ServerResponse } from "node:http"; -import { inject, injectable } from "tsyringe"; import { NotifierController } from "@spt/controllers/NotifierController"; import { Serializer } from "@spt/di/Serializer"; import { HttpServerHelper } from "@spt/helpers/HttpServerHelper"; import { JsonUtil } from "@spt/utils/JsonUtil"; +import { inject, injectable } from "tsyringe"; @injectable() -export class NotifySerializer extends Serializer -{ +export class NotifySerializer extends Serializer { constructor( @inject("NotifierController") protected notifierController: NotifierController, @inject("JsonUtil") protected jsonUtil: JsonUtil, @inject("HttpServerHelper") protected httpServerHelper: HttpServerHelper, - ) - { + ) { super(); } - public override serialize(_sessionID: string, req: IncomingMessage, resp: ServerResponse, _: any): void - { + public override serialize(_sessionID: string, req: IncomingMessage, resp: ServerResponse, _: any): void { const splittedUrl = req.url.split("/"); const tmpSessionID = splittedUrl[splittedUrl.length - 1].split("?last_id")[0]; @@ -32,8 +29,7 @@ export class NotifySerializer extends Serializer .then((text) => this.httpServerHelper.sendTextJson(resp, text)); } - public override canHandle(route: string): boolean - { + public override canHandle(route: string): boolean { return route.toUpperCase() === "NOTIFY"; } } diff --git a/project/src/routers/static/AchievementStaticRouter.ts b/project/src/routers/static/AchievementStaticRouter.ts index 0f74267b..4c4f3628 100644 --- a/project/src/routers/static/AchievementStaticRouter.ts +++ b/project/src/routers/static/AchievementStaticRouter.ts @@ -1,15 +1,13 @@ -import { inject, injectable } from "tsyringe"; import { AchievementCallbacks } from "@spt/callbacks/AchievementCallbacks"; import { RouteAction, StaticRouter } from "@spt/di/Router"; import { IGetBodyResponseData } from "@spt/models/eft/httpResponse/IGetBodyResponseData"; import { ICompletedAchievementsResponse } from "@spt/models/eft/profile/ICompletedAchievementsResponse"; import { IGetAchievementsResponse } from "@spt/models/eft/profile/IGetAchievementsResponse"; +import { inject, injectable } from "tsyringe"; @injectable() -export class AchievementStaticRouter extends StaticRouter -{ - constructor(@inject("AchievementCallbacks") protected achievementCallbacks: AchievementCallbacks) - { +export class AchievementStaticRouter extends StaticRouter { + constructor(@inject("AchievementCallbacks") protected achievementCallbacks: AchievementCallbacks) { super([ new RouteAction( "/client/achievement/list", @@ -18,8 +16,7 @@ export class AchievementStaticRouter extends StaticRouter info: any, sessionID: string, output: string, - ): Promise> => - { + ): Promise> => { return this.achievementCallbacks.getAchievements(url, info, sessionID); }, ), @@ -31,8 +28,7 @@ export class AchievementStaticRouter extends StaticRouter info: any, sessionID: string, output: string, - ): Promise> => - { + ): Promise> => { return this.achievementCallbacks.statistic(url, info, sessionID); }, ), diff --git a/project/src/routers/static/BotStaticRouter.ts b/project/src/routers/static/BotStaticRouter.ts index 96241942..055bb2e7 100644 --- a/project/src/routers/static/BotStaticRouter.ts +++ b/project/src/routers/static/BotStaticRouter.ts @@ -1,14 +1,12 @@ -import { inject, injectable } from "tsyringe"; import { BotCallbacks } from "@spt/callbacks/BotCallbacks"; import { RouteAction, StaticRouter } from "@spt/di/Router"; import { IBotBase } from "@spt/models/eft/common/tables/IBotBase"; import { IGetBodyResponseData } from "@spt/models/eft/httpResponse/IGetBodyResponseData"; +import { inject, injectable } from "tsyringe"; @injectable() -export class BotStaticRouter extends StaticRouter -{ - constructor(@inject("BotCallbacks") protected botCallbacks: BotCallbacks) - { +export class BotStaticRouter extends StaticRouter { + constructor(@inject("BotCallbacks") protected botCallbacks: BotCallbacks) { super([ new RouteAction( "/client/game/bot/generate", @@ -17,8 +15,7 @@ export class BotStaticRouter extends StaticRouter info: any, sessionID: string, output: string, - ): Promise> => - { + ): Promise> => { return this.botCallbacks.generateBots(url, info, sessionID); }, ), diff --git a/project/src/routers/static/BuildStaticRouter.ts b/project/src/routers/static/BuildStaticRouter.ts index eea5619c..fd404fd2 100644 --- a/project/src/routers/static/BuildStaticRouter.ts +++ b/project/src/routers/static/BuildStaticRouter.ts @@ -1,15 +1,13 @@ -import { inject, injectable } from "tsyringe"; import { BuildsCallbacks } from "@spt/callbacks/BuildsCallbacks"; import { RouteAction, StaticRouter } from "@spt/di/Router"; import { IGetBodyResponseData } from "@spt/models/eft/httpResponse/IGetBodyResponseData"; import { INullResponseData } from "@spt/models/eft/httpResponse/INullResponseData"; import { IUserBuilds } from "@spt/models/eft/profile/ISptProfile"; +import { inject, injectable } from "tsyringe"; @injectable() -export class BuildsStaticRouter extends StaticRouter -{ - constructor(@inject("BuildsCallbacks") protected buildsCallbacks: BuildsCallbacks) - { +export class BuildsStaticRouter extends StaticRouter { + constructor(@inject("BuildsCallbacks") protected buildsCallbacks: BuildsCallbacks) { super([ new RouteAction( "/client/builds/list", @@ -18,36 +16,31 @@ export class BuildsStaticRouter extends StaticRouter info: any, sessionID: string, output: string, - ): Promise> => - { + ): Promise> => { return this.buildsCallbacks.getBuilds(url, info, sessionID); }, ), new RouteAction( "/client/builds/magazine/save", - async (url: string, info: any, sessionID: string, output: string): Promise => - { + async (url: string, info: any, sessionID: string, output: string): Promise => { return this.buildsCallbacks.createMagazineTemplate(url, info, sessionID); }, ), new RouteAction( "/client/builds/weapon/save", - async (url: string, info: any, sessionID: string, output: string): Promise => - { + async (url: string, info: any, sessionID: string, output: string): Promise => { return this.buildsCallbacks.setWeapon(url, info, sessionID); }, ), new RouteAction( "/client/builds/equipment/save", - async (url: string, info: any, sessionID: string, output: string): Promise => - { + async (url: string, info: any, sessionID: string, output: string): Promise => { return this.buildsCallbacks.setEquipment(url, info, sessionID); }, ), new RouteAction( "/client/builds/delete", - async (url: string, info: any, sessionID: string, output: string): Promise => - { + async (url: string, info: any, sessionID: string, output: string): Promise => { return this.buildsCallbacks.deleteBuild(url, info, sessionID); }, ), diff --git a/project/src/routers/static/BundleStaticRouter.ts b/project/src/routers/static/BundleStaticRouter.ts index 72181d38..5ffab5d2 100644 --- a/project/src/routers/static/BundleStaticRouter.ts +++ b/project/src/routers/static/BundleStaticRouter.ts @@ -1,17 +1,14 @@ -import { inject, injectable } from "tsyringe"; import { BundleCallbacks } from "@spt/callbacks/BundleCallbacks"; import { RouteAction, StaticRouter } from "@spt/di/Router"; +import { inject, injectable } from "tsyringe"; @injectable() -export class BundleStaticRouter extends StaticRouter -{ - constructor(@inject("BundleCallbacks") protected bundleCallbacks: BundleCallbacks) - { +export class BundleStaticRouter extends StaticRouter { + constructor(@inject("BundleCallbacks") protected bundleCallbacks: BundleCallbacks) { super([ new RouteAction( "/singleplayer/bundles", - async (url: string, info: any, sessionID: string, output: string): Promise => - { + async (url: string, info: any, sessionID: string, output: string): Promise => { return this.bundleCallbacks.getBundles(url, info, sessionID); }, ), diff --git a/project/src/routers/static/ClientLogStaticRouter.ts b/project/src/routers/static/ClientLogStaticRouter.ts index c1ee0ef3..a1696c95 100644 --- a/project/src/routers/static/ClientLogStaticRouter.ts +++ b/project/src/routers/static/ClientLogStaticRouter.ts @@ -1,32 +1,27 @@ -import { inject, injectable } from "tsyringe"; import { ClientLogCallbacks } from "@spt/callbacks/ClientLogCallbacks"; import { RouteAction, StaticRouter } from "@spt/di/Router"; import { INullResponseData } from "@spt/models/eft/httpResponse/INullResponseData"; +import { inject, injectable } from "tsyringe"; @injectable() -export class ClientLogStaticRouter extends StaticRouter -{ - constructor(@inject("ClientLogCallbacks") protected clientLogCallbacks: ClientLogCallbacks) - { +export class ClientLogStaticRouter extends StaticRouter { + constructor(@inject("ClientLogCallbacks") protected clientLogCallbacks: ClientLogCallbacks) { super([ new RouteAction( "/singleplayer/log", - async (url: string, info: any, sessionID: string, output: string): Promise => - { + async (url: string, info: any, sessionID: string, output: string): Promise => { return this.clientLogCallbacks.clientLog(url, info, sessionID); }, ), new RouteAction( "/singleplayer/release", - async (url: string, info: any, sessionID: string, output: string): Promise => - { + async (url: string, info: any, sessionID: string, output: string): Promise => { return this.clientLogCallbacks.releaseNotes(); }, ), new RouteAction( "/singleplayer/enableBSGlogging", - async (url: string, info: any, sessionID: string, output: string): Promise => - { + async (url: string, info: any, sessionID: string, output: string): Promise => { return this.clientLogCallbacks.bsgLogging(); }, ), diff --git a/project/src/routers/static/CustomizationStaticRouter.ts b/project/src/routers/static/CustomizationStaticRouter.ts index 1cefed52..a47685bb 100644 --- a/project/src/routers/static/CustomizationStaticRouter.ts +++ b/project/src/routers/static/CustomizationStaticRouter.ts @@ -1,14 +1,12 @@ -import { inject, injectable } from "tsyringe"; import { CustomizationCallbacks } from "@spt/callbacks/CustomizationCallbacks"; import { RouteAction, StaticRouter } from "@spt/di/Router"; import { IGetSuitsResponse } from "@spt/models/eft/customization/IGetSuitsResponse"; import { IGetBodyResponseData } from "@spt/models/eft/httpResponse/IGetBodyResponseData"; +import { inject, injectable } from "tsyringe"; @injectable() -export class CustomizationStaticRouter extends StaticRouter -{ - constructor(@inject("CustomizationCallbacks") protected customizationCallbacks: CustomizationCallbacks) - { +export class CustomizationStaticRouter extends StaticRouter { + constructor(@inject("CustomizationCallbacks") protected customizationCallbacks: CustomizationCallbacks) { super([ new RouteAction( "/client/trading/customization/storage", @@ -17,8 +15,7 @@ export class CustomizationStaticRouter extends StaticRouter info: any, sessionID: string, output: string, - ): Promise> => - { + ): Promise> => { return this.customizationCallbacks.getSuits(url, info, sessionID); }, ), diff --git a/project/src/routers/static/DataStaticRouter.ts b/project/src/routers/static/DataStaticRouter.ts index e6e6ed87..8b3eece2 100644 --- a/project/src/routers/static/DataStaticRouter.ts +++ b/project/src/routers/static/DataStaticRouter.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { DataCallbacks } from "@spt/callbacks/DataCallbacks"; import { RouteAction, StaticRouter } from "@spt/di/Router"; import { IGlobals } from "@spt/models/eft/common/IGlobals"; @@ -10,12 +9,11 @@ import { IHideoutScavCase } from "@spt/models/eft/hideout/IHideoutScavCase"; import { IHideoutSettingsBase } from "@spt/models/eft/hideout/IHideoutSettingsBase"; import { IGetBodyResponseData } from "@spt/models/eft/httpResponse/IGetBodyResponseData"; import { ISettingsBase } from "@spt/models/spt/server/ISettingsBase"; +import { inject, injectable } from "tsyringe"; @injectable() -export class DataStaticRouter extends StaticRouter -{ - constructor(@inject("DataCallbacks") protected dataCallbacks: DataCallbacks) - { +export class DataStaticRouter extends StaticRouter { + constructor(@inject("DataCallbacks") protected dataCallbacks: DataCallbacks) { super([ new RouteAction( "/client/settings", @@ -24,8 +22,7 @@ export class DataStaticRouter extends StaticRouter info: any, sessionID: string, output: string, - ): Promise> => - { + ): Promise> => { return this.dataCallbacks.getSettings(url, info, sessionID); }, ), @@ -36,15 +33,13 @@ export class DataStaticRouter extends StaticRouter info: any, sessionID: string, output: string, - ): Promise> => - { + ): Promise> => { return this.dataCallbacks.getGlobals(url, info, sessionID); }, ), new RouteAction( "/client/items", - async (url: string, info: any, sessionID: string, output: string): Promise => - { + async (url: string, info: any, sessionID: string, output: string): Promise => { return this.dataCallbacks.getTemplateItems(url, info, sessionID); }, ), @@ -55,8 +50,7 @@ export class DataStaticRouter extends StaticRouter info: any, sessionID: string, output: string, - ): Promise> => - { + ): Promise> => { return this.dataCallbacks.getTemplateHandbook(url, info, sessionID); }, ), @@ -67,8 +61,7 @@ export class DataStaticRouter extends StaticRouter info: any, sessionID: string, output: string, - ): Promise>> => - { + ): Promise>> => { return this.dataCallbacks.getTemplateSuits(url, info, sessionID); }, ), @@ -79,8 +72,7 @@ export class DataStaticRouter extends StaticRouter info: any, sessionID: string, output: string, - ): Promise> => - { + ): Promise> => { return this.dataCallbacks.getTemplateCharacter(url, info, sessionID); }, ), @@ -91,8 +83,7 @@ export class DataStaticRouter extends StaticRouter info: any, sessionID: string, output: string, - ): Promise> => - { + ): Promise> => { return this.dataCallbacks.gethideoutProduction(url, info, sessionID); }, ), @@ -103,8 +94,7 @@ export class DataStaticRouter extends StaticRouter info: any, sessionID: string, output: string, - ): Promise> => - { + ): Promise> => { return this.dataCallbacks.getHideoutSettings(url, info, sessionID); }, ), @@ -115,8 +105,7 @@ export class DataStaticRouter extends StaticRouter info: any, sessionID: string, output: string, - ): Promise> => - { + ): Promise> => { return this.dataCallbacks.getHideoutAreas(url, info, sessionID); }, ), @@ -127,8 +116,7 @@ export class DataStaticRouter extends StaticRouter info: any, sessionID: string, output: string, - ): Promise> => - { + ): Promise> => { return this.dataCallbacks.getHideoutScavcase(url, info, sessionID); }, ), @@ -139,15 +127,13 @@ export class DataStaticRouter extends StaticRouter info: any, sessionID: string, output: string, - ): Promise>> => - { + ): Promise>> => { return this.dataCallbacks.getLocalesLanguages(url, info, sessionID); }, ), new RouteAction( "/client/hideout/qte/list", - async (url: string, info: any, sessionID: string, output: string): Promise => - { + async (url: string, info: any, sessionID: string, output: string): Promise => { return this.dataCallbacks.getQteList(url, info, sessionID); }, ), diff --git a/project/src/routers/static/DialogStaticRouter.ts b/project/src/routers/static/DialogStaticRouter.ts index bf2a309f..1578287d 100644 --- a/project/src/routers/static/DialogStaticRouter.ts +++ b/project/src/routers/static/DialogStaticRouter.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { DialogueCallbacks } from "@spt/callbacks/DialogueCallbacks"; import { RouteAction, StaticRouter } from "@spt/di/Router"; import { IAddUserGroupMailRequest } from "@spt/models/eft/dialog/IAddUserGroupMailRequest"; @@ -13,12 +12,11 @@ import { IRemoveUserGroupMailRequest } from "@spt/models/eft/dialog/IRemoveUserG import { IGetBodyResponseData } from "@spt/models/eft/httpResponse/IGetBodyResponseData"; import { INullResponseData } from "@spt/models/eft/httpResponse/INullResponseData"; import { DialogueInfo } from "@spt/models/eft/profile/ISptProfile"; +import { inject, injectable } from "tsyringe"; @injectable() -export class DialogStaticRouter extends StaticRouter -{ - constructor(@inject("DialogueCallbacks") protected dialogueCallbacks: DialogueCallbacks) - { +export class DialogStaticRouter extends StaticRouter { + constructor(@inject("DialogueCallbacks") protected dialogueCallbacks: DialogueCallbacks) { super([ new RouteAction( "/client/chatServer/list", @@ -27,8 +25,7 @@ export class DialogStaticRouter extends StaticRouter info: any, sessionID: string, output: string, - ): Promise> => - { + ): Promise> => { return this.dialogueCallbacks.getChatServerList(url, info, sessionID); }, ), @@ -39,8 +36,7 @@ export class DialogStaticRouter extends StaticRouter info: any, sessionID: string, output: string, - ): Promise> => - { + ): Promise> => { return this.dialogueCallbacks.getMailDialogList(url, info, sessionID); }, ), @@ -51,8 +47,7 @@ export class DialogStaticRouter extends StaticRouter info: any, sessionID: string, output: string, - ): Promise> => - { + ): Promise> => { return this.dialogueCallbacks.getMailDialogView(url, info, sessionID); }, ), @@ -63,8 +58,7 @@ export class DialogStaticRouter extends StaticRouter info: any, sessionID: string, output: string, - ): Promise> => - { + ): Promise> => { return this.dialogueCallbacks.getMailDialogInfo(url, info, sessionID); }, ), @@ -75,8 +69,7 @@ export class DialogStaticRouter extends StaticRouter info: any, sessionID: string, output: string, - ): Promise> => - { + ): Promise> => { return this.dialogueCallbacks.removeDialog(url, info, sessionID); }, ), @@ -87,8 +80,7 @@ export class DialogStaticRouter extends StaticRouter info: any, sessionID: string, output: string, - ): Promise> => - { + ): Promise> => { return this.dialogueCallbacks.pinDialog(url, info, sessionID); }, ), @@ -99,8 +91,7 @@ export class DialogStaticRouter extends StaticRouter info: any, sessionID: string, output: string, - ): Promise> => - { + ): Promise> => { return this.dialogueCallbacks.unpinDialog(url, info, sessionID); }, ), @@ -111,8 +102,7 @@ export class DialogStaticRouter extends StaticRouter info: any, sessionID: string, output: string, - ): Promise> => - { + ): Promise> => { return this.dialogueCallbacks.setRead(url, info, sessionID); }, ), @@ -123,8 +113,7 @@ export class DialogStaticRouter extends StaticRouter info: any, sessionID: string, output: string, - ): Promise> => - { + ): Promise> => { return this.dialogueCallbacks.removeMail(url, info, sessionID); }, ), @@ -135,8 +124,7 @@ export class DialogStaticRouter extends StaticRouter info: any, sessionID: string, output: string, - ): Promise> => - { + ): Promise> => { return this.dialogueCallbacks.getAllAttachments(url, info, sessionID); }, ), @@ -147,8 +135,7 @@ export class DialogStaticRouter extends StaticRouter info: any, sessionID: string, output: string, - ): Promise> => - { + ): Promise> => { return this.dialogueCallbacks.sendMessage(url, info, sessionID); }, ), @@ -159,8 +146,7 @@ export class DialogStaticRouter extends StaticRouter info: any, sessionID: string, output: string, - ): Promise> => - { + ): Promise> => { return this.dialogueCallbacks.clearMail(url, info, sessionID); }, ), @@ -171,8 +157,7 @@ export class DialogStaticRouter extends StaticRouter info: ICreateGroupMailRequest, sessionID: string, output: string, - ): Promise> => - { + ): Promise> => { return this.dialogueCallbacks.createGroupMail(url, info, sessionID); }, ), @@ -183,8 +168,7 @@ export class DialogStaticRouter extends StaticRouter info: IChangeGroupMailOwnerRequest, sessionID: string, output: string, - ): Promise> => - { + ): Promise> => { return this.dialogueCallbacks.changeMailGroupOwner(url, info, sessionID); }, ), @@ -195,8 +179,7 @@ export class DialogStaticRouter extends StaticRouter info: IAddUserGroupMailRequest, sessionID: string, output: string, - ): Promise> => - { + ): Promise> => { return this.dialogueCallbacks.addUserToMail(url, info, sessionID); }, ), @@ -207,8 +190,7 @@ export class DialogStaticRouter extends StaticRouter info: IRemoveUserGroupMailRequest, sessionID: string, output: string, - ): Promise> => - { + ): Promise> => { return this.dialogueCallbacks.removeUserFromMail(url, info, sessionID); }, ), @@ -219,8 +201,7 @@ export class DialogStaticRouter extends StaticRouter info: any, sessionID: string, output: string, - ): Promise> => - { + ): Promise> => { return this.dialogueCallbacks.getFriendList(url, info, sessionID); }, ), @@ -231,8 +212,7 @@ export class DialogStaticRouter extends StaticRouter info: any, sessionID: string, output: string, - ): Promise> => - { + ): Promise> => { return this.dialogueCallbacks.listOutbox(url, info, sessionID); }, ), @@ -243,8 +223,7 @@ export class DialogStaticRouter extends StaticRouter info: any, sessionID: string, output: string, - ): Promise> => - { + ): Promise> => { return this.dialogueCallbacks.listInbox(url, info, sessionID); }, ), @@ -255,15 +234,13 @@ export class DialogStaticRouter extends StaticRouter info: any, sessionID: string, output: string, - ): Promise> => - { + ): Promise> => { return this.dialogueCallbacks.sendFriendRequest(url, info, sessionID); }, ), new RouteAction( "/client/friend/request/accept-all", - (url: string, info: any, sessionID: string, output: string): any => - { + (url: string, info: any, sessionID: string, output: string): any => { return this.dialogueCallbacks.acceptAllFriendRequests(url, info, sessionID); }, ), @@ -274,15 +251,13 @@ export class DialogStaticRouter extends StaticRouter info: any, sessionID: string, output: string, - ): Promise> => - { + ): Promise> => { return this.dialogueCallbacks.acceptFriendRequest(url, info, sessionID); }, ), new RouteAction( "/client/friend/request/decline", - (url: string, info: any, sessionID: string, output: string): any => - { + (url: string, info: any, sessionID: string, output: string): any => { return this.dialogueCallbacks.declineFriendRequest(url, info, sessionID); }, ), @@ -293,29 +268,25 @@ export class DialogStaticRouter extends StaticRouter info: any, sessionID: string, output: string, - ): Promise> => - { + ): Promise> => { return this.dialogueCallbacks.cancelFriendRequest(url, info, sessionID); }, ), new RouteAction( "/client/friend/delete", - async (url: string, info: any, sessionID: string, output: string): Promise => - { + async (url: string, info: any, sessionID: string, output: string): Promise => { return this.dialogueCallbacks.deleteFriend(url, info, sessionID); }, ), new RouteAction( "/client/friend/ignore/set", - async (url: string, info: any, sessionID: string, output: string): Promise => - { + async (url: string, info: any, sessionID: string, output: string): Promise => { return this.dialogueCallbacks.ignoreFriend(url, info, sessionID); }, ), new RouteAction( "/client/friend/ignore/remove", - async (url: string, info: any, sessionID: string, output: string): Promise => - { + async (url: string, info: any, sessionID: string, output: string): Promise => { return this.dialogueCallbacks.unIgnoreFriend(url, info, sessionID); }, ), diff --git a/project/src/routers/static/GameStaticRouter.ts b/project/src/routers/static/GameStaticRouter.ts index 4020bccc..9facd699 100644 --- a/project/src/routers/static/GameStaticRouter.ts +++ b/project/src/routers/static/GameStaticRouter.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { GameCallbacks } from "@spt/callbacks/GameCallbacks"; import { RouteAction, StaticRouter } from "@spt/di/Router"; import { ICheckVersionResponse } from "@spt/models/eft/game/ICheckVersionResponse"; @@ -14,15 +13,14 @@ import { IServerDetails } from "@spt/models/eft/game/IServerDetails"; import { IGetBodyResponseData } from "@spt/models/eft/httpResponse/IGetBodyResponseData"; import { INullResponseData } from "@spt/models/eft/httpResponse/INullResponseData"; import { HttpResponseUtil } from "@spt/utils/HttpResponseUtil"; +import { inject, injectable } from "tsyringe"; @injectable() -export class GameStaticRouter extends StaticRouter -{ +export class GameStaticRouter extends StaticRouter { constructor( @inject("HttpResponseUtil") protected httpResponse: HttpResponseUtil, - @inject("GameCallbacks") protected gameCallbacks: GameCallbacks - ) - { + @inject("GameCallbacks") protected gameCallbacks: GameCallbacks, + ) { super([ new RouteAction( "/client/game/config", @@ -31,8 +29,7 @@ export class GameStaticRouter extends StaticRouter info: any, sessionID: string, output: string, - ): Promise> => - { + ): Promise> => { return this.gameCallbacks.getGameConfig(url, info, sessionID); }, ), @@ -43,8 +40,7 @@ export class GameStaticRouter extends StaticRouter info: any, sessionID: string, output: string, - ): Promise> => - { + ): Promise> => { return this.gameCallbacks.getGameMode(url, info, sessionID); }, ), @@ -55,8 +51,7 @@ export class GameStaticRouter extends StaticRouter info: any, sessionID: string, output: string, - ): Promise> => - { + ): Promise> => { return this.gameCallbacks.getServer(url, info, sessionID); }, ), @@ -67,15 +62,13 @@ export class GameStaticRouter extends StaticRouter info: any, sessionID: string, output: string, - ): Promise> => - { + ): Promise> => { return this.gameCallbacks.getCurrentGroup(url, info, sessionID); }, ), new RouteAction( "/client/game/version/validate", - async (url: string, info: any, sessionID: string, output: string): Promise => - { + async (url: string, info: any, sessionID: string, output: string): Promise => { return this.gameCallbacks.versionValidate(url, info, sessionID); }, ), @@ -86,8 +79,7 @@ export class GameStaticRouter extends StaticRouter info: any, sessionID: string, output: string, - ): Promise> => - { + ): Promise> => { return this.gameCallbacks.gameStart(url, info, sessionID); }, ), @@ -98,8 +90,7 @@ export class GameStaticRouter extends StaticRouter info: any, sessionID: string, output: string, - ): Promise> => - { + ): Promise> => { return this.gameCallbacks.gameLogout(url, info, sessionID); }, ), @@ -110,8 +101,7 @@ export class GameStaticRouter extends StaticRouter info: any, sessionID: string, output: string, - ): Promise> => - { + ): Promise> => { return this.gameCallbacks.validateGameVersion(url, info, sessionID); }, ), @@ -122,22 +112,19 @@ export class GameStaticRouter extends StaticRouter info: any, sessionID: string, output: string, - ): Promise> => - { + ): Promise> => { return this.gameCallbacks.gameKeepalive(url, info, sessionID); }, ), new RouteAction( "/singleplayer/settings/version", - async (url: string, info: any, sessionID: string, output: string): Promise => - { + async (url: string, info: any, sessionID: string, output: string): Promise => { return this.gameCallbacks.getVersion(url, info, sessionID); }, ), new RouteAction( "/client/reports/lobby/send", - async (url: string, info: any, sessionID: string, output: string): Promise => - { + async (url: string, info: any, sessionID: string, output: string): Promise => { return this.gameCallbacks.reportNickname(url, info, sessionID); }, ), @@ -148,25 +135,22 @@ export class GameStaticRouter extends StaticRouter info: ISendReportRequest, sessionID: string, output: string, - ): Promise => - { + ): Promise => { return this.gameCallbacks.reportNickname(url, info, sessionID); }, ), new RouteAction( "/singleplayer/settings/getRaidTime", - async (url: string, info: any, sessionID: string, output: string): Promise => - { + async (url: string, info: any, sessionID: string, output: string): Promise => { return this.gameCallbacks.getRaidTime(url, info, sessionID); }, ), new RouteAction( "/client/survey", - async (url: string, info: any, sessionID: string, output: string): Promise => - { + async (url: string, info: any, sessionID: string, output: string): Promise => { return this.gameCallbacks.getSurvey(url, info, sessionID); }, - ) + ), ]); } } diff --git a/project/src/routers/static/HealthStaticRouter.ts b/project/src/routers/static/HealthStaticRouter.ts index 29133267..9294c491 100644 --- a/project/src/routers/static/HealthStaticRouter.ts +++ b/project/src/routers/static/HealthStaticRouter.ts @@ -1,13 +1,11 @@ -import { inject, injectable } from "tsyringe"; import { HealthCallbacks } from "@spt/callbacks/HealthCallbacks"; import { RouteAction, StaticRouter } from "@spt/di/Router"; import { IGetBodyResponseData } from "@spt/models/eft/httpResponse/IGetBodyResponseData"; +import { inject, injectable } from "tsyringe"; @injectable() -export class HealthStaticRouter extends StaticRouter -{ - constructor(@inject("HealthCallbacks") protected healthCallbacks: HealthCallbacks) - { +export class HealthStaticRouter extends StaticRouter { + constructor(@inject("HealthCallbacks") protected healthCallbacks: HealthCallbacks) { super([ new RouteAction( "/player/health/sync", @@ -16,8 +14,7 @@ export class HealthStaticRouter extends StaticRouter info: any, sessionID: string, output: string, - ): Promise> => - { + ): Promise> => { return this.healthCallbacks.syncHealth(url, info, sessionID); }, ), @@ -28,8 +25,7 @@ export class HealthStaticRouter extends StaticRouter info: any, sessionID: string, output: string, - ): Promise> => - { + ): Promise> => { return this.healthCallbacks.handleWorkoutEffects(url, info, sessionID); }, ), diff --git a/project/src/routers/static/InraidStaticRouter.ts b/project/src/routers/static/InraidStaticRouter.ts index 71c76b89..58bae352 100644 --- a/project/src/routers/static/InraidStaticRouter.ts +++ b/project/src/routers/static/InraidStaticRouter.ts @@ -1,46 +1,39 @@ -import { inject, injectable } from "tsyringe"; import { InraidCallbacks } from "@spt/callbacks/InraidCallbacks"; import { RouteAction, StaticRouter } from "@spt/di/Router"; import { INullResponseData } from "@spt/models/eft/httpResponse/INullResponseData"; +import { inject, injectable } from "tsyringe"; @injectable() -export class InraidStaticRouter extends StaticRouter -{ - constructor(@inject("InraidCallbacks") protected inraidCallbacks: InraidCallbacks) - { +export class InraidStaticRouter extends StaticRouter { + constructor(@inject("InraidCallbacks") protected inraidCallbacks: InraidCallbacks) { super([ new RouteAction( "/raid/profile/scavsave", - async (url: string, info: any, sessionID: string, output: string): Promise => - { + async (url: string, info: any, sessionID: string, output: string): Promise => { return this.inraidCallbacks.saveProgress(url, info, sessionID); }, ), new RouteAction( "/singleplayer/settings/raid/endstate", - async (url: string, info: any, sessionID: string, output: string): Promise => - { + async (url: string, info: any, sessionID: string, output: string): Promise => { return this.inraidCallbacks.getRaidEndState(); }, ), new RouteAction( "/singleplayer/settings/raid/menu", - async (url: string, info: any, sessionID: string, output: string): Promise => - { + async (url: string, info: any, sessionID: string, output: string): Promise => { return this.inraidCallbacks.getRaidMenuSettings(); }, ), new RouteAction( "/singleplayer/scav/traitorscavhostile", - async (url: string, info: any, sessionID: string, output: string): Promise => - { + async (url: string, info: any, sessionID: string, output: string): Promise => { return this.inraidCallbacks.getTraitorScavHostileChance(url, info, sessionID); }, ), new RouteAction( "/singleplayer/bossconvert", - async (url: string, info: any, sessionID: string, output: string): Promise => - { + async (url: string, info: any, sessionID: string, output: string): Promise => { return this.inraidCallbacks.getBossConvertSettings(url, info, sessionID); }, ), diff --git a/project/src/routers/static/InsuranceStaticRouter.ts b/project/src/routers/static/InsuranceStaticRouter.ts index a0fdba05..42d9539f 100644 --- a/project/src/routers/static/InsuranceStaticRouter.ts +++ b/project/src/routers/static/InsuranceStaticRouter.ts @@ -1,14 +1,12 @@ -import { inject, injectable } from "tsyringe"; import { InsuranceCallbacks } from "@spt/callbacks/InsuranceCallbacks"; import { RouteAction, StaticRouter } from "@spt/di/Router"; import { IGetBodyResponseData } from "@spt/models/eft/httpResponse/IGetBodyResponseData"; import { IGetInsuranceCostResponseData } from "@spt/models/eft/insurance/IGetInsuranceCostResponseData"; +import { inject, injectable } from "tsyringe"; @injectable() -export class InsuranceStaticRouter extends StaticRouter -{ - constructor(@inject("InsuranceCallbacks") protected insuranceCallbacks: InsuranceCallbacks) - { +export class InsuranceStaticRouter extends StaticRouter { + constructor(@inject("InsuranceCallbacks") protected insuranceCallbacks: InsuranceCallbacks) { super([ new RouteAction( "/client/insurance/items/list/cost", @@ -17,8 +15,7 @@ export class InsuranceStaticRouter extends StaticRouter info: any, sessionID: string, output: string, - ): Promise> => - { + ): Promise> => { return this.insuranceCallbacks.getInsuranceCost(url, info, sessionID); }, ), diff --git a/project/src/routers/static/ItemEventStaticRouter.ts b/project/src/routers/static/ItemEventStaticRouter.ts index 18a4ff79..7e846322 100644 --- a/project/src/routers/static/ItemEventStaticRouter.ts +++ b/project/src/routers/static/ItemEventStaticRouter.ts @@ -1,14 +1,12 @@ -import { inject, injectable } from "tsyringe"; import { ItemEventCallbacks } from "@spt/callbacks/ItemEventCallbacks"; import { RouteAction, StaticRouter } from "@spt/di/Router"; import { IGetBodyResponseData } from "@spt/models/eft/httpResponse/IGetBodyResponseData"; import { IItemEventRouterResponse } from "@spt/models/eft/itemEvent/IItemEventRouterResponse"; +import { inject, injectable } from "tsyringe"; @injectable() -export class ItemEventStaticRouter extends StaticRouter -{ - constructor(@inject("ItemEventCallbacks") protected itemEventCallbacks: ItemEventCallbacks) - { +export class ItemEventStaticRouter extends StaticRouter { + constructor(@inject("ItemEventCallbacks") protected itemEventCallbacks: ItemEventCallbacks) { super([ new RouteAction( "/client/game/profile/items/moving", @@ -17,8 +15,7 @@ export class ItemEventStaticRouter extends StaticRouter info: any, sessionID: string, output: string, - ): Promise> => - { + ): Promise> => { return this.itemEventCallbacks.handleEvents(url, info, sessionID); }, ), diff --git a/project/src/routers/static/LauncherStaticRouter.ts b/project/src/routers/static/LauncherStaticRouter.ts index 37f691da..5c9997ee 100644 --- a/project/src/routers/static/LauncherStaticRouter.ts +++ b/project/src/routers/static/LauncherStaticRouter.ts @@ -1,101 +1,86 @@ -import { inject, injectable } from "tsyringe"; import { LauncherCallbacks } from "@spt/callbacks/LauncherCallbacks"; import { RouteAction, StaticRouter } from "@spt/di/Router"; +import { inject, injectable } from "tsyringe"; @injectable() -export class LauncherStaticRouter extends StaticRouter -{ - constructor(@inject("LauncherCallbacks") protected launcherCallbacks: LauncherCallbacks) - { +export class LauncherStaticRouter extends StaticRouter { + constructor(@inject("LauncherCallbacks") protected launcherCallbacks: LauncherCallbacks) { super([ new RouteAction( "/launcher/ping", - async (url: string, info: any, sessionID: string, output: string): Promise => - { + async (url: string, info: any, sessionID: string, output: string): Promise => { return this.launcherCallbacks.ping(url, info, sessionID); }, ), new RouteAction( "/launcher/server/connect", - async (url: string, info: any, sessionID: string, output: string): Promise => - { + async (url: string, info: any, sessionID: string, output: string): Promise => { return this.launcherCallbacks.connect(); }, ), new RouteAction( "/launcher/profile/login", - async (url: string, info: any, sessionID: string, output: string): Promise => - { + async (url: string, info: any, sessionID: string, output: string): Promise => { return this.launcherCallbacks.login(url, info, sessionID); }, ), new RouteAction( "/launcher/profile/register", - async (url: string, info: any, sessionID: string, output: string): Promise => - { + async (url: string, info: any, sessionID: string, output: string): Promise => { return this.launcherCallbacks.register(url, info, sessionID); }, ), new RouteAction( "/launcher/profile/get", - async (url: string, info: any, sessionID: string, output: string): Promise => - { + async (url: string, info: any, sessionID: string, output: string): Promise => { return this.launcherCallbacks.get(url, info, sessionID); }, ), new RouteAction( "/launcher/profile/change/username", - async (url: string, info: any, sessionID: string, output: string): Promise => - { + async (url: string, info: any, sessionID: string, output: string): Promise => { return this.launcherCallbacks.changeUsername(url, info, sessionID); }, ), new RouteAction( "/launcher/profile/change/password", - async (url: string, info: any, sessionID: string, output: string): Promise => - { + async (url: string, info: any, sessionID: string, output: string): Promise => { return this.launcherCallbacks.changePassword(url, info, sessionID); }, ), new RouteAction( "/launcher/profile/change/wipe", - async (url: string, info: any, sessionID: string, output: string): Promise => - { + async (url: string, info: any, sessionID: string, output: string): Promise => { return this.launcherCallbacks.wipe(url, info, sessionID); }, ), new RouteAction( "/launcher/profile/remove", - async (url: string, info: any, sessionID: string, output: string): Promise => - { + async (url: string, info: any, sessionID: string, output: string): Promise => { return this.launcherCallbacks.removeProfile(url, info, sessionID); }, ), new RouteAction( "/launcher/profile/compatibleTarkovVersion", - async (url: string, info: any, sessionID: string, output: string): Promise => - { + async (url: string, info: any, sessionID: string, output: string): Promise => { return this.launcherCallbacks.getCompatibleTarkovVersion(); }, ), new RouteAction( "/launcher/server/version", - async (url: string, info: any, sessionID: string, output: string): Promise => - { + async (url: string, info: any, sessionID: string, output: string): Promise => { return this.launcherCallbacks.getServerVersion(); }, ), new RouteAction( "/launcher/server/loadedServerMods", - async (url: string, info: any, sessionID: string, output: string): Promise => - { + async (url: string, info: any, sessionID: string, output: string): Promise => { return this.launcherCallbacks.getLoadedServerMods(); }, ), new RouteAction( "/launcher/server/serverModsUsedByProfile", - async (url: string, info: any, sessionID: string, output: string): Promise => - { + async (url: string, info: any, sessionID: string, output: string): Promise => { return this.launcherCallbacks.getServerModsProfileUsed(url, info, sessionID); }, ), diff --git a/project/src/routers/static/LocationStaticRouter.ts b/project/src/routers/static/LocationStaticRouter.ts index a81b5310..daddf7ea 100644 --- a/project/src/routers/static/LocationStaticRouter.ts +++ b/project/src/routers/static/LocationStaticRouter.ts @@ -1,15 +1,13 @@ -import { inject, injectable } from "tsyringe"; import { LocationCallbacks } from "@spt/callbacks/LocationCallbacks"; import { RouteAction, StaticRouter } from "@spt/di/Router"; import { ILocationsGenerateAllResponse } from "@spt/models/eft/common/ILocationsSourceDestinationBase"; import { IGetBodyResponseData } from "@spt/models/eft/httpResponse/IGetBodyResponseData"; import { IGetAirdropLootResponse } from "@spt/models/eft/location/IGetAirdropLootResponse"; +import { inject, injectable } from "tsyringe"; @injectable() -export class LocationStaticRouter extends StaticRouter -{ - constructor(@inject("LocationCallbacks") protected locationCallbacks: LocationCallbacks) - { +export class LocationStaticRouter extends StaticRouter { + constructor(@inject("LocationCallbacks") protected locationCallbacks: LocationCallbacks) { super([ new RouteAction( "/client/locations", @@ -18,8 +16,7 @@ export class LocationStaticRouter extends StaticRouter info: any, sessionID: string, output: string, - ): Promise> => - { + ): Promise> => { return this.locationCallbacks.getLocationData(url, info, sessionID); }, ), @@ -30,8 +27,7 @@ export class LocationStaticRouter extends StaticRouter info: any, sessionID: string, output: string, - ): Promise> => - { + ): Promise> => { return this.locationCallbacks.getAirdropLoot(url, info, sessionID); }, ), diff --git a/project/src/routers/static/MatchStaticRouter.ts b/project/src/routers/static/MatchStaticRouter.ts index 6feb2f45..30987a4a 100644 --- a/project/src/routers/static/MatchStaticRouter.ts +++ b/project/src/routers/static/MatchStaticRouter.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { MatchCallbacks } from "@spt/callbacks/MatchCallbacks"; import { RouteAction, StaticRouter } from "@spt/di/Router"; import { IEmptyRequestData } from "@spt/models/eft/common/IEmptyRequestData"; @@ -9,12 +8,11 @@ import { IMatchGroupCurrentResponse } from "@spt/models/eft/match/IMatchGroupCur import { IMatchGroupStatusResponse } from "@spt/models/eft/match/IMatchGroupStatusResponse"; import { IProfileStatusResponse } from "@spt/models/eft/match/IProfileStatusResponse"; import { IStartLocalRaidResponseData } from "@spt/models/eft/match/IStartLocalRaidResponseData"; +import { inject, injectable } from "tsyringe"; @injectable() -export class MatchStaticRouter extends StaticRouter -{ - constructor(@inject("MatchCallbacks") protected matchCallbacks: MatchCallbacks) - { +export class MatchStaticRouter extends StaticRouter { + constructor(@inject("MatchCallbacks") protected matchCallbacks: MatchCallbacks) { super([ new RouteAction( "/client/match/available", @@ -23,15 +21,13 @@ export class MatchStaticRouter extends StaticRouter info: any, sessionID: string, output: string, - ): Promise> => - { + ): Promise> => { return this.matchCallbacks.serverAvailable(url, info, sessionID); }, ), new RouteAction( "/client/match/updatePing", - async (url: string, info: any, sessionID: string, output: string): Promise => - { + async (url: string, info: any, sessionID: string, output: string): Promise => { return this.matchCallbacks.updatePing(url, info, sessionID); }, ), @@ -42,15 +38,13 @@ export class MatchStaticRouter extends StaticRouter info: any, sessionID: string, output: string, - ): Promise> => - { + ): Promise> => { return this.matchCallbacks.joinMatch(url, info, sessionID); }, ), new RouteAction( "/client/match/exit", - async (url: string, info: any, sessionID: string, output: string): Promise => - { + async (url: string, info: any, sessionID: string, output: string): Promise => { return this.matchCallbacks.exitMatch(url, info, sessionID); }, ), @@ -61,8 +55,7 @@ export class MatchStaticRouter extends StaticRouter info: any, sessionID: string, output: string, - ): Promise> => - { + ): Promise> => { return this.matchCallbacks.deleteGroup(url, info, sessionID); }, ), @@ -73,8 +66,7 @@ export class MatchStaticRouter extends StaticRouter info: any, sessionID: string, output: string, - ): Promise> => - { + ): Promise> => { return this.matchCallbacks.leaveGroup(url, info, sessionID); }, ), @@ -85,8 +77,7 @@ export class MatchStaticRouter extends StaticRouter info: any, sessionID: string, output: string, - ): Promise> => - { + ): Promise> => { return this.matchCallbacks.getGroupStatus(url, info, sessionID); }, ), @@ -97,15 +88,13 @@ export class MatchStaticRouter extends StaticRouter info: any, sessionID: string, output: string, - ): Promise> => - { + ): Promise> => { return this.matchCallbacks.joinMatch(url, info, sessionID); }, ), new RouteAction( "/client/match/group/exit_from_menu", - async (url: string, info: any, sessionID: string, output: string): Promise => - { + async (url: string, info: any, sessionID: string, output: string): Promise => { return this.matchCallbacks.exitToMenu(url, info, sessionID); }, ), @@ -116,22 +105,19 @@ export class MatchStaticRouter extends StaticRouter info: IEmptyRequestData, sessionID: string, output: string, - ): Promise> => - { + ): Promise> => { return this.matchCallbacks.groupCurrent(url, info, sessionID); }, ), new RouteAction( "/client/match/group/looking/start", - async (url: string, info: any, sessionID: string, output: string): Promise => - { + async (url: string, info: any, sessionID: string, output: string): Promise => { return this.matchCallbacks.startGroupSearch(url, info, sessionID); }, ), new RouteAction( "/client/match/group/looking/stop", - async (url: string, info: any, sessionID: string, output: string): Promise => - { + async (url: string, info: any, sessionID: string, output: string): Promise => { return this.matchCallbacks.stopGroupSearch(url, info, sessionID); }, ), @@ -142,8 +128,7 @@ export class MatchStaticRouter extends StaticRouter info: any, sessionID: string, output: string, - ): Promise> => - { + ): Promise> => { return this.matchCallbacks.sendGroupInvite(url, info, sessionID); }, ), @@ -154,8 +139,7 @@ export class MatchStaticRouter extends StaticRouter info: any, sessionID: string, output: string, - ): Promise> => - { + ): Promise> => { return this.matchCallbacks.acceptGroupInvite(url, info, sessionID); }, ), @@ -166,8 +150,7 @@ export class MatchStaticRouter extends StaticRouter info: any, sessionID: string, output: string, - ): Promise> => - { + ): Promise> => { return this.matchCallbacks.declineGroupInvite(url, info, sessionID); }, ), @@ -178,8 +161,7 @@ export class MatchStaticRouter extends StaticRouter info: any, sessionID: string, output: string, - ): Promise> => - { + ): Promise> => { return this.matchCallbacks.cancelGroupInvite(url, info, sessionID); }, ), @@ -190,8 +172,7 @@ export class MatchStaticRouter extends StaticRouter info: IEmptyRequestData, sessionID: string, output: string, - ): Promise> => - { + ): Promise> => { return this.matchCallbacks.cancelAllGroupInvite(url, info, sessionID); }, ), @@ -202,8 +183,7 @@ export class MatchStaticRouter extends StaticRouter info: any, sessionID: string, output: string, - ): Promise> => - { + ): Promise> => { return this.matchCallbacks.transferGroup(url, info, sessionID); }, ), @@ -214,8 +194,7 @@ export class MatchStaticRouter extends StaticRouter info: any, sessionID: string, output: string, - ): Promise> => - { + ): Promise> => { return this.matchCallbacks.raidReady(url, info, sessionID); }, ), @@ -226,15 +205,13 @@ export class MatchStaticRouter extends StaticRouter info: any, sessionID: string, output: string, - ): Promise> => - { + ): Promise> => { return this.matchCallbacks.notRaidReady(url, info, sessionID); }, ), new RouteAction( "/client/putMetrics", - async (url: string, info: any, sessionID: string, output: string): Promise => - { + async (url: string, info: any, sessionID: string, output: string): Promise => { return this.matchCallbacks.putMetrics(url, info, sessionID); }, ), @@ -245,22 +222,19 @@ export class MatchStaticRouter extends StaticRouter info: any, sessionID: string, output: string, - ): Promise> => - { + ): Promise> => { return this.matchCallbacks.getMetrics(url, info, sessionID); }, ), new RouteAction( "/client/raid/configuration", - async (url: string, info: any, sessionID: string, output: string): Promise => - { + async (url: string, info: any, sessionID: string, output: string): Promise => { return this.matchCallbacks.getRaidConfiguration(url, info, sessionID); }, ), new RouteAction( "/client/raid/configuration-by-profile", - async (url: string, info: any, sessionID: string, output: string): Promise => - { + async (url: string, info: any, sessionID: string, output: string): Promise => { return this.matchCallbacks.getConfigurationByProfile(url, info, sessionID); }, ), @@ -271,8 +245,7 @@ export class MatchStaticRouter extends StaticRouter info: any, sessionID: string, output: string, - ): Promise> => - { + ): Promise> => { return this.matchCallbacks.removePlayerFromGroup(url, info, sessionID); }, ), @@ -283,20 +256,13 @@ export class MatchStaticRouter extends StaticRouter info: any, sessionID: string, output: string, - ): Promise> => - { + ): Promise> => { return this.matchCallbacks.startLocalRaid(url, info, sessionID); }, ), new RouteAction( "/client/match/local/end", - async ( - url: string, - info: any, - sessionID: string, - output: string, - ): Promise => - { + async (url: string, info: any, sessionID: string, output: string): Promise => { return this.matchCallbacks.endLocalRaid(url, info, sessionID); }, ), diff --git a/project/src/routers/static/NotifierStaticRouter.ts b/project/src/routers/static/NotifierStaticRouter.ts index 623c9c53..f3623ea8 100644 --- a/project/src/routers/static/NotifierStaticRouter.ts +++ b/project/src/routers/static/NotifierStaticRouter.ts @@ -1,15 +1,13 @@ -import { inject, injectable } from "tsyringe"; import { NotifierCallbacks } from "@spt/callbacks/NotifierCallbacks"; import { RouteAction, StaticRouter } from "@spt/di/Router"; import { IGetBodyResponseData } from "@spt/models/eft/httpResponse/IGetBodyResponseData"; import { INotifierChannel } from "@spt/models/eft/notifier/INotifier"; import { ISelectProfileResponse } from "@spt/models/eft/notifier/ISelectProfileResponse"; +import { inject, injectable } from "tsyringe"; @injectable() -export class NotifierStaticRouter extends StaticRouter -{ - constructor(@inject("NotifierCallbacks") protected notifierCallbacks: NotifierCallbacks) - { +export class NotifierStaticRouter extends StaticRouter { + constructor(@inject("NotifierCallbacks") protected notifierCallbacks: NotifierCallbacks) { super([ new RouteAction( "/client/notifier/channel/create", @@ -18,8 +16,7 @@ export class NotifierStaticRouter extends StaticRouter info: any, sessionID: string, output: string, - ): Promise> => - { + ): Promise> => { return this.notifierCallbacks.createNotifierChannel(url, info, sessionID); }, ), @@ -30,8 +27,7 @@ export class NotifierStaticRouter extends StaticRouter info: any, sessionID: string, output: string, - ): Promise> => - { + ): Promise> => { return this.notifierCallbacks.selectProfile(url, info, sessionID); }, ), diff --git a/project/src/routers/static/ProfileStaticRouter.ts b/project/src/routers/static/ProfileStaticRouter.ts index 05615464..69f77227 100644 --- a/project/src/routers/static/ProfileStaticRouter.ts +++ b/project/src/routers/static/ProfileStaticRouter.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { ProfileCallbacks } from "@spt/callbacks/ProfileCallbacks"; import { RouteAction, StaticRouter } from "@spt/di/Router"; import { IPmcData } from "@spt/models/eft/common/IPmcData"; @@ -8,12 +7,11 @@ import { GetProfileStatusResponseData } from "@spt/models/eft/profile/GetProfile import { ICreateProfileResponse } from "@spt/models/eft/profile/ICreateProfileResponse"; import { IGetOtherProfileResponse } from "@spt/models/eft/profile/IGetOtherProfileResponse"; import { ISearchFriendResponse } from "@spt/models/eft/profile/ISearchFriendResponse"; +import { inject, injectable } from "tsyringe"; @injectable() -export class ProfileStaticRouter extends StaticRouter -{ - constructor(@inject("ProfileCallbacks") protected profileCallbacks: ProfileCallbacks) - { +export class ProfileStaticRouter extends StaticRouter { + constructor(@inject("ProfileCallbacks") protected profileCallbacks: ProfileCallbacks) { super([ new RouteAction( "/client/game/profile/create", @@ -22,8 +20,7 @@ export class ProfileStaticRouter extends StaticRouter info: any, sessionID: string, output: string, - ): Promise> => - { + ): Promise> => { return this.profileCallbacks.createProfile(url, info, sessionID); }, ), @@ -34,8 +31,7 @@ export class ProfileStaticRouter extends StaticRouter info: any, sessionID: string, output: string, - ): Promise> => - { + ): Promise> => { return this.profileCallbacks.getProfileData(url, info, sessionID); }, ), @@ -46,15 +42,13 @@ export class ProfileStaticRouter extends StaticRouter info: any, sessionID: string, output: string, - ): Promise> => - { + ): Promise> => { return this.profileCallbacks.regenerateScav(url, info, sessionID); }, ), new RouteAction( "/client/game/profile/voice/change", - async (url: string, info: any, sessionID: string, output: string): Promise => - { + async (url: string, info: any, sessionID: string, output: string): Promise => { return this.profileCallbacks.changeVoice(url, info, sessionID); }, ), @@ -65,8 +59,7 @@ export class ProfileStaticRouter extends StaticRouter info: any, sessionID: string, output: string, - ): Promise> => - { + ): Promise> => { return this.profileCallbacks.changeNickname(url, info, sessionID); }, ), @@ -77,8 +70,7 @@ export class ProfileStaticRouter extends StaticRouter info: any, sessionID: string, output: string, - ): Promise> => - { + ): Promise> => { return this.profileCallbacks.validateNickname(url, info, sessionID); }, ), @@ -89,8 +81,7 @@ export class ProfileStaticRouter extends StaticRouter info: any, sessionID: string, output: string, - ): Promise> => - { + ): Promise> => { return this.profileCallbacks.getReservedNickname(url, info, sessionID); }, ), @@ -101,8 +92,7 @@ export class ProfileStaticRouter extends StaticRouter info: any, sessionID: string, output: string, - ): Promise> => - { + ): Promise> => { return this.profileCallbacks.getProfileStatus(url, info, sessionID); }, ), @@ -113,8 +103,7 @@ export class ProfileStaticRouter extends StaticRouter info: any, sessionID: string, output: string, - ): Promise> => - { + ): Promise> => { return this.profileCallbacks.getOtherProfile(url, info, sessionID); }, ), @@ -125,8 +114,7 @@ export class ProfileStaticRouter extends StaticRouter info: any, sessionID: string, output: string, - ): Promise> => - { + ): Promise> => { return this.profileCallbacks.getProfileSettings(url, info, sessionID); }, ), @@ -137,22 +125,19 @@ export class ProfileStaticRouter extends StaticRouter info: any, sessionID: string, output: string, - ): Promise> => - { + ): Promise> => { return this.profileCallbacks.searchFriend(url, info, sessionID); }, ), new RouteAction( "/launcher/profile/info", - async (url: string, info: any, sessionID: string, output: string): Promise => - { + async (url: string, info: any, sessionID: string, output: string): Promise => { return this.profileCallbacks.getMiniProfile(url, info, sessionID); }, ), new RouteAction( "/launcher/profiles", - async (url: string, info: any, sessionID: string, output: string): Promise => - { + async (url: string, info: any, sessionID: string, output: string): Promise => { return this.profileCallbacks.getAllMiniProfiles(url, info, sessionID); }, ), diff --git a/project/src/routers/static/QuestStaticRouter.ts b/project/src/routers/static/QuestStaticRouter.ts index f6e049a4..5381ad44 100644 --- a/project/src/routers/static/QuestStaticRouter.ts +++ b/project/src/routers/static/QuestStaticRouter.ts @@ -1,15 +1,13 @@ -import { inject, injectable } from "tsyringe"; import { QuestCallbacks } from "@spt/callbacks/QuestCallbacks"; import { RouteAction, StaticRouter } from "@spt/di/Router"; import { IQuest } from "@spt/models/eft/common/tables/IQuest"; import { IPmcDataRepeatableQuest } from "@spt/models/eft/common/tables/IRepeatableQuests"; import { IGetBodyResponseData } from "@spt/models/eft/httpResponse/IGetBodyResponseData"; +import { inject, injectable } from "tsyringe"; @injectable() -export class QuestStaticRouter extends StaticRouter -{ - constructor(@inject("QuestCallbacks") protected questCallbacks: QuestCallbacks) - { +export class QuestStaticRouter extends StaticRouter { + constructor(@inject("QuestCallbacks") protected questCallbacks: QuestCallbacks) { super([ new RouteAction( "/client/quest/list", @@ -18,8 +16,7 @@ export class QuestStaticRouter extends StaticRouter info: any, sessionID: string, output: string, - ): Promise> => - { + ): Promise> => { return this.questCallbacks.listQuests(url, info, sessionID); }, ), @@ -30,8 +27,7 @@ export class QuestStaticRouter extends StaticRouter info: any, sessionID: string, output: string, - ): Promise> => - { + ): Promise> => { return this.questCallbacks.activityPeriods(url, info, sessionID); }, ), diff --git a/project/src/routers/static/RagfairStaticRouter.ts b/project/src/routers/static/RagfairStaticRouter.ts index b14df84f..9a012593 100644 --- a/project/src/routers/static/RagfairStaticRouter.ts +++ b/project/src/routers/static/RagfairStaticRouter.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { RagfairCallbacks } from "@spt/callbacks/RagfairCallbacks"; import { RouteAction, StaticRouter } from "@spt/di/Router"; import { IGetBodyResponseData } from "@spt/models/eft/httpResponse/IGetBodyResponseData"; @@ -6,12 +5,11 @@ import { INullResponseData } from "@spt/models/eft/httpResponse/INullResponseDat import { IGetItemPriceResult } from "@spt/models/eft/ragfair/IGetItemPriceResult"; import { IGetOffersResult } from "@spt/models/eft/ragfair/IGetOffersResult"; import { IRagfairOffer } from "@spt/models/eft/ragfair/IRagfairOffer"; +import { inject, injectable } from "tsyringe"; @injectable() -export class RagfairStaticRouter extends StaticRouter -{ - constructor(@inject("RagfairCallbacks") protected ragfairCallbacks: RagfairCallbacks) - { +export class RagfairStaticRouter extends StaticRouter { + constructor(@inject("RagfairCallbacks") protected ragfairCallbacks: RagfairCallbacks) { super([ new RouteAction( "/client/ragfair/search", @@ -20,8 +18,7 @@ export class RagfairStaticRouter extends StaticRouter info: any, sessionID: string, output: string, - ): Promise> => - { + ): Promise> => { return this.ragfairCallbacks.search(url, info, sessionID); }, ), @@ -32,8 +29,7 @@ export class RagfairStaticRouter extends StaticRouter info: any, sessionID: string, output: string, - ): Promise> => - { + ): Promise> => { return this.ragfairCallbacks.search(url, info, sessionID); }, ), @@ -44,22 +40,19 @@ export class RagfairStaticRouter extends StaticRouter info: any, sessionID: string, output: string, - ): Promise> => - { + ): Promise> => { return this.ragfairCallbacks.getMarketPrice(url, info, sessionID); }, ), new RouteAction( "/client/ragfair/offerfees", - async (url: string, info: any, sessionID: string, output: string): Promise => - { + async (url: string, info: any, sessionID: string, output: string): Promise => { return this.ragfairCallbacks.storePlayerOfferTaxAmount(url, info, sessionID); }, ), new RouteAction( "/client/reports/ragfair/send", - async (url: string, info: any, sessionID: string, output: string): Promise => - { + async (url: string, info: any, sessionID: string, output: string): Promise => { return this.ragfairCallbacks.sendReport(url, info, sessionID); }, ), @@ -70,8 +63,7 @@ export class RagfairStaticRouter extends StaticRouter info: any, sessionID: string, output: string, - ): Promise>> => - { + ): Promise>> => { return this.ragfairCallbacks.getFleaPrices(url, info, sessionID); }, ), @@ -82,8 +74,7 @@ export class RagfairStaticRouter extends StaticRouter info: any, sessionID: string, output: string, - ): Promise> => - { + ): Promise> => { return this.ragfairCallbacks.getFleaOfferById(url, info, sessionID); }, ), diff --git a/project/src/routers/static/TraderStaticRouter.ts b/project/src/routers/static/TraderStaticRouter.ts index 1fedc2b5..58e985ab 100644 --- a/project/src/routers/static/TraderStaticRouter.ts +++ b/project/src/routers/static/TraderStaticRouter.ts @@ -1,14 +1,12 @@ -import { inject, injectable } from "tsyringe"; import { TraderCallbacks } from "@spt/callbacks/TraderCallbacks"; import { RouteAction, StaticRouter } from "@spt/di/Router"; import { ITraderBase } from "@spt/models/eft/common/tables/ITrader"; import { IGetBodyResponseData } from "@spt/models/eft/httpResponse/IGetBodyResponseData"; +import { inject, injectable } from "tsyringe"; @injectable() -export class TraderStaticRouter extends StaticRouter -{ - constructor(@inject("TraderCallbacks") protected traderCallbacks: TraderCallbacks) - { +export class TraderStaticRouter extends StaticRouter { + constructor(@inject("TraderCallbacks") protected traderCallbacks: TraderCallbacks) { super([ new RouteAction( "/client/trading/api/traderSettings", @@ -17,8 +15,7 @@ export class TraderStaticRouter extends StaticRouter info: any, sessionID: string, output: string, - ): Promise> => - { + ): Promise> => { return this.traderCallbacks.getTraderSettings(url, info, sessionID); }, ), diff --git a/project/src/routers/static/WeatherStaticRouter.ts b/project/src/routers/static/WeatherStaticRouter.ts index 52e7846b..16ee020c 100644 --- a/project/src/routers/static/WeatherStaticRouter.ts +++ b/project/src/routers/static/WeatherStaticRouter.ts @@ -1,15 +1,13 @@ -import { inject, injectable } from "tsyringe"; import { WeatherCallbacks } from "@spt/callbacks/WeatherCallbacks"; import { RouteAction, StaticRouter } from "@spt/di/Router"; import { IGetBodyResponseData } from "@spt/models/eft/httpResponse/IGetBodyResponseData"; import { IWeatherData } from "@spt/models/eft/weather/IWeatherData"; import { IGetLocalWeatherResponseData } from "@spt/models/spt/weather/IGetLocalWeatherResponseData"; +import { inject, injectable } from "tsyringe"; @injectable() -export class WeatherStaticRouter extends StaticRouter -{ - constructor(@inject("WeatherCallbacks") protected weatherCallbacks: WeatherCallbacks) - { +export class WeatherStaticRouter extends StaticRouter { + constructor(@inject("WeatherCallbacks") protected weatherCallbacks: WeatherCallbacks) { super([ new RouteAction( "/client/weather", @@ -18,8 +16,7 @@ export class WeatherStaticRouter extends StaticRouter info: any, sessionID: string, output: string, - ): Promise> => - { + ): Promise> => { return this.weatherCallbacks.getWeather(url, info, sessionID); }, ), @@ -30,9 +27,8 @@ export class WeatherStaticRouter extends StaticRouter url: string, info: any, sessionID: string, - _output: string - ): Promise> => - { + _output: string, + ): Promise> => { return this.weatherCallbacks.getLocalWeather(url, info, sessionID); }, ), diff --git a/project/src/servers/ConfigServer.ts b/project/src/servers/ConfigServer.ts index 61f98760..51351f0d 100644 --- a/project/src/servers/ConfigServer.ts +++ b/project/src/servers/ConfigServer.ts @@ -1,12 +1,11 @@ -import { inject, injectable } from "tsyringe"; import { ConfigTypes } from "@spt/models/enums/ConfigTypes"; import { ILogger } from "@spt/models/spt/utils/ILogger"; import { JsonUtil } from "@spt/utils/JsonUtil"; import { VFS } from "@spt/utils/VFS"; +import { inject, injectable } from "tsyringe"; @injectable() -export class ConfigServer -{ +export class ConfigServer { protected configs: Record = {}; protected readonly acceptableFileExtensions: string[] = ["json", "jsonc"]; @@ -14,28 +13,23 @@ export class ConfigServer @inject("PrimaryLogger") protected logger: ILogger, @inject("VFS") protected vfs: VFS, @inject("JsonUtil") protected jsonUtil: JsonUtil, - ) - { + ) { this.initialize(); } - public getConfig(configType: ConfigTypes): T - { - if (!this.configs[configType]) - { + public getConfig(configType: ConfigTypes): T { + if (!this.configs[configType]) { throw new Error(`Config: ${configType} is undefined. Ensure you have not broken it via editing`); } return this.configs[configType]; } - public getConfigByString(configType: string): T - { + public getConfigByString(configType: string): T { return this.configs[configType]; } - public initialize(): void - { + public initialize(): void { this.logger.debug("Importing configs..."); // Get all filepaths @@ -43,10 +37,8 @@ export class ConfigServer const files = this.vfs.getFiles(filepath); // Add file content to result - for (const file of files) - { - if (this.acceptableFileExtensions.includes(this.vfs.getFileExtension(file.toLowerCase()))) - { + for (const file of files) { + if (this.acceptableFileExtensions.includes(this.vfs.getFileExtension(file.toLowerCase()))) { const fileName = this.vfs.stripExtension(file); const filePathAndName = `${filepath}${file}`; this.configs[`spt-${fileName}`] = this.jsonUtil.deserializeJsonC( diff --git a/project/src/servers/DatabaseServer.ts b/project/src/servers/DatabaseServer.ts index 7ec83643..d30ac87d 100644 --- a/project/src/servers/DatabaseServer.ts +++ b/project/src/servers/DatabaseServer.ts @@ -1,9 +1,8 @@ -import { injectable } from "tsyringe"; import { IDatabaseTables } from "@spt/models/spt/server/IDatabaseTables"; +import { injectable } from "tsyringe"; @injectable() -export class DatabaseServer -{ +export class DatabaseServer { protected tableData: IDatabaseTables = { bots: undefined, hideout: undefined, @@ -17,13 +16,11 @@ export class DatabaseServer settings: undefined, }; - public getTables(): IDatabaseTables - { + public getTables(): IDatabaseTables { return this.tableData; } - public setTables(tableData: IDatabaseTables): void - { + public setTables(tableData: IDatabaseTables): void { this.tableData = tableData; } } diff --git a/project/src/servers/HttpServer.ts b/project/src/servers/HttpServer.ts index 2b7082a6..306bb374 100644 --- a/project/src/servers/HttpServer.ts +++ b/project/src/servers/HttpServer.ts @@ -1,5 +1,4 @@ import http, { IncomingMessage, ServerResponse, Server } from "node:http"; -import { inject, injectAll, injectable } from "tsyringe"; import { ApplicationContext } from "@spt/context/ApplicationContext"; import { ContextVariableType } from "@spt/context/ContextVariableType"; import { HttpServerHelper } from "@spt/helpers/HttpServerHelper"; @@ -8,13 +7,13 @@ import { IHttpConfig } from "@spt/models/spt/config/IHttpConfig"; import { ILogger } from "@spt/models/spt/utils/ILogger"; import { ConfigServer } from "@spt/servers/ConfigServer"; import { DatabaseServer } from "@spt/servers/DatabaseServer"; -import { IHttpListener } from "@spt/servers/http/IHttpListener"; import { WebSocketServer } from "@spt/servers/WebSocketServer"; +import { IHttpListener } from "@spt/servers/http/IHttpListener"; import { LocalisationService } from "@spt/services/LocalisationService"; +import { inject, injectAll, injectable } from "tsyringe"; @injectable() -export class HttpServer -{ +export class HttpServer { protected httpConfig: IHttpConfig; protected started: boolean; @@ -27,44 +26,36 @@ export class HttpServer @inject("ConfigServer") protected configServer: ConfigServer, @inject("ApplicationContext") protected applicationContext: ApplicationContext, @inject("WebSocketServer") protected webSocketServer: WebSocketServer, - ) - { + ) { this.httpConfig = this.configServer.getConfig(ConfigTypes.HTTP); } /** * Handle server loading event */ - public load(): void - { + public load(): void { this.started = false; /* create server */ const httpServer: Server = http.createServer(); - httpServer.on("request", (req, res) => - { + httpServer.on("request", (req, res) => { this.handleRequest(req, res); }); /* Config server to listen on a port */ - httpServer.listen(this.httpConfig.port, this.httpConfig.ip, () => - { + httpServer.listen(this.httpConfig.port, this.httpConfig.ip, () => { this.started = true; this.logger.success( this.localisationService.getText("started_webserver_success", this.httpServerHelper.getBackendUrl()), ); }); - httpServer.on("error", (e: any) => - { + httpServer.on("error", (e: any) => { /* server is already running or program using privileged port without root */ - if (process.platform === "linux" && !(process.getuid && process.getuid() === 0) && e.port < 1024) - { + if (process.platform === "linux" && !(process.getuid && process.getuid() === 0) && e.port < 1024) { this.logger.error(this.localisationService.getText("linux_use_priviledged_port_non_root")); - } - else - { + } else { const message = this.localisationService.getText("port_already_in_use", e.port); this.logger.error(`${message} [${e.message}]`); } @@ -74,8 +65,7 @@ export class HttpServer this.webSocketServer.setupWebSocket(httpServer); } - protected handleRequest(req: IncomingMessage, resp: ServerResponse): void - { + protected handleRequest(req: IncomingMessage, resp: ServerResponse): void { // Pull sessionId out of cookies and store inside app context const sessionId = this.getCookies(req).PHPSESSID; this.applicationContext.addValue(ContextVariableType.SESSION_ID, sessionId); @@ -85,17 +75,12 @@ export class HttpServer const forwardedFor = req.headers["x-forwarded-for"] as string; const clientIp = realIp || (forwardedFor ? forwardedFor.split(",")[0].trim() : req.socket.remoteAddress); - if (this.httpConfig.logRequests) - { + if (this.httpConfig.logRequests) { const isLocalRequest = this.isLocalRequest(clientIp); - if (typeof isLocalRequest !== "undefined") - { - if (isLocalRequest) - { + if (typeof isLocalRequest !== "undefined") { + if (isLocalRequest) { this.logger.info(this.localisationService.getText("client_request", req.url)); - } - else - { + } else { this.logger.info( this.localisationService.getText("client_request_ip", { ip: clientIp, @@ -106,10 +91,8 @@ export class HttpServer } } - for (const listener of this.httpListeners) - { - if (listener.canHandle(sessionId, req)) - { + for (const listener of this.httpListeners) { + if (listener.canHandle(sessionId, req)) { listener.handle(sessionId, req, resp); break; } @@ -121,29 +104,24 @@ export class HttpServer * @param remoteAddress Address to check * @returns True if its local */ - protected isLocalRequest(remoteAddress: string): boolean - { - if (!remoteAddress) - { + protected isLocalRequest(remoteAddress: string): boolean { + if (!remoteAddress) { return undefined; } return ( - remoteAddress.startsWith("127.0.0") - || remoteAddress.startsWith("192.168.") - || remoteAddress.startsWith("localhost") + remoteAddress.startsWith("127.0.0") || + remoteAddress.startsWith("192.168.") || + remoteAddress.startsWith("localhost") ); } - protected getCookies(req: IncomingMessage): Record - { + protected getCookies(req: IncomingMessage): Record { const found: Record = {}; const cookies = req.headers.cookie; - if (cookies) - { - for (const cookie of cookies.split(";")) - { + if (cookies) { + for (const cookie of cookies.split(";")) { const parts = cookie.split("="); found[parts.shift().trim()] = decodeURI(parts.join("=")); @@ -153,8 +131,7 @@ export class HttpServer return found; } - public isStarted(): boolean - { + public isStarted(): boolean { return this.started; } } diff --git a/project/src/servers/RagfairServer.ts b/project/src/servers/RagfairServer.ts index 30399b76..668870f9 100644 --- a/project/src/servers/RagfairServer.ts +++ b/project/src/servers/RagfairServer.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { RagfairOfferGenerator } from "@spt/generators/RagfairOfferGenerator"; import { TraderAssortHelper } from "@spt/helpers/TraderAssortHelper"; import { TraderHelper } from "@spt/helpers/TraderHelper"; @@ -13,10 +12,10 @@ import { LocalisationService } from "@spt/services/LocalisationService"; import { RagfairCategoriesService } from "@spt/services/RagfairCategoriesService"; import { RagfairOfferService } from "@spt/services/RagfairOfferService"; import { RagfairRequiredItemsService } from "@spt/services/RagfairRequiredItemsService"; +import { inject, injectable } from "tsyringe"; @injectable() -export class RagfairServer -{ +export class RagfairServer { protected ragfairConfig: IRagfairConfig; constructor( @@ -29,40 +28,33 @@ export class RagfairServer @inject("TraderHelper") protected traderHelper: TraderHelper, @inject("TraderAssortHelper") protected traderAssortHelper: TraderAssortHelper, @inject("ConfigServer") protected configServer: ConfigServer, - ) - { + ) { this.ragfairConfig = this.configServer.getConfig(ConfigTypes.RAGFAIR); } - public async load(): Promise - { + public async load(): Promise { await this.ragfairOfferGenerator.generateDynamicOffers(); await this.update(); } - public async update(): Promise - { + public async update(): Promise { this.ragfairOfferService.expireStaleOffers(); // Generate trader offers const traders = this.getUpdateableTraders(); - for (const traderId of traders) - { + for (const traderId of traders) { // Skip generating fence offers - if (traderId === Traders.FENCE) - { + if (traderId === Traders.FENCE) { continue; } - if (this.ragfairOfferService.traderOffersNeedRefreshing(traderId)) - { + if (this.ragfairOfferService.traderOffersNeedRefreshing(traderId)) { this.ragfairOfferGenerator.generateFleaOffersForTrader(traderId); } } // Regenerate expired offers when over threshold limit - if (this.ragfairOfferService.getExpiredOfferCount() >= this.ragfairConfig.dynamic.expiredOfferThreshold) - { + if (this.ragfairOfferService.getExpiredOfferCount() >= this.ragfairConfig.dynamic.expiredOfferThreshold) { const expiredAssortsWithChildren = this.ragfairOfferService.getExpiredOfferAssorts(); await this.ragfairOfferGenerator.generateDynamicOffers(expiredAssortsWithChildren); @@ -77,8 +69,7 @@ export class RagfairServer * Get traders who need to be periodically refreshed * @returns string array of traders */ - public getUpdateableTraders(): string[] - { + public getUpdateableTraders(): string[] { return Object.keys(this.ragfairConfig.traders).filter((x) => this.ragfairConfig.traders[x]); } @@ -86,8 +77,7 @@ export class RagfairServer fleaUnlocked: boolean, searchRequestData: ISearchRequestData, offers: IRagfairOffer[], - ): Record - { + ): Record { return this.ragfairCategoriesService.getCategoriesFromOffers(offers, searchRequestData, fleaUnlocked); } @@ -95,13 +85,11 @@ export class RagfairServer * Disable/Hide an offer from flea * @param offerId */ - public hideOffer(offerId: string): void - { + public hideOffer(offerId: string): void { const offers = this.ragfairOfferService.getOffers(); const offer = offers.find((x) => x._id === offerId); - if (!offer) - { + if (!offer) { this.logger.error(this.localisationService.getText("ragfair-offer_not_found_unable_to_hide", offerId)); return; @@ -110,28 +98,23 @@ export class RagfairServer offer.locked = true; } - public getOffer(offerID: string): IRagfairOffer - { + public getOffer(offerID: string): IRagfairOffer { return this.ragfairOfferService.getOfferByOfferId(offerID); } - public getOffers(): IRagfairOffer[] - { + public getOffers(): IRagfairOffer[] { return this.ragfairOfferService.getOffers(); } - public removeOfferStack(offerID: string, amount: number): void - { + public removeOfferStack(offerID: string, amount: number): void { this.ragfairOfferService.removeOfferStack(offerID, amount); } - public doesOfferExist(offerId: string): boolean - { + public doesOfferExist(offerId: string): boolean { return this.ragfairOfferService.doesOfferExist(offerId); } - public addPlayerOffers(): void - { + public addPlayerOffers(): void { this.ragfairOfferService.addPlayerOffers(); } } diff --git a/project/src/servers/SaveServer.ts b/project/src/servers/SaveServer.ts index 0639880e..8d7d9d86 100644 --- a/project/src/servers/SaveServer.ts +++ b/project/src/servers/SaveServer.ts @@ -1,4 +1,3 @@ -import { inject, injectAll, injectable } from "tsyringe"; import { SaveLoadRouter } from "@spt/di/Router"; import { ISptProfile, Info } from "@spt/models/eft/profile/ISptProfile"; import { ConfigTypes } from "@spt/models/enums/ConfigTypes"; @@ -9,10 +8,10 @@ import { LocalisationService } from "@spt/services/LocalisationService"; import { HashUtil } from "@spt/utils/HashUtil"; import { JsonUtil } from "@spt/utils/JsonUtil"; import { VFS } from "@spt/utils/VFS"; +import { inject, injectAll, injectable } from "tsyringe"; @injectable() -export class SaveServer -{ +export class SaveServer { protected profileFilepath = "user/profiles/"; protected profiles = {}; // onLoad = require("../bindings/SaveLoad"); @@ -27,16 +26,14 @@ export class SaveServer @inject("LocalisationService") protected localisationService: LocalisationService, @inject("PrimaryLogger") protected logger: ILogger, @inject("ConfigServer") protected configServer: ConfigServer, - ) - {} + ) {} /** * Add callback to occur prior to saving profile changes * @param id Id for save callback * @param callback Callback to execute prior to running SaveServer.saveProfile() */ - public addBeforeSaveCallback(id: string, callback: (profile: Partial) => Partial): void - { + public addBeforeSaveCallback(id: string, callback: (profile: Partial) => Partial): void { this.onBeforeSaveCallbacks[id] = callback; } @@ -44,34 +41,29 @@ export class SaveServer * Remove a callback from being executed prior to saving profile in SaveServer.saveProfile() * @param id Id of callback to remove */ - public removeBeforeSaveCallback(id: string): void - { + public removeBeforeSaveCallback(id: string): void { this.onBeforeSaveCallbacks[id] = undefined; } /** * Load all profiles in /user/profiles folder into memory (this.profiles) */ - public load(): void - { + public load(): void { // get files to load - if (!this.vfs.exists(this.profileFilepath)) - { + if (!this.vfs.exists(this.profileFilepath)) { this.vfs.createDir(this.profileFilepath); } - const files = this.vfs.getFiles(this.profileFilepath).filter((item) => - { + const files = this.vfs.getFiles(this.profileFilepath).filter((item) => { return this.vfs.getFileExtension(item) === "json"; }); // load profiles const start = performance.now(); let loadTimeCount = 0; - for (const file of files) - { + for (const file of files) { this.loadProfile(this.vfs.stripExtension(file)); - loadTimeCount += (performance.now() - start); + loadTimeCount += performance.now() - start; } this.logger.debug(`${files.length} Profiles took: ${loadTimeCount.toFixed(2)}ms to load.`); @@ -80,12 +72,10 @@ export class SaveServer /** * Save changes for each profile from memory into user/profiles json */ - public save(): void - { + public save(): void { // Save every profile let totalTime = 0; - for (const sessionID in this.profiles) - { + for (const sessionID in this.profiles) { totalTime += this.saveProfile(sessionID); } @@ -100,28 +90,23 @@ export class SaveServer * @param sessionId Session id * @returns ISptProfile */ - public getProfile(sessionId: string): ISptProfile - { - if (!sessionId) - { + public getProfile(sessionId: string): ISptProfile { + if (!sessionId) { throw new Error("session id provided was empty, did you restart the server while the game was running?"); } - if (!this.profiles) - { + if (!this.profiles) { throw new Error(`no profiles found in saveServer with id: ${sessionId}`); } - if (!this.profiles[sessionId]) - { + if (!this.profiles[sessionId]) { throw new Error(`no profile found for sessionId: ${sessionId}`); } return this.profiles[sessionId]; } - public profileExists(id: string): boolean - { + public profileExists(id: string): boolean { return !!this.profiles[id]; } @@ -129,8 +114,7 @@ export class SaveServer * Get all profiles from memory * @returns Dictionary of ISptProfile */ - public getProfiles(): Record - { + public getProfiles(): Record { return this.profiles; } @@ -139,10 +123,8 @@ export class SaveServer * @param sessionID Id of profile to remove * @returns true when deleted, false when profile not found */ - public deleteProfileById(sessionID: string): boolean - { - if (this.profiles[sessionID]) - { + public deleteProfileById(sessionID: string): boolean { + if (this.profiles[sessionID]) { delete this.profiles[sessionID]; return true; } @@ -154,10 +136,8 @@ export class SaveServer * Create a new profile in memory with empty pmc/scav objects * @param profileInfo Basic profile data */ - public createProfile(profileInfo: Info): void - { - if (this.profiles[profileInfo.id]) - { + public createProfile(profileInfo: Info): void { + if (this.profiles[profileInfo.id]) { throw new Error(`profile already exists for sessionId: ${profileInfo.id}`); } @@ -168,8 +148,7 @@ export class SaveServer * Add full profile in memory by key (info.id) * @param profileDetails Profile to save */ - public addProfile(profileDetails: ISptProfile): void - { + public addProfile(profileDetails: ISptProfile): void { this.profiles[profileDetails.info.id] = profileDetails; } @@ -178,19 +157,16 @@ export class SaveServer * Execute saveLoadRouters callbacks after being loaded into memory * @param sessionID Id of profile to store in memory */ - public loadProfile(sessionID: string): void - { + public loadProfile(sessionID: string): void { const filename = `${sessionID}.json`; const filePath = `${this.profileFilepath}${filename}`; - if (this.vfs.exists(filePath)) - { + if (this.vfs.exists(filePath)) { // File found, store in profiles[] this.profiles[sessionID] = this.jsonUtil.deserialize(this.vfs.readFile(filePath), filename); } // Run callbacks - for (const callback of this.saveLoadRouters) - { + for (const callback of this.saveLoadRouters) { this.profiles[sessionID] = callback.handleLoad(this.getProfile(sessionID)); } } @@ -201,20 +177,15 @@ export class SaveServer * @param sessionID profile id (user/profiles/id.json) * @returns time taken to save in MS */ - public saveProfile(sessionID: string): number - { + public saveProfile(sessionID: string): number { const filePath = `${this.profileFilepath}${sessionID}.json`; // Run pre-save callbacks before we save into json - for (const callback in this.onBeforeSaveCallbacks) - { + for (const callback in this.onBeforeSaveCallbacks) { const previous = this.profiles[sessionID]; - try - { + try { this.profiles[sessionID] = this.onBeforeSaveCallbacks[callback](this.profiles[sessionID]); - } - catch (error) - { + } catch (error) { this.logger.error(this.localisationService.getText("profile_save_callback_error", { callback, error })); this.profiles[sessionID] = previous; } @@ -226,8 +197,7 @@ export class SaveServer !this.configServer.getConfig(ConfigTypes.CORE).features.compressProfile, ); const fmd5 = this.hashUtil.generateMd5ForData(jsonProfile); - if (typeof this.saveMd5[sessionID] !== "string" || this.saveMd5[sessionID] !== fmd5) - { + if (typeof this.saveMd5[sessionID] !== "string" || this.saveMd5[sessionID] !== fmd5) { this.saveMd5[sessionID] = String(fmd5); // save profile to disk this.vfs.writeFile(filePath, jsonProfile); @@ -241,8 +211,7 @@ export class SaveServer * @param sessionID Profile id to remove * @returns true if file no longer exists */ - public removeProfile(sessionID: string): boolean - { + public removeProfile(sessionID: string): boolean { const file = `${this.profileFilepath}${sessionID}.json`; delete this.profiles[sessionID]; diff --git a/project/src/servers/WebSocketServer.ts b/project/src/servers/WebSocketServer.ts index a076355c..aaa4a49e 100644 --- a/project/src/servers/WebSocketServer.ts +++ b/project/src/servers/WebSocketServer.ts @@ -1,16 +1,15 @@ import http, { IncomingMessage } from "node:http"; -import { inject, injectAll, injectable } from "tsyringe"; -import { WebSocket, Server } from "ws"; import { HttpServerHelper } from "@spt/helpers/HttpServerHelper"; import { ILogger } from "@spt/models/spt/utils/ILogger"; import { IWebSocketConnectionHandler } from "@spt/servers/ws/IWebSocketConnectionHandler"; import { LocalisationService } from "@spt/services/LocalisationService"; import { JsonUtil } from "@spt/utils/JsonUtil"; import { RandomUtil } from "@spt/utils/RandomUtil"; +import { inject, injectAll, injectable } from "tsyringe"; +import { Server, WebSocket } from "ws"; @injectable() -export class WebSocketServer -{ +export class WebSocketServer { protected webSocketServer: Server; constructor( @@ -20,21 +19,16 @@ export class WebSocketServer @inject("LocalisationService") protected localisationService: LocalisationService, @inject("HttpServerHelper") protected httpServerHelper: HttpServerHelper, @injectAll("WebSocketConnectionHandler") protected webSocketConnectionHandlers: IWebSocketConnectionHandler[], - ) - { - } + ) {} - public getWebSocketServer(): Server - { + public getWebSocketServer(): Server { return this.webSocketServer; } - public setupWebSocket(httpServer: http.Server): void - { + public setupWebSocket(httpServer: http.Server): void { this.webSocketServer = new Server({ server: httpServer }); - this.webSocketServer.addListener("listening", () => - { + this.webSocketServer.addListener("listening", () => { this.logger.success( this.localisationService.getText("websocket-started", this.httpServerHelper.getWebsocketUrl()), ); @@ -46,10 +40,8 @@ export class WebSocketServer this.webSocketServer.addListener("connection", this.wsOnConnection.bind(this)); } - protected getRandomisedMessage(): string - { - if (this.randomUtil.getInt(1, 1000) > 999) - { + protected getRandomisedMessage(): string { + if (this.randomUtil.getInt(1, 1000) > 999) { return this.localisationService.getRandomTextThatMatchesPartialKey("server_start_meme_"); } @@ -58,19 +50,16 @@ export class WebSocketServer : this.localisationService.getText("server_start_success"); } - protected wsOnConnection(ws: WebSocket, req: IncomingMessage): void - { + protected wsOnConnection(ws: WebSocket, req: IncomingMessage): void { const socketHandlers = this.webSocketConnectionHandlers.filter((wsh) => req.url.includes(wsh.getHookUrl())); - if ((socketHandlers?.length ?? 0) === 0) - { + if ((socketHandlers?.length ?? 0) === 0) { const message = `Socket connection received for url ${req.url}, but there is not websocket handler configured for it`; this.logger.warning(message); ws.send(this.jsonUtil.serialize({ error: message })); ws.close(); return; } - socketHandlers.forEach((wsh) => - { + socketHandlers.forEach((wsh) => { wsh.onConnection(ws, req); this.logger.info(`WebSocketHandler "${wsh.getSocketId()}" connected`); }); diff --git a/project/src/servers/http/HttpMethods.ts b/project/src/servers/http/HttpMethods.ts index 031ca7c1..a57c51e8 100644 --- a/project/src/servers/http/HttpMethods.ts +++ b/project/src/servers/http/HttpMethods.ts @@ -1,5 +1,4 @@ -export enum HttpMethods -{ +export enum HttpMethods { OPTIONS = "OPTIONS", GET = "GET", POST = "POST", diff --git a/project/src/servers/http/IHttpListener.ts b/project/src/servers/http/IHttpListener.ts index 9699f4d5..33952b57 100644 --- a/project/src/servers/http/IHttpListener.ts +++ b/project/src/servers/http/IHttpListener.ts @@ -1,7 +1,6 @@ import { IncomingMessage, ServerResponse } from "node:http"; -export interface IHttpListener -{ - canHandle(sessionId: string, req: IncomingMessage): boolean - handle(sessionId: string, req: IncomingMessage, resp: ServerResponse): Promise +export interface IHttpListener { + canHandle(sessionId: string, req: IncomingMessage): boolean; + handle(sessionId: string, req: IncomingMessage, resp: ServerResponse): Promise; } diff --git a/project/src/servers/http/SptHttpListener.ts b/project/src/servers/http/SptHttpListener.ts index 9a863ef3..10fb2187 100644 --- a/project/src/servers/http/SptHttpListener.ts +++ b/project/src/servers/http/SptHttpListener.ts @@ -1,6 +1,5 @@ import { IncomingHttpHeaders, IncomingMessage, ServerResponse } from "node:http"; import zlib from "node:zlib"; -import { inject, injectAll, injectable } from "tsyringe"; import { Serializer } from "@spt/di/Serializer"; import { ILogger } from "@spt/models/spt/utils/ILogger"; import { HttpRouter } from "@spt/routers/HttpRouter"; @@ -8,10 +7,10 @@ import { IHttpListener } from "@spt/servers/http/IHttpListener"; import { LocalisationService } from "@spt/services/LocalisationService"; import { HttpResponseUtil } from "@spt/utils/HttpResponseUtil"; import { JsonUtil } from "@spt/utils/JsonUtil"; +import { inject, injectAll, injectable } from "tsyringe"; @injectable() -export class SptHttpListener implements IHttpListener -{ +export class SptHttpListener implements IHttpListener { constructor( @inject("HttpRouter") protected httpRouter: HttpRouter, // TODO: delay required @injectAll("Serializer") protected serializers: Serializer[], @@ -20,28 +19,22 @@ export class SptHttpListener implements IHttpListener @inject("JsonUtil") protected jsonUtil: JsonUtil, @inject("HttpResponseUtil") protected httpResponse: HttpResponseUtil, @inject("LocalisationService") protected localisationService: LocalisationService, - ) - {} + ) {} - public canHandle(_: string, req: IncomingMessage): boolean - { + public canHandle(_: string, req: IncomingMessage): boolean { return ["GET", "PUT", "POST"].includes(req.method); } - public async handle(sessionId: string, req: IncomingMessage, resp: ServerResponse): Promise - { - switch (req.method) - { - case "GET": - { + public async handle(sessionId: string, req: IncomingMessage, resp: ServerResponse): Promise { + switch (req.method) { + case "GET": { const response = await this.getResponse(sessionId, req, undefined); this.sendResponse(sessionId, req, resp, undefined, response); break; } // these are handled almost identically. case "POST": - case "PUT": - { + case "PUT": { // Data can come in chunks. Notably, if someone saves their profile (which can be // kinda big), on a slow connection. We need to re-assemble the entire http payload // before processing it. @@ -50,14 +43,12 @@ export class SptHttpListener implements IHttpListener const buffer = Buffer.alloc(requestLength); let written = 0; - req.on("data", (data: any) => - { + req.on("data", (data: any) => { data.copy(buffer, written, 0); written += data.length; }); - req.on("end", async () => - { + req.on("end", async () => { // Contrary to reasonable expectations, the content-encoding is _not_ actually used to // determine if the payload is compressed. All PUT requests are, and POST requests without // debug = 1 are as well. This should be fixed. @@ -66,8 +57,7 @@ export class SptHttpListener implements IHttpListener const requestCompressed = req.method === "PUT" || requestIsCompressed; const value = requestCompressed ? zlib.inflateSync(buffer) : buffer; - if (!requestIsCompressed) - { + if (!requestIsCompressed) { this.logger.debug(value.toString(), true); } @@ -78,8 +68,7 @@ export class SptHttpListener implements IHttpListener break; } - default: - { + default: { this.logger.warning(`${this.localisationService.getText("unknown_request")}: ${req.method}`); break; } @@ -100,45 +89,37 @@ export class SptHttpListener implements IHttpListener resp: ServerResponse, body: Buffer, output: string, - ): void - { + ): void { const info = this.getBodyInfo(body); let handled = false; // Check if this is a debug request, if so just send the raw response without transformation - if (req.headers.responsecompressed === "0") - { + if (req.headers.responsecompressed === "0") { this.sendJson(resp, output, sessionID); } // Attempt to use one of our serializers to do the job - for (const serializer of this.serializers) - { - if (serializer.canHandle(output)) - { + for (const serializer of this.serializers) { + if (serializer.canHandle(output)) { serializer.serialize(sessionID, req, resp, info); handled = true; break; } } // If no serializer can handle the request we zlib the output and send it - if (!handled) - { + if (!handled) { this.sendZlibJson(resp, output, sessionID); } - if (globalThis.G_LOG_REQUESTS) - { + if (globalThis.G_LOG_REQUESTS) { const log = new Response(req.method, output); this.requestsLogger.info(`RESPONSE=${this.jsonUtil.serialize(log)}`); } } - public async getResponse(sessionID: string, req: IncomingMessage, body: Buffer): Promise - { + public async getResponse(sessionID: string, req: IncomingMessage, body: Buffer): Promise { const info = this.getBodyInfo(body, req.url); - if (globalThis.G_LOG_REQUESTS) - { + if (globalThis.G_LOG_REQUESTS) { // Parse quest info into object const data = typeof info === "object" ? info : this.jsonUtil.deserialize(info); @@ -148,58 +129,48 @@ export class SptHttpListener implements IHttpListener let output = await this.httpRouter.getResponse(req, info, sessionID); /* route doesn't exist or response is not properly set up */ - if (!output) - { + if (!output) { this.logger.error(this.localisationService.getText("unhandled_response", req.url)); this.logger.info(info); - output = ( this.httpResponse.getBody(undefined, 404, `UNHANDLED RESPONSE: ${req.url}`)); + output = (this.httpResponse.getBody(undefined, 404, `UNHANDLED RESPONSE: ${req.url}`)); } return output; } - protected getBodyInfo(body: Buffer, requestUrl = undefined): any - { + protected getBodyInfo(body: Buffer, requestUrl = undefined): any { const text = body ? body.toString() : "{}"; const info = text ? this.jsonUtil.deserialize(text, requestUrl) : {}; return info; } - public sendJson(resp: ServerResponse, output: string, sessionID: string): void - { + public sendJson(resp: ServerResponse, output: string, sessionID: string): void { resp.writeHead(200, "OK", { "Content-Type": "application/json", "Set-Cookie": `PHPSESSID=${sessionID}` }); resp.end(output); } - public sendZlibJson(resp: ServerResponse, output: string, sessionID: string): void - { + public sendZlibJson(resp: ServerResponse, output: string, sessionID: string): void { zlib.deflate(output, (_, buf) => resp.end(buf)); } } -class RequestData -{ +class RequestData { constructor( public url: string, public headers: IncomingHttpHeaders, public data?: any, - ) - {} + ) {} } -class Request -{ +class Request { constructor( public type: string, public req: RequestData, - ) - {} + ) {} } -class Response -{ +class Response { constructor( public type: string, public response: any, - ) - {} + ) {} } diff --git a/project/src/servers/ws/IWebSocketConnectionHandler.ts b/project/src/servers/ws/IWebSocketConnectionHandler.ts index 82afa91f..9a5925c8 100644 --- a/project/src/servers/ws/IWebSocketConnectionHandler.ts +++ b/project/src/servers/ws/IWebSocketConnectionHandler.ts @@ -1,9 +1,8 @@ import { IncomingMessage } from "node:http"; import { WebSocket } from "ws"; -export interface IWebSocketConnectionHandler -{ - getSocketId(): string - getHookUrl(): string - onConnection(ws: WebSocket, req: IncomingMessage): void +export interface IWebSocketConnectionHandler { + getSocketId(): string; + getHookUrl(): string; + onConnection(ws: WebSocket, req: IncomingMessage): void; } diff --git a/project/src/servers/ws/SptWebSocketConnectionHandler.ts b/project/src/servers/ws/SptWebSocketConnectionHandler.ts index 82418a26..cf5ea177 100644 --- a/project/src/servers/ws/SptWebSocketConnectionHandler.ts +++ b/project/src/servers/ws/SptWebSocketConnectionHandler.ts @@ -1,6 +1,4 @@ import { IncomingMessage } from "http"; -import { inject, injectAll, injectable } from "tsyringe"; -import { WebSocket } from "ws"; import { ProfileHelper } from "@spt/helpers/ProfileHelper"; import { IWsNotificationEvent } from "@spt/models/eft/ws/IWsNotificationEvent"; import { ConfigTypes } from "@spt/models/enums/ConfigTypes"; @@ -12,10 +10,11 @@ import { IWebSocketConnectionHandler } from "@spt/servers/ws/IWebSocketConnectio import { ISptWebSocketMessageHandler } from "@spt/servers/ws/message/ISptWebSocketMessageHandler"; import { LocalisationService } from "@spt/services/LocalisationService"; import { JsonUtil } from "@spt/utils/JsonUtil"; +import { inject, injectAll, injectable } from "tsyringe"; +import { WebSocket } from "ws"; @injectable() -export class SptWebSocketConnectionHandler implements IWebSocketConnectionHandler -{ +export class SptWebSocketConnectionHandler implements IWebSocketConnectionHandler { protected httpConfig: IHttpConfig; protected webSockets: Map = new Map(); protected defaultNotification: IWsNotificationEvent = { type: NotificationEventType.PING, eventId: "ping" }; @@ -28,23 +27,19 @@ export class SptWebSocketConnectionHandler implements IWebSocketConnectionHandle @inject("ConfigServer") protected configServer: ConfigServer, @inject("JsonUtil") protected jsonUtil: JsonUtil, @injectAll("SptWebSocketMessageHandler") protected sptWebSocketMessageHandlers: ISptWebSocketMessageHandler[], - ) - { + ) { this.httpConfig = this.configServer.getConfig(ConfigTypes.HTTP); } - public getSocketId(): string - { + public getSocketId(): string { return "SPT WebSocket Handler"; } - public getHookUrl(): string - { + public getHookUrl(): string { return "/notifierServer/getwebsocket/"; } - public onConnection(ws: WebSocket, req: IncomingMessage): void - { + public onConnection(ws: WebSocket, req: IncomingMessage): void { // Strip request and break it into sections const splitUrl = req.url.substring(0, req.url.indexOf("?")).split("/"); const sessionID = splitUrl.pop(); @@ -56,23 +51,22 @@ export class SptWebSocketConnectionHandler implements IWebSocketConnectionHandle // throw new Error("Method not implemented."); this.webSockets.set(sessionID, ws); - if (this.websocketPingHandler) - { + if (this.websocketPingHandler) { clearInterval(this.websocketPingHandler); } - ws.on("message", (msg) => this.sptWebSocketMessageHandlers.forEach((wsmh) => wsmh.onSptMessage(sessionID, this.webSockets.get(sessionID), msg))); + ws.on("message", (msg) => + this.sptWebSocketMessageHandlers.forEach((wsmh) => + wsmh.onSptMessage(sessionID, this.webSockets.get(sessionID), msg), + ), + ); - this.websocketPingHandler = setInterval(() => - { + this.websocketPingHandler = setInterval(() => { this.logger.debug(this.localisationService.getText("websocket-pinging_player", sessionID)); - if (ws.readyState === WebSocket.OPEN) - { + if (ws.readyState === WebSocket.OPEN) { ws.send(this.jsonUtil.serialize(this.defaultNotification)); - } - else - { + } else { this.logger.debug(this.localisationService.getText("websocket-socket_lost_deleting_handle")); clearInterval(this.websocketPingHandler); this.webSockets.delete(sessionID); @@ -80,33 +74,24 @@ export class SptWebSocketConnectionHandler implements IWebSocketConnectionHandle }, this.httpConfig.webSocketPingDelayMs); } - public sendMessage(sessionID: string, output: IWsNotificationEvent): void - { - try - { - if (this.isConnectionWebSocket(sessionID)) - { + public sendMessage(sessionID: string, output: IWsNotificationEvent): void { + try { + if (this.isConnectionWebSocket(sessionID)) { this.webSockets.get(sessionID).send(this.jsonUtil.serialize(output)); this.logger.debug(this.localisationService.getText("websocket-message_sent")); - } - else - { + } else { this.logger.debug(this.localisationService.getText("websocket-not_ready_message_not_sent", sessionID)); } - } - catch (err) - { + } catch (err) { this.logger.error(this.localisationService.getText("websocket-message_send_failed_with_error", err)); } } - public isConnectionWebSocket(sessionID: string): boolean - { + public isConnectionWebSocket(sessionID: string): boolean { return this.webSockets.has(sessionID) && this.webSockets.get(sessionID).readyState === WebSocket.OPEN; } - public getSessionWebSocket(sessionID: string): WebSocket - { + public getSessionWebSocket(sessionID: string): WebSocket { return this.webSockets[sessionID]; } } diff --git a/project/src/servers/ws/message/DefaultSptWebSocketMessageHandler.ts b/project/src/servers/ws/message/DefaultSptWebSocketMessageHandler.ts index a1ffdabe..91da6a9b 100644 --- a/project/src/servers/ws/message/DefaultSptWebSocketMessageHandler.ts +++ b/project/src/servers/ws/message/DefaultSptWebSocketMessageHandler.ts @@ -1,16 +1,13 @@ -import { inject, injectable } from "tsyringe"; -import { RawData, WebSocket } from "ws"; import { ILogger } from "@spt/models/spt/utils/ILogger"; import { ISptWebSocketMessageHandler } from "@spt/servers/ws/message/ISptWebSocketMessageHandler"; +import { inject, injectable } from "tsyringe"; +import { RawData, WebSocket } from "ws"; @injectable() -export class DefaultSptWebSocketMessageHandler implements ISptWebSocketMessageHandler -{ - constructor(@inject("PrimaryLogger") protected logger: ILogger) - {} +export class DefaultSptWebSocketMessageHandler implements ISptWebSocketMessageHandler { + constructor(@inject("PrimaryLogger") protected logger: ILogger) {} - public onSptMessage(sessionId: string, client: WebSocket, message: RawData): void - { + public onSptMessage(sessionId: string, client: WebSocket, message: RawData): void { this.logger.debug(`[${sessionId}] SPT message received: ${message}`); } } diff --git a/project/src/servers/ws/message/ISptWebSocketMessageHandler.ts b/project/src/servers/ws/message/ISptWebSocketMessageHandler.ts index ddc7cfec..4553959d 100644 --- a/project/src/servers/ws/message/ISptWebSocketMessageHandler.ts +++ b/project/src/servers/ws/message/ISptWebSocketMessageHandler.ts @@ -1,6 +1,5 @@ import { RawData, WebSocket } from "ws"; -export interface ISptWebSocketMessageHandler -{ - onSptMessage(sessionID: string, client: WebSocket, message: RawData): void +export interface ISptWebSocketMessageHandler { + onSptMessage(sessionID: string, client: WebSocket, message: RawData): void; } diff --git a/project/src/services/AirdropService.ts b/project/src/services/AirdropService.ts index 1b455e8f..53e7e703 100644 --- a/project/src/services/AirdropService.ts +++ b/project/src/services/AirdropService.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { LootGenerator } from "@spt/generators/LootGenerator"; import { ItemHelper } from "@spt/helpers/ItemHelper"; import { WeightedRandomHelper } from "@spt/helpers/WeightedRandomHelper"; @@ -14,12 +13,12 @@ import { ConfigServer } from "@spt/servers/ConfigServer"; import { DatabaseService } from "@spt/services/DatabaseService"; import { ItemFilterService } from "@spt/services/ItemFilterService"; import { LocalisationService } from "@spt/services/LocalisationService"; -import { ICloner } from "@spt/utils/cloners/ICloner"; import { HashUtil } from "@spt/utils/HashUtil"; +import { ICloner } from "@spt/utils/cloners/ICloner"; +import { inject, injectable } from "tsyringe"; @injectable() -export class AirdropService -{ +export class AirdropService { protected airdropConfig: IAirdropConfig; constructor( @@ -33,8 +32,7 @@ export class AirdropService @inject("DatabaseService") protected databaseService: DatabaseService, @inject("ConfigServer") protected configServer: ConfigServer, @inject("PrimaryCloner") protected cloner: ICloner, - ) - { + ) { this.airdropConfig = this.configServer.getConfig(ConfigTypes.AIRDROP); } @@ -44,8 +42,7 @@ export class AirdropService * Generates it randomly based on config/airdrop.json values * @returns Array of LootItem objects */ - public generateAirdropLoot(): IGetAirdropLootResponse - { + public generateAirdropLoot(): IGetAirdropLootResponse { const airdropType = this.chooseAirdropType(); this.logger.debug(`Chose ${airdropType} for airdrop loot`); @@ -62,17 +59,14 @@ export class AirdropService crateLoot.unshift(airdropCrateItem); // Reparent loot items to create we added above - for (const item of crateLoot) - { - if (item._id == airdropCrateItem._id) - { + for (const item of crateLoot) { + if (item._id == airdropCrateItem._id) { // Crate itself, don't alter continue; } // no parentId = root item, make item have create as parent - if (!item.parentId) - { + if (!item.parentId) { item.parentId = airdropCrateItem._id; item.slotId = "main"; } @@ -86,8 +80,7 @@ export class AirdropService * @param airdropType What tpye of container: weapon/common etc * @returns Item */ - protected getAirdropCrateItem(airdropType: AirdropTypeEnum): Item - { + protected getAirdropCrateItem(airdropType: AirdropTypeEnum): Item { const airdropContainer = { _id: this.hashUtil.generate(), _tpl: "", // picked later @@ -97,8 +90,7 @@ export class AirdropService }, }; - switch (airdropType) - { + switch (airdropType) { case AirdropTypeEnum.MEDICAL: airdropContainer._tpl = ItemTpl.LOOTCONTAINER_AIRDROP_MEDICAL_CRATE; break; @@ -121,8 +113,7 @@ export class AirdropService * Randomly pick a type of airdrop loot using weighted values from config * @returns airdrop type value */ - protected chooseAirdropType(): AirdropTypeEnum - { + protected chooseAirdropType(): AirdropTypeEnum { const possibleAirdropTypes = this.airdropConfig.airdropTypeWeightings; return this.weightedRandomHelper.getWeightedValue(possibleAirdropTypes); @@ -133,11 +124,9 @@ export class AirdropService * @param airdropType Type of airdrop to get settings for * @returns LootRequest */ - protected getAirdropLootConfigByType(airdropType: AirdropTypeEnum): LootRequest - { + protected getAirdropLootConfigByType(airdropType: AirdropTypeEnum): LootRequest { let lootSettingsByType: AirdropLoot = this.airdropConfig.loot[airdropType]; - if (!lootSettingsByType) - { + if (!lootSettingsByType) { this.logger.error( this.localisationService.getText("location-unable_to_find_airdrop_drop_config_of_type", airdropType), ); diff --git a/project/src/services/BotEquipmentFilterService.ts b/project/src/services/BotEquipmentFilterService.ts index f0f7eaf8..aefb6dc0 100644 --- a/project/src/services/BotEquipmentFilterService.ts +++ b/project/src/services/BotEquipmentFilterService.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { BotHelper } from "@spt/helpers/BotHelper"; import { ProfileHelper } from "@spt/helpers/ProfileHelper"; import { @@ -19,10 +18,10 @@ import { } from "@spt/models/spt/config/IBotConfig"; import { ILogger } from "@spt/models/spt/utils/ILogger"; import { ConfigServer } from "@spt/servers/ConfigServer"; +import { inject, injectable } from "tsyringe"; @injectable() -export class BotEquipmentFilterService -{ +export class BotEquipmentFilterService { protected botConfig: IBotConfig; protected botEquipmentConfig: Record; @@ -31,8 +30,7 @@ export class BotEquipmentFilterService @inject("BotHelper") protected botHelper: BotHelper, @inject("ProfileHelper") protected profileHelper: ProfileHelper, @inject("ConfigServer") protected configServer: ConfigServer, - ) - { + ) { this.botConfig = this.configServer.getConfig(ConfigTypes.BOT); this.botEquipmentConfig = this.botConfig.equipment; } @@ -49,8 +47,7 @@ export class BotEquipmentFilterService baseBotNode: IBotType, botLevel: number, botGenerationDetails: BotGenerationDetails, - ): void - { + ): void { const pmcProfile = this.profileHelper.getPmcProfile(sessionId); const botRole = botGenerationDetails.isPmc ? "pmc" : botGenerationDetails.role; @@ -65,28 +62,24 @@ export class BotEquipmentFilterService const botEquipConfig = this.botConfig.equipment[botRole]; const randomisationDetails = this.botHelper.getBotRandomizationDetails(botLevel, botEquipConfig); - if (botEquipmentBlacklist || botEquipmentWhitelist) - { + if (botEquipmentBlacklist || botEquipmentWhitelist) { this.filterEquipment(baseBotNode, botEquipmentBlacklist, botEquipmentWhitelist); this.filterCartridges(baseBotNode, botEquipmentBlacklist, botEquipmentWhitelist); } - if (botWeightingAdjustments) - { + if (botWeightingAdjustments) { this.adjustWeighting(botWeightingAdjustments?.equipment, baseBotNode.inventory.equipment); this.adjustWeighting(botWeightingAdjustments?.ammo, baseBotNode.inventory.Ammo); // Dont warn when edited item not found, we're editing usec/bear clothing and they dont have each others clothing this.adjustWeighting(botWeightingAdjustments?.clothing, baseBotNode.appearance, false); } - if (botWeightingAdjustmentsByPlayerLevel) - { + if (botWeightingAdjustmentsByPlayerLevel) { this.adjustWeighting(botWeightingAdjustmentsByPlayerLevel?.equipment, baseBotNode.inventory.equipment); this.adjustWeighting(botWeightingAdjustmentsByPlayerLevel?.ammo, baseBotNode.inventory.Ammo); } - if (randomisationDetails) - { + if (randomisationDetails) { this.adjustChances(randomisationDetails?.equipment, baseBotNode.chances.equipment); this.adjustChances(randomisationDetails?.weaponMods, baseBotNode.chances.weaponMods); this.adjustChances(randomisationDetails?.equipmentMods, baseBotNode.chances.equipmentMods); @@ -102,15 +95,12 @@ export class BotEquipmentFilterService protected adjustChances( equipmentChanges: Record, baseValues: EquipmentChances | ModsChances, - ): void - { - if (!equipmentChanges) - { + ): void { + if (!equipmentChanges) { return; } - for (const itemKey in equipmentChanges) - { + for (const itemKey in equipmentChanges) { baseValues[itemKey] = equipmentChanges[itemKey]; } } @@ -123,15 +113,12 @@ export class BotEquipmentFilterService protected adjustGenerationChances( generationChanges: Record, baseBotGeneration: Generation, - ): void - { - if (!generationChanges) - { + ): void { + if (!generationChanges) { return; } - for (const itemKey in generationChanges) - { + for (const itemKey in generationChanges) { baseBotGeneration.items[itemKey].weights = generationChanges[itemKey].weights; baseBotGeneration.items[itemKey].whitelist = generationChanges[itemKey].whitelist; } @@ -142,8 +129,7 @@ export class BotEquipmentFilterService * @param botEquipmentRole equipment role to return * @returns EquipmentFilters object */ - public getBotEquipmentSettings(botEquipmentRole: string): EquipmentFilters - { + public getBotEquipmentSettings(botEquipmentRole: string): EquipmentFilters { return this.botEquipmentConfig[botEquipmentRole]; } @@ -152,12 +138,10 @@ export class BotEquipmentFilterService * @param botEquipmentRole equipment role of bot to look up * @returns Dictionary of weapon type and their whitelisted scope types */ - public getBotWeaponSightWhitelist(botEquipmentRole: string): Record | undefined - { + public getBotWeaponSightWhitelist(botEquipmentRole: string): Record | undefined { const botEquipmentSettings = this.botEquipmentConfig[botEquipmentRole]; - if (!botEquipmentSettings) - { + if (!botEquipmentSettings) { return undefined; } @@ -170,17 +154,15 @@ export class BotEquipmentFilterService * @param playerLevel Level of the player * @returns EquipmentBlacklistDetails object */ - public getBotEquipmentBlacklist(botRole: string, playerLevel: number): EquipmentFilterDetails | undefined - { + public getBotEquipmentBlacklist(botRole: string, playerLevel: number): EquipmentFilterDetails | undefined { const blacklistDetailsForBot = this.botEquipmentConfig[botRole]; // No equipment blacklist found, skip if ( - !blacklistDetailsForBot - || Object.keys(blacklistDetailsForBot).length === 0 - || !blacklistDetailsForBot.blacklist - ) - { + !blacklistDetailsForBot || + Object.keys(blacklistDetailsForBot).length === 0 || + !blacklistDetailsForBot.blacklist + ) { return undefined; } @@ -195,13 +177,11 @@ export class BotEquipmentFilterService * @param playerLevel Players level * @returns EquipmentFilterDetails object */ - protected getBotEquipmentWhitelist(botRole: string, playerLevel: number): EquipmentFilterDetails | undefined - { + protected getBotEquipmentWhitelist(botRole: string, playerLevel: number): EquipmentFilterDetails | undefined { const botEquipmentConfig = this.botEquipmentConfig[botRole]; // No equipment blacklist found, skip - if (!botEquipmentConfig || Object.keys(botEquipmentConfig).length === 0 || !botEquipmentConfig.whitelist) - { + if (!botEquipmentConfig || Object.keys(botEquipmentConfig).length === 0 || !botEquipmentConfig.whitelist) { return undefined; } @@ -216,17 +196,15 @@ export class BotEquipmentFilterService * @param botLevel Level of bot * @returns Weighting adjustments for bot items */ - protected getBotWeightingAdjustments(botRole: string, botLevel: number): WeightingAdjustmentDetails | undefined - { + protected getBotWeightingAdjustments(botRole: string, botLevel: number): WeightingAdjustmentDetails | undefined { const botEquipmentConfig = this.botEquipmentConfig[botRole]; // No config found, skip if ( - !botEquipmentConfig - || Object.keys(botEquipmentConfig).length === 0 - || !botEquipmentConfig.weightingAdjustmentsByBotLevel - ) - { + !botEquipmentConfig || + Object.keys(botEquipmentConfig).length === 0 || + !botEquipmentConfig.weightingAdjustmentsByBotLevel + ) { return undefined; } @@ -244,17 +222,15 @@ export class BotEquipmentFilterService protected getBotWeightingAdjustmentsByPlayerLevel( botRole: string, playerlevel: number, - ): WeightingAdjustmentDetails | undefined - { + ): WeightingAdjustmentDetails | undefined { const botEquipmentConfig = this.botEquipmentConfig[botRole]; // No config found, skip if ( - !botEquipmentConfig - || Object.keys(botEquipmentConfig).length === 0 - || !botEquipmentConfig.weightingAdjustmentsByPlayerLevel - ) - { + !botEquipmentConfig || + Object.keys(botEquipmentConfig).length === 0 || + !botEquipmentConfig.weightingAdjustmentsByPlayerLevel + ) { return undefined; } @@ -274,27 +250,21 @@ export class BotEquipmentFilterService baseBotNode: IBotType, blacklist: EquipmentFilterDetails, whitelist: EquipmentFilterDetails, - ): void - { - if (whitelist) - { - for (const equipmentSlotKey in baseBotNode.inventory.equipment) - { + ): void { + if (whitelist) { + for (const equipmentSlotKey in baseBotNode.inventory.equipment) { const botEquipment = baseBotNode.inventory.equipment[equipmentSlotKey]; // Skip equipment slot if whitelist doesn't exist / is empty const whitelistEquipmentForSlot = whitelist.equipment[equipmentSlotKey]; - if (!whitelistEquipmentForSlot || Object.keys(whitelistEquipmentForSlot).length === 0) - { + if (!whitelistEquipmentForSlot || Object.keys(whitelistEquipmentForSlot).length === 0) { continue; } // Filter equipment slot items to just items in whitelist baseBotNode.inventory.equipment[equipmentSlotKey] = {}; - for (const key of Object.keys(botEquipment)) - { - if (whitelistEquipmentForSlot.includes(key)) - { + for (const key of Object.keys(botEquipment)) { + if (whitelistEquipmentForSlot.includes(key)) { baseBotNode.inventory.equipment[equipmentSlotKey][key] = botEquipment[key]; } } @@ -303,25 +273,20 @@ export class BotEquipmentFilterService return; } - if (blacklist) - { - for (const equipmentSlotKey in baseBotNode.inventory.equipment) - { + if (blacklist) { + for (const equipmentSlotKey in baseBotNode.inventory.equipment) { const botEquipment = baseBotNode.inventory.equipment[equipmentSlotKey]; // Skip equipment slot if blacklist doesn't exist / is empty const equipmentSlotBlacklist = blacklist.equipment[equipmentSlotKey]; - if (!equipmentSlotBlacklist || Object.keys(equipmentSlotBlacklist).length === 0) - { + if (!equipmentSlotBlacklist || Object.keys(equipmentSlotBlacklist).length === 0) { continue; } // Filter equipment slot items to just items not in blacklist baseBotNode.inventory.equipment[equipmentSlotKey] = {}; - for (const key of Object.keys(botEquipment)) - { - if (!equipmentSlotBlacklist.includes(key)) - { + for (const key of Object.keys(botEquipment)) { + if (!equipmentSlotBlacklist.includes(key)) { baseBotNode.inventory.equipment[equipmentSlotKey][key] = botEquipment[key]; } } @@ -341,27 +306,21 @@ export class BotEquipmentFilterService baseBotNode: IBotType, blacklist: EquipmentFilterDetails, whitelist: EquipmentFilterDetails, - ): void - { - if (whitelist) - { - for (const ammoCaliberKey in baseBotNode.inventory.Ammo) - { + ): void { + if (whitelist) { + for (const ammoCaliberKey in baseBotNode.inventory.Ammo) { const botAmmo = baseBotNode.inventory.Ammo[ammoCaliberKey]; // Skip cartridge slot if whitelist doesn't exist / is empty const whiteListedCartridgesForCaliber = whitelist.cartridge[ammoCaliberKey]; - if (!whiteListedCartridgesForCaliber || Object.keys(whiteListedCartridgesForCaliber).length === 0) - { + if (!whiteListedCartridgesForCaliber || Object.keys(whiteListedCartridgesForCaliber).length === 0) { continue; } // Filter calibre slot items to just items in whitelist baseBotNode.inventory.Ammo[ammoCaliberKey] = {}; - for (const key of Object.keys(botAmmo)) - { - if (whitelist.cartridge[ammoCaliberKey].includes(key)) - { + for (const key of Object.keys(botAmmo)) { + if (whitelist.cartridge[ammoCaliberKey].includes(key)) { baseBotNode.inventory.Ammo[ammoCaliberKey][key] = botAmmo[key]; } } @@ -370,25 +329,20 @@ export class BotEquipmentFilterService return; } - if (blacklist) - { - for (const ammoCaliberKey in baseBotNode.inventory.Ammo) - { + if (blacklist) { + for (const ammoCaliberKey in baseBotNode.inventory.Ammo) { const botAmmo = baseBotNode.inventory.Ammo[ammoCaliberKey]; // Skip cartridge slot if blacklist doesn't exist / is empty const cartridgeCaliberBlacklist = blacklist.cartridge[ammoCaliberKey]; - if (!cartridgeCaliberBlacklist || Object.keys(cartridgeCaliberBlacklist).length === 0) - { + if (!cartridgeCaliberBlacklist || Object.keys(cartridgeCaliberBlacklist).length === 0) { continue; } // Filter cartridge slot items to just items not in blacklist baseBotNode.inventory.Ammo[ammoCaliberKey] = {}; - for (const key of Object.keys(botAmmo)) - { - if (!cartridgeCaliberBlacklist.includes(key)) - { + for (const key of Object.keys(botAmmo)) { + if (!cartridgeCaliberBlacklist.includes(key)) { baseBotNode.inventory.Ammo[ammoCaliberKey][key] = botAmmo[key]; } } @@ -405,41 +359,29 @@ export class BotEquipmentFilterService weightingAdjustments: IAdjustmentDetails, botItemPool: Record, showEditWarnings = true, - ): void - { - if (!weightingAdjustments) - { + ): void { + if (!weightingAdjustments) { return; } - if (weightingAdjustments.add && Object.keys(weightingAdjustments.add).length > 0) - { - for (const poolAdjustmentKey in weightingAdjustments.add) - { + if (weightingAdjustments.add && Object.keys(weightingAdjustments.add).length > 0) { + for (const poolAdjustmentKey in weightingAdjustments.add) { const locationToUpdate = botItemPool[poolAdjustmentKey]; - for (const itemToAddKey in weightingAdjustments.add[poolAdjustmentKey]) - { + for (const itemToAddKey in weightingAdjustments.add[poolAdjustmentKey]) { locationToUpdate[itemToAddKey] = weightingAdjustments.add[poolAdjustmentKey][itemToAddKey]; } } } - if (weightingAdjustments.edit && Object.keys(weightingAdjustments.edit).length > 0) - { - for (const poolAdjustmentKey in weightingAdjustments.edit) - { + if (weightingAdjustments.edit && Object.keys(weightingAdjustments.edit).length > 0) { + for (const poolAdjustmentKey in weightingAdjustments.edit) { const locationToUpdate = botItemPool[poolAdjustmentKey]; - for (const itemToEditKey in weightingAdjustments.edit[poolAdjustmentKey]) - { + for (const itemToEditKey in weightingAdjustments.edit[poolAdjustmentKey]) { // Only make change if item exists as we're editing, not adding - if (locationToUpdate[itemToEditKey] || locationToUpdate[itemToEditKey] === 0) - { + if (locationToUpdate[itemToEditKey] || locationToUpdate[itemToEditKey] === 0) { locationToUpdate[itemToEditKey] = weightingAdjustments.edit[poolAdjustmentKey][itemToEditKey]; - } - else - { - if (showEditWarnings) - { + } else { + if (showEditWarnings) { this.logger.debug( `Tried to edit a non-existent item for slot: ${poolAdjustmentKey} ${itemToEditKey}`, ); diff --git a/project/src/services/BotEquipmentModPoolService.ts b/project/src/services/BotEquipmentModPoolService.ts index d991ac67..59e4f114 100644 --- a/project/src/services/BotEquipmentModPoolService.ts +++ b/project/src/services/BotEquipmentModPoolService.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { ItemHelper } from "@spt/helpers/ItemHelper"; import { Mods } from "@spt/models/eft/common/tables/IBotType"; import { ITemplateItem } from "@spt/models/eft/common/tables/ITemplateItem"; @@ -10,11 +9,11 @@ import { ConfigServer } from "@spt/servers/ConfigServer"; import { DatabaseService } from "@spt/services/DatabaseService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { VFS } from "@spt/utils/VFS"; +import { inject, injectable } from "tsyringe"; /** Store a mapping between weapons, their slots and the items that fit those slots */ @injectable() -export class BotEquipmentModPoolService -{ +export class BotEquipmentModPoolService { protected botConfig: IBotConfig; protected weaponModPool: Mods = {}; protected gearModPool: Mods = {}; @@ -28,8 +27,7 @@ export class BotEquipmentModPoolService @inject("DatabaseService") protected databaseService: DatabaseService, @inject("LocalisationService") protected localisationService: LocalisationService, @inject("ConfigServer") protected configServer: ConfigServer, - ) - { + ) { this.botConfig = this.configServer.getConfig(ConfigTypes.BOT); } @@ -37,10 +35,8 @@ export class BotEquipmentModPoolService * Store dictionary of mods for each item passed in * @param items items to find related mods and store in modPool */ - protected generatePool(items: ITemplateItem[], poolType: string): void - { - if (!items) - { + protected generatePool(items: ITemplateItem[], poolType: string): void { + if (!items) { this.logger.error(this.localisationService.getText("bot-unable_to_generate_item_pool_no_items", poolType)); return; @@ -48,10 +44,8 @@ export class BotEquipmentModPoolService // Get weapon or gear pool const pool = poolType === "weapon" ? this.weaponModPool : this.gearModPool; - for (const item of items) - { - if (!item._props) - { + for (const item of items) { + if (!item._props) { this.logger.error( this.localisationService.getText("bot-item_missing_props_property", { itemTpl: item._id, @@ -63,43 +57,35 @@ export class BotEquipmentModPoolService } // skip item witout slots - if (!item._props.Slots || item._props.Slots.length === 0) - { + if (!item._props.Slots || item._props.Slots.length === 0) { continue; } // Add tpl to pool when missing - if (!pool[item._id]) - { + if (!pool[item._id]) { pool[item._id] = {}; } // No slots, skip - if (!item._props.Slots) - { + if (!item._props.Slots) { return; } - for (const slot of item._props.Slots) - { + for (const slot of item._props.Slots) { const itemsThatFit = slot._props.filters[0].Filter; - for (const itemToAdd of itemsThatFit) - { - if (!pool[item._id][slot._name]) - { + for (const itemToAdd of itemsThatFit) { + if (!pool[item._id][slot._name]) { pool[item._id][slot._name] = []; } // only add item to pool if it doesnt already exist - if (!pool[item._id][slot._name].some((x) => x === itemToAdd)) - { + if (!pool[item._id][slot._name].some((x) => x === itemToAdd)) { pool[item._id][slot._name].push(itemToAdd); // Check item added into array for slots, need to iterate over those const subItemDetails = this.itemHelper.getItem(itemToAdd)[1]; const hasSubItemsToAdd = subItemDetails?._props?.Slots?.length ?? 0 > 0; - if (hasSubItemsToAdd && !pool[subItemDetails._id]) - { + if (hasSubItemsToAdd && !pool[subItemDetails._id]) { // Recursive call this.generatePool([subItemDetails], poolType); } @@ -112,8 +98,7 @@ export class BotEquipmentModPoolService /** * Empty the mod pool */ - public resetPool(): void - { + public resetPool(): void { this.weaponModPool = {}; } @@ -123,10 +108,8 @@ export class BotEquipmentModPoolService * @param slotName slot to get compatible mods for * @returns tpls that fit the slot */ - public getCompatibleModsForWeaponSlot(itemTpl: string, slotName: string): string[] - { - if (!this.weaponPoolGenerated) - { + public getCompatibleModsForWeaponSlot(itemTpl: string, slotName: string): string[] { + if (!this.weaponPoolGenerated) { // Get every weapon in db and generate mod pool this.generateWeaponPool(); } @@ -140,10 +123,8 @@ export class BotEquipmentModPoolService * @param slotName slot to get compatible mods for * @returns tpls that fit the slot */ - public getCompatibleModsFoGearSlot(itemTpl: string, slotName: string): string[] - { - if (!this.armorPoolGenerated) - { + public getCompatibleModsFoGearSlot(itemTpl: string, slotName: string): string[] { + if (!this.armorPoolGenerated) { this.generateGearPool(); } @@ -155,10 +136,8 @@ export class BotEquipmentModPoolService * @param itemTpl items tpl to look up mods for * @returns Dictionary of mods (keys are mod slot names) with array of compatible mod tpls as value */ - public getModsForGearSlot(itemTpl: string): Record - { - if (!this.armorPoolGenerated) - { + public getModsForGearSlot(itemTpl: string): Record { + if (!this.armorPoolGenerated) { this.generateGearPool(); } @@ -170,10 +149,8 @@ export class BotEquipmentModPoolService * @param itemTpl Weapons tpl to look up mods for * @returns Dictionary of mods (keys are mod slot names) with array of compatible mod tpls as value */ - public getModsForWeaponSlot(itemTpl: string): Record - { - if (!this.weaponPoolGenerated) - { + public getModsForWeaponSlot(itemTpl: string): Record { + if (!this.weaponPoolGenerated) { this.generateWeaponPool(); } @@ -183,8 +160,7 @@ export class BotEquipmentModPoolService /** * Create weapon mod pool and set generated flag to true */ - protected generateWeaponPool(): void - { + protected generateWeaponPool(): void { const weapons = Object.values(this.databaseService.getItems()).filter( (item) => item._type === "Item" && this.itemHelper.isOfBaseclass(item._id, BaseClasses.WEAPON), ); @@ -197,12 +173,11 @@ export class BotEquipmentModPoolService /** * Create gear mod pool and set generated flag to true */ - protected generateGearPool(): void - { + protected generateGearPool(): void { const gear = Object.values(this.databaseService.getItems()).filter( (item) => - item._type === "Item" - && this.itemHelper.isOfBaseclasses(item._id, [ + item._type === "Item" && + this.itemHelper.isOfBaseclasses(item._id, [ BaseClasses.ARMORED_EQUIPMENT, BaseClasses.VEST, BaseClasses.ARMOR, diff --git a/project/src/services/BotGenerationCacheService.ts b/project/src/services/BotGenerationCacheService.ts index cb277cf0..49ac5a8a 100644 --- a/project/src/services/BotGenerationCacheService.ts +++ b/project/src/services/BotGenerationCacheService.ts @@ -1,13 +1,12 @@ -import { inject, injectable } from "tsyringe"; import { BotHelper } from "@spt/helpers/BotHelper"; import { IBotBase } from "@spt/models/eft/common/tables/IBotBase"; import { ILogger } from "@spt/models/spt/utils/ILogger"; import { LocalisationService } from "@spt/services/LocalisationService"; import { RandomUtil } from "@spt/utils/RandomUtil"; +import { inject, injectable } from "tsyringe"; @injectable() -export class BotGenerationCacheService -{ +export class BotGenerationCacheService { protected storedBots: Map = new Map(); protected activeBotsInRaid: IBotBase[] = []; @@ -16,23 +15,17 @@ export class BotGenerationCacheService @inject("RandomUtil") protected randomUtil: RandomUtil, @inject("LocalisationService") protected localisationService: LocalisationService, @inject("BotHelper") protected botHelper: BotHelper, - ) - {} + ) {} /** * Store array of bots in cache, shuffle results before storage * @param botsToStore Bots we want to store in the cache */ - public storeBots(key: string, botsToStore: IBotBase[]): void - { - for (const bot of botsToStore) - { - if (this.storedBots.has(key)) - { + public storeBots(key: string, botsToStore: IBotBase[]): void { + for (const bot of botsToStore) { + if (this.storedBots.has(key)) { this.storedBots.get(key).unshift(bot); - } - else - { + } else { this.storedBots.set(key, [bot]); } } @@ -44,13 +37,10 @@ export class BotGenerationCacheService * @param key role to retreive (assault/bossTagilla etc) * @returns IBotBase object */ - public getBot(key: string): IBotBase - { - if (this.storedBots.has(key)) - { + public getBot(key: string): IBotBase { + if (this.storedBots.has(key)) { const cachedOfType = this.storedBots.get(key); - if (cachedOfType.length > 0) - { + if (cachedOfType.length > 0) { return cachedOfType.pop(); } @@ -66,8 +56,7 @@ export class BotGenerationCacheService * Cache a bot that has been sent to the client in memory for later use post-raid to determine if player killed a traitor scav * @param botToStore Bot object to store */ - public storeUsedBot(botToStore: IBotBase): void - { + public storeUsedBot(botToStore: IBotBase): void { this.activeBotsInRaid.push(botToStore); } @@ -77,16 +66,14 @@ export class BotGenerationCacheService * @param profileId Id of bot to get * @returns IBotBase */ - public getUsedBot(profileId: string): IBotBase - { + public getUsedBot(profileId: string): IBotBase { return this.activeBotsInRaid.find((x) => x._id === profileId); } /** * Remove all cached bot profiles from memory */ - public clearStoredBots(): void - { + public clearStoredBots(): void { this.storedBots = new Map(); this.activeBotsInRaid = []; } @@ -95,18 +82,15 @@ export class BotGenerationCacheService * Does cache have a bot with requested key * @returns false if empty */ - public cacheHasBotOfRole(key: string): boolean - { + public cacheHasBotOfRole(key: string): boolean { return this.storedBots.has(key) && this.storedBots.get(key).length > 0; } - public getCachedBotCount(key: string): number - { + public getCachedBotCount(key: string): number { return this.storedBots.get(key)?.length ?? 0; } - public createCacheKey(role: string, difficulty: string): string - { + public createCacheKey(role: string, difficulty: string): string { return `${role.toLowerCase()}${difficulty.toLowerCase()}`; } } diff --git a/project/src/services/BotLootCacheService.ts b/project/src/services/BotLootCacheService.ts index 0846c5b0..4d8132e5 100644 --- a/project/src/services/BotLootCacheService.ts +++ b/project/src/services/BotLootCacheService.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { PMCLootGenerator } from "@spt/generators/PMCLootGenerator"; import { ItemHelper } from "@spt/helpers/ItemHelper"; import { IBotType } from "@spt/models/eft/common/tables/IBotType"; @@ -10,10 +9,10 @@ import { DatabaseServer } from "@spt/servers/DatabaseServer"; import { LocalisationService } from "@spt/services/LocalisationService"; import { RagfairPriceService } from "@spt/services/RagfairPriceService"; import { ICloner } from "@spt/utils/cloners/ICloner"; +import { inject, injectable } from "tsyringe"; @injectable() -export class BotLootCacheService -{ +export class BotLootCacheService { protected lootCache: Record; constructor( @@ -24,16 +23,14 @@ export class BotLootCacheService @inject("LocalisationService") protected localisationService: LocalisationService, @inject("RagfairPriceService") protected ragfairPriceService: RagfairPriceService, @inject("PrimaryCloner") protected cloner: ICloner, - ) - { + ) { this.clearCache(); } /** * Remove cached bot loot data */ - public clearCache(): void - { + public clearCache(): void { this.lootCache = {}; } @@ -50,17 +47,14 @@ export class BotLootCacheService isPmc: boolean, lootType: LootCacheType, botJsonTemplate: IBotType, - ): Record - { - if (!this.botRoleExistsInCache(botRole)) - { + ): Record { + if (!this.botRoleExistsInCache(botRole)) { this.initCacheForBotRole(botRole); this.addLootToCache(botRole, isPmc, botJsonTemplate); } let result = undefined; - switch (lootType) - { + switch (lootType) { case LootCacheType.SPECIAL: result = this.lootCache[botRole].specialItems; break; @@ -120,8 +114,7 @@ export class BotLootCacheService * @param isPmc Is the bot a PMC (alteres what loot is cached) * @param botJsonTemplate db template for bot having its loot generated */ - protected addLootToCache(botRole: string, isPmc: boolean, botJsonTemplate: IBotType): void - { + protected addLootToCache(botRole: string, isPmc: boolean, botJsonTemplate: IBotType): void { // the full pool of loot we use to create the various sub-categories with const lootPool = botJsonTemplate.inventory.items; @@ -133,8 +126,7 @@ export class BotLootCacheService const secureLootTPool: Record = {}; const combinedLootPool: Record = {}; - if (isPmc) - { + 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)); @@ -142,17 +134,14 @@ export class BotLootCacheService } // Backpack/Pockets etc - for (const [slot, pool] of Object.entries(lootPool)) - { + for (const [slot, pool] of Object.entries(lootPool)) { // No items to add, skip - if (Object.keys(pool).length === 0) - { + if (Object.keys(pool).length === 0) { continue; } // Sort loot pool into separate buckets - switch (slot.toLowerCase()) - { + switch (slot.toLowerCase()) { case "specialloot": this.addItemsToPool(specialLootPool, pool); break; @@ -173,163 +162,138 @@ export class BotLootCacheService } // Add all items (if any) to combined pool (excluding secure) - if (Object.keys(pool).length > 0 && slot.toLowerCase() !== "securedcontainer") - { + 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 - = Object.keys(botJsonTemplate.generation.items.specialItems.whitelist)?.length > 0 + const specialLootItems: Record = + Object.keys(botJsonTemplate.generation.items.specialItems.whitelist)?.length > 0 ? botJsonTemplate.generation.items.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)) - { + 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))) - { + if (!(this.isBulletOrGrenade(itemTemplate._props) || this.isMagazine(itemTemplate._props))) { specialLootItems[tpl] = weight; } } } // Assign whitelisted healing items to bot if any exist - const healingItems: Record - = Object.keys(botJsonTemplate.generation.items.healing.whitelist)?.length > 0 + const healingItems: Record = + Object.keys(botJsonTemplate.generation.items.healing.whitelist)?.length > 0 ? botJsonTemplate.generation.items.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)) - { + 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 - ) - { + 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 - = Object.keys(botJsonTemplate.generation.items.drugs.whitelist)?.length > 0 + const drugItems: Record = + Object.keys(botJsonTemplate.generation.items.drugs.whitelist)?.length > 0 ? botJsonTemplate.generation.items.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)) - { + 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) - { + if (this.isMedicalItem(itemTemplate._props) && itemTemplate._parent === BaseClasses.DRUGS) { drugItems[tpl] = weight; } } } // Assign whitelisted food to bot if any exist - const foodItems: Record - = Object.keys(botJsonTemplate.generation.items.food.whitelist)?.length > 0 + const foodItems: Record = + Object.keys(botJsonTemplate.generation.items.food.whitelist)?.length > 0 ? botJsonTemplate.generation.items.food.whitelist : {}; // No food whitelist, find and assign from combined item pool - if (Object.keys(foodItems).length === 0) - { - for (const [tpl, weight] of Object.entries(combinedLootPool)) - { + 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)) - { + if (this.itemHelper.isOfBaseclass(itemTemplate._id, BaseClasses.FOOD)) { foodItems[tpl] = weight; } } } // Assign whitelisted drink to bot if any exist - const drinkItems: Record - = Object.keys(botJsonTemplate.generation.items.food.whitelist)?.length > 0 + const drinkItems: Record = + Object.keys(botJsonTemplate.generation.items.food.whitelist)?.length > 0 ? botJsonTemplate.generation.items.food.whitelist : {}; // No drink whitelist, find and assign from combined item pool - if (Object.keys(drinkItems).length === 0) - { - for (const [tpl, weight] of Object.entries(combinedLootPool)) - { + 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)) - { + if (this.itemHelper.isOfBaseclass(itemTemplate._id, BaseClasses.DRINK)) { drinkItems[tpl] = weight; } } } // Assign whitelisted currency to bot if any exist - const currencyItems: Record - = Object.keys(botJsonTemplate.generation.items.currency.whitelist)?.length > 0 + const currencyItems: Record = + Object.keys(botJsonTemplate.generation.items.currency.whitelist)?.length > 0 ? botJsonTemplate.generation.items.currency.whitelist : {}; // No currency whitelist, find and assign from combined item pool - if (Object.keys(currencyItems).length === 0) - { - for (const [tpl, weight] of Object.entries(combinedLootPool)) - { + 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)) - { + if (this.itemHelper.isOfBaseclass(itemTemplate._id, BaseClasses.MONEY)) { currencyItems[tpl] = weight; } } } // Assign whitelisted stims to bot if any exist - const stimItems: Record - = Object.keys(botJsonTemplate.generation.items.stims.whitelist)?.length > 0 + const stimItems: Record = + Object.keys(botJsonTemplate.generation.items.stims.whitelist)?.length > 0 ? botJsonTemplate.generation.items.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)) - { + 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) - { + if (this.isMedicalItem(itemTemplate._props) && itemTemplate._parent === BaseClasses.STIMULATOR) { stimItems[tpl] = weight; } } } // Assign whitelisted grenades to bot if any exist - const grenadeItems: Record - = Object.keys(botJsonTemplate.generation.items.grenades.whitelist)?.length > 0 + const grenadeItems: Record = + Object.keys(botJsonTemplate.generation.items.grenades.whitelist)?.length > 0 ? botJsonTemplate.generation.items.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)) - { + 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)) - { + if (this.isGrenade(itemTemplate._props)) { grenadeItems[tpl] = weight; } } @@ -337,24 +301,21 @@ export class BotLootCacheService // Get backpack loot (excluding magazines, bullets, grenades, drink, food and healing/stim items) const filteredBackpackItems = {}; - for (const itemKey of Object.keys(backpackLootPool)) - { + for (const itemKey of Object.keys(backpackLootPool)) { const itemResult = this.itemHelper.getItem(itemKey); - if (!itemResult[0]) - { + 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) - ) - { + 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; } @@ -364,26 +325,23 @@ export class BotLootCacheService // Get pocket loot (excluding magazines, bullets, grenades, drink, food medical and healing/stim items) const filteredPocketItems = {}; - for (const itemKey of Object.keys(pocketLootPool)) - { + for (const itemKey of Object.keys(pocketLootPool)) { const itemResult = this.itemHelper.getItem(itemKey); - if (!itemResult[0]) - { + 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 - ) - { + 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; } @@ -392,24 +350,21 @@ export class BotLootCacheService // Get vest loot (excluding magazines, bullets, grenades, medical and healing/stim items) const filteredVestItems = {}; - for (const itemKey of Object.keys(vestLootPool)) - { + for (const itemKey of Object.keys(vestLootPool)) { const itemResult = this.itemHelper.getItem(itemKey); - if (!itemResult[0]) - { + 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) - ) - { + 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; } @@ -436,10 +391,8 @@ export class BotLootCacheService * @param poolToAddTo Pool of items to add to * @param itemsToAdd items to add to combined pool if unique */ - protected addUniqueItemsToPool(poolToAddTo: ITemplateItem[], itemsToAdd: ITemplateItem[]): void - { - if (poolToAddTo.length === 0) - { + protected addUniqueItemsToPool(poolToAddTo: ITemplateItem[], itemsToAdd: ITemplateItem[]): void { + if (poolToAddTo.length === 0) { poolToAddTo.push(...itemsToAdd); return; } @@ -452,13 +405,10 @@ export class BotLootCacheService poolToAddTo.push(...uniqueResults); } - protected addItemsToPool(poolToAddTo: Record, poolOfItemsToAdd: Record): void - { - for (const tpl in poolOfItemsToAdd) - { + protected addItemsToPool(poolToAddTo: Record, poolOfItemsToAdd: Record): void { + for (const tpl in poolOfItemsToAdd) { // Skip adding items that already exist - if (poolToAddTo[tpl]) - { + if (poolToAddTo[tpl]) { continue; } @@ -471,8 +421,7 @@ export class BotLootCacheService * @param props * @returns */ - protected isBulletOrGrenade(props: Props): boolean - { + protected isBulletOrGrenade(props: Props): boolean { return "ammoType" in props; } @@ -481,8 +430,7 @@ export class BotLootCacheService * @param props * @returns */ - protected isMagazine(props: Props): boolean - { + protected isMagazine(props: Props): boolean { return "ReloadMagType" in props; } @@ -491,8 +439,7 @@ export class BotLootCacheService * @param props * @returns */ - protected isMedicalItem(props: Props): boolean - { + protected isMedicalItem(props: Props): boolean { return "medUseTime" in props; } @@ -501,23 +448,19 @@ export class BotLootCacheService * @param props * @returns */ - protected isGrenade(props: Props): boolean - { + protected isGrenade(props: Props): boolean { return "ThrowType" in props; } - protected isFood(tpl: string): boolean - { + protected isFood(tpl: string): boolean { return this.itemHelper.isOfBaseclass(tpl, BaseClasses.FOOD); } - protected isDrink(tpl: string): boolean - { + protected isDrink(tpl: string): boolean { return this.itemHelper.isOfBaseclass(tpl, BaseClasses.DRINK); } - protected isCurrency(tpl: string): boolean - { + protected isCurrency(tpl: string): boolean { return this.itemHelper.isOfBaseclass(tpl, BaseClasses.MONEY); } @@ -526,8 +469,7 @@ export class BotLootCacheService * @param botRole role to check for * @returns true if they exist */ - protected botRoleExistsInCache(botRole: string): boolean - { + protected botRoleExistsInCache(botRole: string): boolean { return !!this.lootCache[botRole]; } @@ -535,8 +477,7 @@ export class BotLootCacheService * If lootcache is undefined, init with empty property arrays * @param botRole Bot role to hydrate */ - protected initCacheForBotRole(botRole: string): void - { + protected initCacheForBotRole(botRole: string): void { this.lootCache[botRole] = { backpackLoot: {}, pocketLoot: {}, @@ -564,26 +505,21 @@ export class BotLootCacheService * @param itemBPrice * @returns */ - protected compareByValue(itemAPrice: number, itemBPrice: number): number - { + protected compareByValue(itemAPrice: number, itemBPrice: number): number { // If item A has no price, it should be moved to the back when sorting - if (!itemAPrice) - { + if (!itemAPrice) { return 1; } - if (!itemBPrice) - { + if (!itemBPrice) { return -1; } - if (itemAPrice < itemBPrice) - { + if (itemAPrice < itemBPrice) { return -1; } - if (itemAPrice > itemBPrice) - { + if (itemAPrice > itemBPrice) { return 1; } diff --git a/project/src/services/BotWeaponModLimitService.ts b/project/src/services/BotWeaponModLimitService.ts index ef04a0c6..84505a76 100644 --- a/project/src/services/BotWeaponModLimitService.ts +++ b/project/src/services/BotWeaponModLimitService.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { ItemHelper } from "@spt/helpers/ItemHelper"; import { Item } from "@spt/models/eft/common/tables/IItem"; import { ITemplateItem } from "@spt/models/eft/common/tables/ITemplateItem"; @@ -8,9 +7,9 @@ import { ItemTpl } from "@spt/models/enums/ItemTpl"; import { IBotConfig } from "@spt/models/spt/config/IBotConfig"; import { ILogger } from "@spt/models/spt/utils/ILogger"; import { ConfigServer } from "@spt/servers/ConfigServer"; +import { inject, injectable } from "tsyringe"; -export class BotModLimits -{ +export class BotModLimits { scope: ItemCount; scopeMax: number; scopeBaseTypes: string[]; @@ -19,22 +18,19 @@ export class BotModLimits flashlgihtLaserBaseTypes: string[]; } -export class ItemCount -{ +export class ItemCount { count: number; } @injectable() -export class BotWeaponModLimitService -{ +export class BotWeaponModLimitService { protected botConfig: IBotConfig; constructor( @inject("PrimaryLogger") protected logger: ILogger, @inject("ConfigServer") protected configServer: ConfigServer, @inject("ItemHelper") protected itemHelper: ItemHelper, - ) - { + ) { this.botConfig = this.configServer.getConfig(ConfigTypes.BOT); } @@ -43,8 +39,7 @@ export class BotWeaponModLimitService * @param botRole "assault", "bossTagilla" or "pmc" * @returns BotModLimits object */ - public getWeaponModLimits(botRole: string): BotModLimits - { + public getWeaponModLimits(botRole: string): BotModLimits { return { scope: { count: 0 }, scopeMax: this.botConfig.equipment[botRole]?.weaponModLimits?.scopeLimit, @@ -83,12 +78,12 @@ export class BotWeaponModLimitService modLimits: BotModLimits, modsParent: ITemplateItem, weapon: Item[], - ): boolean - { + ): boolean { // If mod or mods parent is the NcSTAR MPR45 Backup mount, allow it as it looks cool - if (modsParent._id === ItemTpl.MOUNT_NCSTAR_MPR45_BACKUP - || modTemplate._id === ItemTpl.MOUNT_NCSTAR_MPR45_BACKUP) - { + if ( + modsParent._id === ItemTpl.MOUNT_NCSTAR_MPR45_BACKUP || + modTemplate._id === ItemTpl.MOUNT_NCSTAR_MPR45_BACKUP + ) { // If weapon already has a longer ranged scope on it, allow ncstar to be spawned if ( weapon.some((item) => @@ -98,8 +93,7 @@ export class BotWeaponModLimitService BaseClasses.SPECIAL_SCOPE, ]), ) - ) - { + ) { return false; } @@ -108,32 +102,28 @@ export class BotWeaponModLimitService // mods parent is scope and mod is scope, allow it (adds those mini-sights to the tops of sights) const modIsScope = this.itemHelper.isOfBaseclasses(modTemplate._id, modLimits.scopeBaseTypes); - if (this.itemHelper.isOfBaseclasses(modsParent._id, modLimits.scopeBaseTypes) && modIsScope) - { + if (this.itemHelper.isOfBaseclasses(modsParent._id, modLimits.scopeBaseTypes) && modIsScope) { return false; } // If mod is a scope, return if limit reached - if (modIsScope) - { + if (modIsScope) { return this.weaponModLimitReached(modTemplate._id, modLimits.scope, modLimits.scopeMax, botRole); } // Mod is a mount that can hold only scopes and limit is reached (dont want to add empty mounts if limit is reached) if ( - this.itemHelper.isOfBaseclass(modTemplate._id, BaseClasses.MOUNT) - && modTemplate._props.Slots.some((x) => x._name === "mod_scope") - && modTemplate._props.Slots.length === 1 - && modLimits.scope.count >= modLimits.scopeMax - ) - { + this.itemHelper.isOfBaseclass(modTemplate._id, BaseClasses.MOUNT) && + modTemplate._props.Slots.some((x) => x._name === "mod_scope") && + modTemplate._props.Slots.length === 1 && + modLimits.scope.count >= modLimits.scopeMax + ) { return true; } // If mod is a light/laser, return if limit reached const modIsLightOrLaser = this.itemHelper.isOfBaseclasses(modTemplate._id, modLimits.flashlgihtLaserBaseTypes); - if (modIsLightOrLaser) - { + if (modIsLightOrLaser) { return this.weaponModLimitReached( modTemplate._id, modLimits.flashlightLaser, @@ -144,12 +134,11 @@ export class BotWeaponModLimitService // Mod is a mount that can hold only flashlights ad limit is reached (dont want to add empty mounts if limit is reached) if ( - this.itemHelper.isOfBaseclass(modTemplate._id, BaseClasses.MOUNT) - && modTemplate._props.Slots.some((x) => x._name === "mod_flashlight") - && modTemplate._props.Slots.length === 1 - && modLimits.scope.count >= modLimits.scopeMax - ) - { + this.itemHelper.isOfBaseclass(modTemplate._id, BaseClasses.MOUNT) && + modTemplate._props.Slots.some((x) => x._name === "mod_flashlight") && + modTemplate._props.Slots.length === 1 && + modLimits.scope.count >= modLimits.scopeMax + ) { return true; } @@ -169,17 +158,14 @@ export class BotWeaponModLimitService currentCount: { count: number }, maxLimit: number, botRole: string, - ): boolean - { + ): boolean { // No value or 0 - if (!maxLimit) - { + if (!maxLimit) { return false; } // Has mod limit for bot type been reached - if (currentCount.count >= maxLimit) - { + if (currentCount.count >= maxLimit) { // this.logger.debug(`[${botRole}] scope limit reached! tried to add ${modTpl} but scope count is ${currentCount.count}`); return true; } diff --git a/project/src/services/CustomLocationWaveService.ts b/project/src/services/CustomLocationWaveService.ts index ea6f0ea9..48322a52 100644 --- a/project/src/services/CustomLocationWaveService.ts +++ b/project/src/services/CustomLocationWaveService.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { BossLocationSpawn, Wave } from "@spt/models/eft/common/ILocationBase"; import { ConfigTypes } from "@spt/models/enums/ConfigTypes"; import { ILocationConfig } from "@spt/models/spt/config/ILocationConfig"; @@ -6,10 +5,10 @@ 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 { inject, injectable } from "tsyringe"; @injectable() -export class CustomLocationWaveService -{ +export class CustomLocationWaveService { protected locationConfig: ILocationConfig; constructor( @@ -17,8 +16,7 @@ export class CustomLocationWaveService @inject("RandomUtil") protected randomUtil: RandomUtil, @inject("DatabaseService") protected databaseService: DatabaseService, @inject("ConfigServer") protected configServer: ConfigServer, - ) - { + ) { this.locationConfig = this.configServer.getConfig(ConfigTypes.LOCATION); } @@ -27,8 +25,7 @@ export class CustomLocationWaveService * @param locationId e.g. factory4_day, bigmap * @param waveToAdd Boss wave to add to map */ - public addBossWaveToMap(locationId: string, waveToAdd: BossLocationSpawn): void - { + public addBossWaveToMap(locationId: string, waveToAdd: BossLocationSpawn): void { this.locationConfig.customWaves.boss[locationId].push(waveToAdd); } @@ -37,8 +34,7 @@ export class CustomLocationWaveService * @param locationId e.g. factory4_day, bigmap * @param waveToAdd Wave to add to map */ - public addNormalWaveToMap(locationId: string, waveToAdd: Wave): void - { + public addNormalWaveToMap(locationId: string, waveToAdd: Wave): void { this.locationConfig.customWaves.normal[locationId].push(waveToAdd); } @@ -46,8 +42,7 @@ export class CustomLocationWaveService * Clear all custom boss waves from a map * @param locationId e.g. factory4_day, bigmap */ - public clearBossWavesForMap(locationId: string): void - { + public clearBossWavesForMap(locationId: string): void { this.locationConfig.customWaves.boss[locationId] = []; } @@ -55,33 +50,27 @@ export class CustomLocationWaveService * Clear all custom normal waves from a map * @param locationId e.g. factory4_day, bigmap */ - public clearNormalWavesForMap(locationId: string): void - { + public clearNormalWavesForMap(locationId: string): void { this.locationConfig.customWaves.normal[locationId] = []; } /** * Add custom boss and normal waves to maps found in config/location.json to db */ - public applyWaveChangesToAllMaps(): void - { + public applyWaveChangesToAllMaps(): void { const bossWavesToApply = this.locationConfig.customWaves.boss; const normalWavesToApply = this.locationConfig.customWaves.normal; - for (const mapKey in bossWavesToApply) - { + for (const mapKey in bossWavesToApply) { const locationBase = this.databaseService.getLocation(mapKey).base; - if (!locationBase) - { + if (!locationBase) { this.logger.warning(`Unable to add custom boss wave to location: ${mapKey}, location not found`); continue; } - for (const bossWave of bossWavesToApply[mapKey]) - { - if (locationBase.BossLocationSpawn.some((x) => x.sptId === bossWave.sptId)) - { + for (const bossWave of bossWavesToApply[mapKey]) { + if (locationBase.BossLocationSpawn.some((x) => x.sptId === bossWave.sptId)) { // Already exists, skip continue; } @@ -92,20 +81,16 @@ export class CustomLocationWaveService } } - for (const mapKey in normalWavesToApply) - { + for (const mapKey in normalWavesToApply) { const locationBase = this.databaseService.getLocation(mapKey).base; - if (!locationBase) - { + if (!locationBase) { this.logger.warning(`Unable to add custom wave to location: ${mapKey}, location not found`); continue; } - for (const normalWave of normalWavesToApply[mapKey]) - { - if (locationBase.waves.some((x) => x.sptId === normalWave.sptId)) - { + for (const normalWave of normalWavesToApply[mapKey]) { + if (locationBase.waves.some((x) => x.sptId === normalWave.sptId)) { // Already exists, skip continue; } diff --git a/project/src/services/DatabaseService.ts b/project/src/services/DatabaseService.ts index 27fe3681..b0af7ead 100644 --- a/project/src/services/DatabaseService.ts +++ b/project/src/services/DatabaseService.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { IGlobals } from "@spt/models/eft/common/IGlobals"; import { ILocation } from "@spt/models/eft/common/ILocation"; import { IAchievement } from "@spt/models/eft/common/tables/IAchievement"; @@ -22,35 +21,30 @@ import { ITemplates } from "@spt/models/spt/templates/ITemplates"; import { ILogger } from "@spt/models/spt/utils/ILogger"; import { DatabaseServer } from "@spt/servers/DatabaseServer"; import { LocalisationService } from "@spt/services/LocalisationService"; +import { inject, injectable } from "tsyringe"; @injectable() -export class DatabaseService -{ +export class DatabaseService { protected locationConfig: ILocationConfig; constructor( @inject("PrimaryLogger") protected logger: ILogger, @inject("DatabaseServer") protected databaseServer: DatabaseServer, @inject("LocalisationService") protected localisationService: LocalisationService, - ) - { - } + ) {} /** * @returns assets/database/ */ - public getTables(): IDatabaseTables - { + public getTables(): IDatabaseTables { return this.databaseServer.getTables(); } /** * @returns assets/database/bots/ */ - public getBots(): IBots - { - if (!this.databaseServer.getTables().bots) - { + public getBots(): IBots { + if (!this.databaseServer.getTables().bots) { throw new Error(this.localisationService.getText("database-data_at_path_missing", "assets/database/bots")); } @@ -60,11 +54,11 @@ export class DatabaseService /** * @returns assets/database/globals.json */ - public getGlobals(): IGlobals - { - if (!this.databaseServer.getTables().globals) - { - throw new Error(this.localisationService.getText("database-data_at_path_missing", "assets/database/globals.json")); + public getGlobals(): IGlobals { + if (!this.databaseServer.getTables().globals) { + throw new Error( + this.localisationService.getText("database-data_at_path_missing", "assets/database/globals.json"), + ); } return this.databaseServer.getTables().globals!; @@ -73,11 +67,11 @@ export class DatabaseService /** * @returns assets/database/hideout/ */ - public getHideout(): IHideout - { - if (!this.databaseServer.getTables().hideout) - { - throw new Error(this.localisationService.getText("database-data_at_path_missing", "assets/database/hideout")); + public getHideout(): IHideout { + if (!this.databaseServer.getTables().hideout) { + throw new Error( + this.localisationService.getText("database-data_at_path_missing", "assets/database/hideout"), + ); } return this.databaseServer.getTables().hideout!; @@ -86,11 +80,11 @@ export class DatabaseService /** * @returns assets/database/locales/ */ - public getLocales(): ILocaleBase - { - if (!this.databaseServer.getTables().locales) - { - throw new Error(this.localisationService.getText("database-data_at_path_missing", "assets/database/locales")); + public getLocales(): ILocaleBase { + if (!this.databaseServer.getTables().locales) { + throw new Error( + this.localisationService.getText("database-data_at_path_missing", "assets/database/locales"), + ); } return this.databaseServer.getTables().locales!; @@ -99,11 +93,11 @@ export class DatabaseService /** * @returns assets/database/locations */ - public getLocations(): ILocations - { - if (!this.databaseServer.getTables().locales) - { - throw new Error(this.localisationService.getText("database-data_at_path_missing", "assets/database/locales")); + public getLocations(): ILocations { + if (!this.databaseServer.getTables().locales) { + throw new Error( + this.localisationService.getText("database-data_at_path_missing", "assets/database/locales"), + ); } return this.databaseServer.getTables().locations!; @@ -114,12 +108,10 @@ export class DatabaseService * @param locationId Desired location id * @returns assets/database/locations/ */ - public getLocation(locationId: string): ILocation - { + public getLocation(locationId: string): ILocation { const locations = this.getLocations(); const desiredLocation = locations[locationId.toLowerCase()]; - if (!desiredLocation) - { + if (!desiredLocation) { throw new Error(this.localisationService.getText("database-no_location_found_with_id", locationId)); } @@ -129,11 +121,11 @@ export class DatabaseService /** * @returns assets/database/match/ */ - public getMatch(): IMatch - { - if (!this.databaseServer.getTables().locales) - { - throw new Error(this.localisationService.getText("database-data_at_path_missing", "assets/database/locales")); + public getMatch(): IMatch { + if (!this.databaseServer.getTables().locales) { + throw new Error( + this.localisationService.getText("database-data_at_path_missing", "assets/database/locales"), + ); } return this.databaseServer.getTables().match!; @@ -142,11 +134,11 @@ export class DatabaseService /** * @returns assets/database/server.json */ - public getServer(): IServerBase - { - if (!this.databaseServer.getTables().locales) - { - throw new Error(this.localisationService.getText("database-data_at_path_missing", "assets/database/server")); + public getServer(): IServerBase { + if (!this.databaseServer.getTables().locales) { + throw new Error( + this.localisationService.getText("database-data_at_path_missing", "assets/database/server"), + ); } return this.databaseServer.getTables().server!; @@ -155,11 +147,11 @@ export class DatabaseService /** * @returns assets/database/settings.json */ - public getSettings(): ISettingsBase - { - if (!this.databaseServer.getTables().locales) - { - throw new Error(this.localisationService.getText("database-data_at_path_missing", "assets/database/settings")); + public getSettings(): ISettingsBase { + if (!this.databaseServer.getTables().locales) { + throw new Error( + this.localisationService.getText("database-data_at_path_missing", "assets/database/settings"), + ); } return this.databaseServer.getTables().settings!; @@ -168,11 +160,11 @@ export class DatabaseService /** * @returns assets/database/templates/ */ - public getTemplates(): ITemplates - { - if (!this.databaseServer.getTables().templates) - { - throw new Error(this.localisationService.getText("database-data_at_path_missing", "assets/database/templates")); + public getTemplates(): ITemplates { + if (!this.databaseServer.getTables().templates) { + throw new Error( + this.localisationService.getText("database-data_at_path_missing", "assets/database/templates"), + ); } return this.databaseServer.getTables().templates!; @@ -181,11 +173,14 @@ export class DatabaseService /** * @returns assets/database/templates/achievements.json */ - public getAchievements(): IAchievement[] - { - if (!this.databaseServer.getTables().templates!.achievements) - { - throw new Error(this.localisationService.getText("database-data_at_path_missing", "assets/database/templates/achievements.json")); + public getAchievements(): IAchievement[] { + if (!this.databaseServer.getTables().templates!.achievements) { + throw new Error( + this.localisationService.getText( + "database-data_at_path_missing", + "assets/database/templates/achievements.json", + ), + ); } return this.databaseServer.getTables().templates!.achievements!; @@ -194,11 +189,14 @@ export class DatabaseService /** * @returns assets/database/templates/customisation.json */ - public getCustomization(): Record - { - if (!this.databaseServer.getTables().templates!.customization) - { - throw new Error(this.localisationService.getText("database-data_at_path_missing", "assets/database/templates/customization.json")); + public getCustomization(): Record { + if (!this.databaseServer.getTables().templates!.customization) { + throw new Error( + this.localisationService.getText( + "database-data_at_path_missing", + "assets/database/templates/customization.json", + ), + ); } return this.databaseServer.getTables().templates!.customization!; @@ -207,11 +205,14 @@ export class DatabaseService /** * @returns assets/database/templates/items.json */ - public getHandbook(): IHandbookBase - { - if (!this.databaseServer.getTables().templates!.handbook) - { - throw new Error(this.localisationService.getText("database-data_at_path_missing", "assets/database/templates/handbook.json")); + public getHandbook(): IHandbookBase { + if (!this.databaseServer.getTables().templates!.handbook) { + throw new Error( + this.localisationService.getText( + "database-data_at_path_missing", + "assets/database/templates/handbook.json", + ), + ); } return this.databaseServer.getTables().templates!.handbook!; @@ -220,11 +221,14 @@ export class DatabaseService /** * @returns assets/database/templates/items.json */ - public getItems(): Record - { - if (!this.databaseServer.getTables().templates!.items) - { - throw new Error(this.localisationService.getText("database-data_at_path_missing", "assets/database/templates/items.json")); + public getItems(): Record { + if (!this.databaseServer.getTables().templates!.items) { + throw new Error( + this.localisationService.getText( + "database-data_at_path_missing", + "assets/database/templates/items.json", + ), + ); } return this.databaseServer.getTables().templates!.items!; @@ -233,11 +237,14 @@ export class DatabaseService /** * @returns assets/database/templates/prices.json */ - public getPrices(): Record - { - if (!this.databaseServer.getTables().templates!.prices) - { - throw new Error(this.localisationService.getText("database-data_at_path_missing", "assets/database/templates/prices.json")); + public getPrices(): Record { + if (!this.databaseServer.getTables().templates!.prices) { + throw new Error( + this.localisationService.getText( + "database-data_at_path_missing", + "assets/database/templates/prices.json", + ), + ); } return this.databaseServer.getTables().templates!.prices!; @@ -246,11 +253,14 @@ export class DatabaseService /** * @returns assets/database/templates/profiles.json */ - public getProfiles(): IProfileTemplates - { - if (!this.databaseServer.getTables().templates!.profiles) - { - throw new Error(this.localisationService.getText("database-data_at_path_missing", "assets/database/templates/profiles.json")); + public getProfiles(): IProfileTemplates { + if (!this.databaseServer.getTables().templates!.profiles) { + throw new Error( + this.localisationService.getText( + "database-data_at_path_missing", + "assets/database/templates/profiles.json", + ), + ); } return this.databaseServer.getTables().templates!.profiles!; @@ -259,11 +269,14 @@ export class DatabaseService /** * @returns assets/database/templates/items.json */ - public getQuests(): Record - { - if (!this.databaseServer.getTables().templates!.quests) - { - throw new Error(this.localisationService.getText("database-data_at_path_missing", "assets/database/templates/quests.json")); + public getQuests(): Record { + if (!this.databaseServer.getTables().templates!.quests) { + throw new Error( + this.localisationService.getText( + "database-data_at_path_missing", + "assets/database/templates/quests.json", + ), + ); } return this.databaseServer.getTables().templates!.quests!; @@ -272,11 +285,11 @@ export class DatabaseService /** * @returns assets/database/traders/ */ - public getTraders(): Record - { - if (!this.databaseServer.getTables().traders) - { - throw new Error(this.localisationService.getText("database-data_at_path_missing", "assets/database/traders")); + public getTraders(): Record { + if (!this.databaseServer.getTables().traders) { + throw new Error( + this.localisationService.getText("database-data_at_path_missing", "assets/database/traders"), + ); } return this.databaseServer.getTables().traders!; @@ -287,12 +300,10 @@ export class DatabaseService * @param traderId Desired trader id * @returns assets/database/traders/ */ - public getTrader(traderId: string): ITrader - { + public getTrader(traderId: string): ITrader { const traders = this.getTraders(); const desiredTrader = traders[traderId]; - if (!desiredTrader) - { + if (!desiredTrader) { throw new Error(this.localisationService.getText("database-no_trader_found_with_id", traderId)); } @@ -302,11 +313,11 @@ export class DatabaseService /** * @returns assets/database/locationServices/ */ - public getLocationServices(): ILocationServices - { - if (!this.databaseServer.getTables().templates!.locationServices) - { - throw new Error(this.localisationService.getText("database-data_at_path_missing", "assets/database/locationServices")); + public getLocationServices(): ILocationServices { + if (!this.databaseServer.getTables().templates!.locationServices) { + throw new Error( + this.localisationService.getText("database-data_at_path_missing", "assets/database/locationServices"), + ); } return this.databaseServer.getTables().templates!.locationServices!; diff --git a/project/src/services/FenceService.ts b/project/src/services/FenceService.ts index 5a2edbbf..a8e58718 100644 --- a/project/src/services/FenceService.ts +++ b/project/src/services/FenceService.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { HandbookHelper } from "@spt/helpers/HandbookHelper"; import { ItemHelper } from "@spt/helpers/ItemHelper"; import { PresetHelper } from "@spt/helpers/PresetHelper"; @@ -21,17 +20,17 @@ import { ILogger } from "@spt/models/spt/utils/ILogger"; import { ConfigServer } from "@spt/servers/ConfigServer"; import { DatabaseService } from "@spt/services/DatabaseService"; import { LocalisationService } from "@spt/services/LocalisationService"; -import { ICloner } from "@spt/utils/cloners/ICloner"; import { RandomUtil } from "@spt/utils/RandomUtil"; import { TimeUtil } from "@spt/utils/TimeUtil"; +import { ICloner } from "@spt/utils/cloners/ICloner"; +import { inject, injectable } from "tsyringe"; /** * Handle actions surrounding Fence * e.g. generating or refreshing assorts / get next refresh time */ @injectable() -export class FenceService -{ +export class FenceService { protected traderConfig: ITraderConfig; /** Time when some items in assort will be replaced */ @@ -69,8 +68,7 @@ export class FenceService @inject("LocalisationService") protected localisationService: LocalisationService, @inject("ConfigServer") protected configServer: ConfigServer, @inject("PrimaryCloner") protected cloner: ICloner, - ) - { + ) { this.traderConfig = this.configServer.getConfig(ConfigTypes.TRADER); } @@ -78,8 +76,7 @@ export class FenceService * Replace main fence assort with new assort * @param assort New assorts to replace old with */ - public setFenceAssort(assort: ITraderAssort): void - { + public setFenceAssort(assort: ITraderAssort): void { this.fenceAssort = assort; } @@ -87,8 +84,7 @@ export class FenceService * Replace discount fence assort with new assort * @param assort New assorts to replace old with */ - public setDiscountFenceAssort(assort: ITraderAssort): void - { + public setDiscountFenceAssort(assort: ITraderAssort): void { this.fenceDiscountAssort = assort; } @@ -96,8 +92,7 @@ export class FenceService * Get main fence assort * @return ITraderAssort */ - public getMainFenceAssort(): ITraderAssort | undefined - { + public getMainFenceAssort(): ITraderAssort | undefined { return this.fenceAssort; } @@ -105,8 +100,7 @@ export class FenceService * Get discount fence assort * @return ITraderAssort */ - public getDiscountFenceAssort(): ITraderAssort | undefined - { + public getDiscountFenceAssort(): ITraderAssort | undefined { return this.fenceDiscountAssort; } @@ -114,8 +108,7 @@ export class FenceService * Replace high rep level fence assort with new assort * @param discountAssort New assorts to replace old with */ - public setFenceDiscountAssort(discountAssort: ITraderAssort): void - { + public setFenceDiscountAssort(discountAssort: ITraderAssort): void { this.fenceDiscountAssort = discountAssort; } @@ -125,10 +118,8 @@ export class FenceService * @param pmcProfile Player profile * @returns ITraderAssort */ - public getFenceAssorts(pmcProfile: IPmcData): ITraderAssort - { - if (this.traderConfig.fence.regenerateAssortsOnRefresh) - { + public getFenceAssorts(pmcProfile: IPmcData): ITraderAssort { + if (this.traderConfig.fence.regenerateAssortsOnRefresh) { // Using base assorts made earlier, do some alterations and store in this.fenceAssort this.generateFenceAssorts(); } @@ -138,8 +129,7 @@ export class FenceService this.adjustAssortItemPricesByConfigMultiplier(assort!, 1, this.traderConfig.fence.presetPriceMult); // merge normal fence assorts + discount assorts if player standing is large enough - if (pmcProfile.TradersInfo[Traders.FENCE].standing >= 6) - { + if (pmcProfile.TradersInfo[Traders.FENCE].standing >= 6) { const discountAssort = this.cloner.clone(this.fenceDiscountAssort); this.adjustAssortItemPricesByConfigMultiplier( discountAssort!, @@ -159,8 +149,7 @@ export class FenceService * @param items the items to add with all its childrens * @param mainItem the most parent item of the array */ - public addItemsToFenceAssort(items: Item[], mainItem: Item): void - { + public addItemsToFenceAssort(items: Item[], mainItem: Item): void { // HUGE THANKS TO LACYWAY AND LEAVES FOR PROVIDING THIS SOLUTION FOR SPT TO IMPLEMENT!! // Copy the item and its children let clonedItems = this.cloner.clone(this.itemHelper.findAndReturnChildrenAsItems(items, mainItem._id)); @@ -171,8 +160,7 @@ export class FenceService // Fix IDs clonedItems = this.itemHelper.reparentItemAndChildren(root, clonedItems); root.parentId = "hideout"; - if (root.upd?.SpawnedInSession !== undefined) - { + if (root.upd?.SpawnedInSession !== undefined) { root.upd.SpawnedInSession = false; } @@ -193,8 +181,7 @@ export class FenceService * @param items the items (with its children) to calculate fence price for * @returns the fence price of the item */ - public getItemPrice(itemTpl: string, items: Item[]): number - { + public getItemPrice(itemTpl: string, items: Item[]): number { return this.itemHelper.isOfBaseclass(itemTpl, BaseClasses.AMMO_BOX) ? this.getAmmoBoxPrice(items) * this.traderConfig.fence.itemPriceMult : this.handbookHelper.getTemplatePrice(itemTpl) * this.traderConfig.fence.itemPriceMult; @@ -206,13 +193,10 @@ export class FenceService * @param items the ammo box (and all its children ammo items) * @returns the price of the ammo box */ - protected getAmmoBoxPrice(items: Item[]): number - { + protected getAmmoBoxPrice(items: Item[]): number { let total = 0; - for (const item of items) - { - if (this.itemHelper.isOfBaseclass(item._tpl, BaseClasses.AMMO)) - { + for (const item of items) { + if (this.itemHelper.isOfBaseclass(item._tpl, BaseClasses.AMMO)) { total += this.handbookHelper.getTemplatePrice(item._tpl) * (item.upd?.StackObjectsCount ?? 1); } } @@ -230,13 +214,10 @@ export class FenceService assort: ITraderAssort, itemMultipler: number, presetMultiplier: number, - ): void - { - for (const item of assort.items) - { + ): void { + for (const item of assort.items) { // Skip sub-items when adjusting prices - if (item.slotId !== "hideout") - { + if (item.slotId !== "hideout") { continue; } @@ -250,20 +231,16 @@ export class FenceService * @param secondAssort assort #2 * @returns merged assort */ - protected mergeAssorts(firstAssort: ITraderAssort, secondAssort: ITraderAssort): ITraderAssort - { - for (const itemId in secondAssort.barter_scheme) - { + protected mergeAssorts(firstAssort: ITraderAssort, secondAssort: ITraderAssort): ITraderAssort { + for (const itemId in secondAssort.barter_scheme) { firstAssort.barter_scheme[itemId] = secondAssort.barter_scheme[itemId]; } - for (const item of secondAssort.items) - { + for (const item of secondAssort.items) { firstAssort.items.push(item); } - for (const itemId in secondAssort.loyal_level_items) - { + for (const itemId in secondAssort.loyal_level_items) { firstAssort.loyal_level_items[itemId] = secondAssort.loyal_level_items[itemId]; } @@ -282,22 +259,15 @@ export class FenceService assort: ITraderAssort, modifier: number, presetModifier: number, - ): void - { + ): void { // Is preset - if (item.upd?.sptPresetId) - { - if (assort.barter_scheme[item._id]) - { + if (item.upd?.sptPresetId) { + if (assort.barter_scheme[item._id]) { assort.barter_scheme[item._id][0][0].count *= presetModifier; } - } - else if (assort.barter_scheme[item._id]) - { + } else if (assort.barter_scheme[item._id]) { assort.barter_scheme[item._id][0][0].count *= modifier; - } - else - { + } else { this.logger.warning(`adjustItemPriceByModifier() - no action taken for item: ${item._tpl}`); return; @@ -308,8 +278,7 @@ export class FenceService * Get fence assorts with no price adjustments based on fence rep * @returns ITraderAssort */ - public getRawFenceAssorts(): ITraderAssort - { + public getRawFenceAssorts(): ITraderAssort { return this.mergeAssorts(this.cloner.clone(this.fenceAssort!), this.cloner.clone(this.fenceDiscountAssort!)); } @@ -317,16 +286,14 @@ export class FenceService * Does fence need to perform a partial refresh because its passed the refresh timer defined in trader.json * @returns true if it needs a partial refresh */ - public needsPartialRefresh(): boolean - { + public needsPartialRefresh(): boolean { return this.timeUtil.getTimestamp() > this.nextPartialRefreshTimestamp; } /** * Replace a percentage of fence assorts with freshly generated items */ - public performPartialRefresh(): void - { + public performPartialRefresh(): void { const itemCountToReplace = this.getCountOfItemsToReplace(this.traderConfig.fence.assortSize); const discountItemCountToReplace = this.getCountOfItemsToReplace( this.traderConfig.fence.discountOptions.assortSize, @@ -355,28 +322,24 @@ export class FenceService this.updateFenceAssorts(newDiscountItems, this.fenceDiscountAssort!); // Add new barter items to fence barter scheme - for (const barterItemKey in newItems.barter_scheme) - { + for (const barterItemKey in newItems.barter_scheme) { this.fenceAssort!.barter_scheme[barterItemKey] = newItems.barter_scheme[barterItemKey]; } // Add loyalty items to fence assorts loyalty object - for (const loyaltyItemKey in newItems.loyal_level_items) - { + for (const loyaltyItemKey in newItems.loyal_level_items) { this.fenceAssort!.loyal_level_items[loyaltyItemKey] = newItems.loyal_level_items[loyaltyItemKey]; } // Add new barter items to fence assorts discounted barter scheme - for (const barterItemKey in newDiscountItems.barter_scheme) - { + for (const barterItemKey in newDiscountItems.barter_scheme) { this.fenceDiscountAssort!.barter_scheme[barterItemKey] = newDiscountItems.barter_scheme[barterItemKey]; } // Add loyalty items to fence discount assorts loyalty object - for (const loyaltyItemKey in newDiscountItems.loyal_level_items) - { - this.fenceDiscountAssort!.loyal_level_items[loyaltyItemKey] - = newDiscountItems.loyal_level_items[loyaltyItemKey]; + for (const loyaltyItemKey in newDiscountItems.loyal_level_items) { + this.fenceDiscountAssort!.loyal_level_items[loyaltyItemKey] = + newDiscountItems.loyal_level_items[loyaltyItemKey]; } // Reset the clock @@ -391,14 +354,11 @@ export class FenceService protected updateFenceAssorts( newFenceAssorts: ICreateFenceAssortsResult, existingFenceAssorts: ITraderAssort, - ): void - { - for (const itemWithChildren of newFenceAssorts.sptItems) - { + ): void { + for (const itemWithChildren of newFenceAssorts.sptItems) { // Find the root item const newRootItem = itemWithChildren.find((item) => item.slotId === "hideout"); - if (!newRootItem) - { + if (!newRootItem) { const firstItem = itemWithChildren.find((x) => x); this.logger.error( `Unable to process fence assort as root item is missing, ${firstItem?._tpl}, skipping`, @@ -413,8 +373,7 @@ export class FenceService ); // Check if same type of item exists + its on list of item types to always stack - if (existingRootItem && this.itemInPreventDupeCategoryList(newRootItem._tpl)) - { + if (existingRootItem && this.itemInPreventDupeCategoryList(newRootItem._tpl)) { const existingFullItemTree = this.itemHelper.findAndReturnChildrenAsItems( existingFenceAssorts.items, existingRootItem._id, @@ -425,11 +384,9 @@ export class FenceService existingFullItemTree, this.fenceItemUpdCompareProperties, ) - ) - { + ) { // Guard against a missing stack count - if (existingRootItem.upd?.StackObjectsCount === undefined) - { + if (existingRootItem.upd?.StackObjectsCount === undefined) { existingRootItem.upd!.StackObjectsCount = 1; } @@ -441,25 +398,23 @@ export class FenceService } // if the upd doesnt exist just initialize it - if (newRootItem.upd === undefined) - { + if (newRootItem.upd === undefined) { newRootItem.upd = {}; } // New assort to be added to existing assorts existingFenceAssorts.items.push(...itemWithChildren); existingFenceAssorts.barter_scheme[newRootItem._id] = newFenceAssorts.barter_scheme[newRootItem._id]; - existingFenceAssorts.loyal_level_items[newRootItem._id] - = newFenceAssorts.loyal_level_items[newRootItem._id]; + existingFenceAssorts.loyal_level_items[newRootItem._id] = + newFenceAssorts.loyal_level_items[newRootItem._id]; } } /** * Increment fence next refresh timestamp by current timestamp + partialRefreshTimeSeconds from config */ - protected incrementPartialRefreshTime(): void - { - this.nextPartialRefreshTimestamp - = this.timeUtil.getTimestamp() + this.traderConfig.fence.partialRefreshTimeSeconds; + protected incrementPartialRefreshTime(): void { + this.nextPartialRefreshTimestamp = + this.timeUtil.getTimestamp() + this.traderConfig.fence.partialRefreshTimeSeconds; } /** @@ -471,20 +426,17 @@ export class FenceService protected getItemCountsToGenerate( assortItems: Item[], generationValues: IGenerationAssortValues, - ): IGenerationAssortValues - { + ): IGenerationAssortValues { const allRootItems = assortItems.filter((item) => item.slotId === "hideout"); const rootPresetItems = allRootItems.filter((item) => item?.upd?.sptPresetId); // Get count of weapons - const currentWeaponPresetCount = rootPresetItems.reduce((count, item) => - { + const currentWeaponPresetCount = rootPresetItems.reduce((count, item) => { return this.itemHelper.isOfBaseclass(item._tpl, BaseClasses.WEAPON) ? count + 1 : count; }, 0); // Get count of equipment - const currentEquipmentPresetCount = rootPresetItems.reduce((count, item) => - { + const currentEquipmentPresetCount = rootPresetItems.reduce((count, item) => { return this.itemHelper.armorItemCanHoldMods(item._tpl) ? count + 1 : count; }, 0); @@ -508,13 +460,10 @@ export class FenceService * @param itemCountToReplace * @param discountItemCountToReplace */ - protected deleteRandomAssorts(itemCountToReplace: number, assort: ITraderAssort): void - { - if (assort?.items?.length > 0) - { + protected deleteRandomAssorts(itemCountToReplace: number, assort: ITraderAssort): void { + if (assort?.items?.length > 0) { const rootItems = assort.items.filter((item) => item.slotId === "hideout"); - for (let index = 0; index < itemCountToReplace; index++) - { + for (let index = 0; index < itemCountToReplace; index++) { this.removeRandomItemFromAssorts(assort, rootItems); } } @@ -525,8 +474,7 @@ export class FenceService * @param assort Trader assort to remove item from * @param rootItems Pool of root items to pick from to remove */ - protected removeRandomItemFromAssorts(assort: ITraderAssort, rootItems: Item[]): void - { + protected removeRandomItemFromAssorts(assort: ITraderAssort, rootItems: Item[]): void { const rootItemToAdjust = this.randomUtil.getArrayValue(rootItems); // Items added by mods may not have a upd object, assume item stack size is 1 @@ -538,10 +486,8 @@ export class FenceService const isEntireStackToBeRemoved = itemCountToRemove === stackSize; // Partial stack reduction - if (!isEntireStackToBeRemoved) - { - if (!rootItemToAdjust.upd) - { + if (!isEntireStackToBeRemoved) { + if (!rootItemToAdjust.upd) { this.logger.warning(`Fence Item: ${rootItemToAdjust._tpl} lacks a upd object, adding`); rootItemToAdjust.upd = {}; } @@ -554,8 +500,7 @@ export class FenceService // Remove item + child mods (if any) const itemWithChildren = this.itemHelper.findAndReturnChildrenAsItems(assort.items, rootItemToAdjust._id); - for (const itemToDelete of itemWithChildren) - { + for (const itemToDelete of itemWithChildren) { // Delete item from assort items array assort.items.splice(assort.items.indexOf(itemToDelete), 1); } @@ -570,8 +515,7 @@ export class FenceService * @param totalItemCount total item count * @returns rounded int of items to replace */ - protected getCountOfItemsToReplace(totalItemCount: number): number - { + protected getCountOfItemsToReplace(totalItemCount: number): number { return Math.round(totalItemCount * (this.traderConfig.fence.partialRefreshChangePercent / 100)); } @@ -579,10 +523,8 @@ export class FenceService * Get the count of items fence offers * @returns number */ - public getOfferCount(): number - { - if (!this.fenceAssort?.items?.length) - { + public getOfferCount(): number { + if (!this.fenceAssort?.items?.length) { return 0; } @@ -593,8 +535,7 @@ export class FenceService * Create trader assorts for fence and store in fenceService cache * Uses fence base cache generatedon server start as a base */ - public generateFenceAssorts(): void - { + public generateFenceAssorts(): void { // Reset refresh time now assorts are being generated this.incrementPartialRefreshTime(); @@ -619,11 +560,9 @@ export class FenceService * @param intermediaryAssorts Generated assorts that will be converted * @returns ITraderAssort */ - protected convertIntoFenceAssort(intermediaryAssorts: ICreateFenceAssortsResult): ITraderAssort - { + protected convertIntoFenceAssort(intermediaryAssorts: ICreateFenceAssortsResult): ITraderAssort { const result = this.createFenceAssortSkeleton(); - for (const itemWithChilden of intermediaryAssorts.sptItems) - { + for (const itemWithChilden of intermediaryAssorts.sptItems) { result.items.push(...itemWithChilden); } @@ -637,8 +576,7 @@ export class FenceService * Create object that contains calculated fence assort item values to make based on config * Stored in this.desiredAssortCounts */ - protected createInitialFenceAssortGenerationValues(): void - { + protected createInitialFenceAssortGenerationValues(): void { const result: IFenceAssortGenerationValues = { normal: { item: 0, weaponPreset: 0, equipmentPreset: 0 }, discount: { item: 0, weaponPreset: 0, equipmentPreset: 0 }, @@ -675,8 +613,7 @@ export class FenceService * Create skeleton to hold assort items * @returns ITraderAssort object */ - protected createFenceAssortSkeleton(): ITraderAssort - { + protected createFenceAssortSkeleton(): ITraderAssort { return { items: [], barter_scheme: {}, @@ -690,15 +627,13 @@ export class FenceService * @param assortCount Number of assorts to generate * @param assorts object to add created assorts to */ - protected createAssorts(itemCounts: IGenerationAssortValues, loyaltyLevel: number): ICreateFenceAssortsResult - { + protected createAssorts(itemCounts: IGenerationAssortValues, loyaltyLevel: number): ICreateFenceAssortsResult { const result: ICreateFenceAssortsResult = { sptItems: [], barter_scheme: {}, loyal_level_items: {} }; const baseFenceAssortClone = this.cloner.clone(this.databaseService.getTrader(Traders.FENCE).assort); const itemTypeLimitCounts = this.initItemLimitCounter(this.traderConfig.fence.itemTypeLimits); - if (itemCounts.item > 0) - { + if (itemCounts.item > 0) { const itemResult = this.addItemAssorts( itemCounts.item, result, @@ -708,8 +643,7 @@ export class FenceService ); } - if (itemCounts.weaponPreset > 0 || itemCounts.equipmentPreset > 0) - { + if (itemCounts.weaponPreset > 0 || itemCounts.equipmentPreset > 0) { // Add presets this.addPresetsToAssort( itemCounts.weaponPreset, @@ -735,23 +669,18 @@ export class FenceService assortCount: number, assorts: ICreateFenceAssortsResult, baseFenceAssortClone: ITraderAssort, - itemTypeLimits: Record, + itemTypeLimits: Record, loyaltyLevel: number, - ): void - { + ): void { const priceLimits = this.traderConfig.fence.itemCategoryRoublePriceLimit; const assortRootItems = baseFenceAssortClone.items.filter( (item) => item.parentId === "hideout" && !item.upd?.sptPresetId, ); - for (let i = 0; i < assortCount; i++) - { + for (let i = 0; i < assortCount; i++) { const chosenBaseAssortRoot = this.randomUtil.getArrayValue(assortRootItems); - if (!chosenBaseAssortRoot) - { - this.logger.error( - this.localisationService.getText("fence-unable_to_find_assort_by_id"), - ); + if (!chosenBaseAssortRoot) { + this.logger.error(this.localisationService.getText("fence-unable_to_find_assort_by_id")); continue; } @@ -761,8 +690,7 @@ export class FenceService const itemDbDetails = this.itemHelper.getItem(chosenBaseAssortRoot._tpl)[1]; const itemLimitCount = this.getMatchingItemLimit(itemTypeLimits, itemDbDetails._id)!; - if (itemLimitCount?.current >= itemLimitCount?.max) - { + if (itemLimitCount?.current >= itemLimitCount?.max) { // Skip adding item as assort as limit reached, decrement i counter so we still get another item i--; continue; @@ -771,23 +699,20 @@ export class FenceService const itemIsPreset = this.presetHelper.isPreset(chosenBaseAssortRoot._id); const price = baseFenceAssortClone.barter_scheme[chosenBaseAssortRoot._id][0][0].count; - if (price === 0 || (price === 1 && !itemIsPreset) || price === 100) - { + if (price === 0 || (price === 1 && !itemIsPreset) || price === 100) { // Don't allow "special" items / presets i--; continue; } - if (price > priceLimits[itemDbDetails._parent]) - { + if (price > priceLimits[itemDbDetails._parent]) { // Too expensive for fence, try another item i--; continue; } // Increment count as item is being added - if (itemLimitCount) - { + if (itemLimitCount) { itemLimitCount.current++; } @@ -802,16 +727,14 @@ export class FenceService // Only randomise upd values for single const isSingleStack = (rootItemBeingAdded.upd?.StackObjectsCount ?? 0) === 1; - if (isSingleStack) - { + if (isSingleStack) { this.randomiseItemUpdProperties(itemDbDetails, rootItemBeingAdded); } // Skip items already in the assort if it exists in the prevent duplicate list const existingItemThatMatches = this.getMatchingItem(rootItemBeingAdded, itemDbDetails, assorts.sptItems)!; const shouldBeStacked = this.itemShouldBeForceStacked(existingItemThatMatches, itemDbDetails); - if (shouldBeStacked && existingItemThatMatches) - { + if (shouldBeStacked && existingItemThatMatches) { // Decrement loop counter so another items gets added i--; existingItemThatMatches.upd!.StackObjectsCount!++; @@ -820,8 +743,7 @@ export class FenceService } // Add mods to armors so they dont show as red in the trade screen - if (this.itemHelper.itemRequiresSoftInserts(rootItemBeingAdded._tpl)) - { + if (this.itemHelper.itemRequiresSoftInserts(rootItemBeingAdded._tpl)) { this.randomiseArmorModDurability(desiredAssortItemAndChildrenClone, itemDbDetails); } @@ -832,8 +754,7 @@ export class FenceService ); // Only adjust item price by quality for solo items, never multi-stack - if (isSingleStack) - { + if (isSingleStack) { this.adjustItemPriceByQuality(assorts.barter_scheme, rootItemBeingAdded, itemDbDetails); } @@ -853,16 +774,14 @@ export class FenceService rootItemBeingAdded: Item, itemDbDetails: ITemplateItem, itemsWithChildren: Item[][], - ): Item | undefined - { + ): Item | undefined { // Get matching root items const matchingItems = itemsWithChildren .filter((itemWithChildren) => itemWithChildren.find((item) => item._tpl === rootItemBeingAdded._tpl && item.parentId === "hideout"), ) - .flatMap((x) => x); - if (matchingItems.length === 0) - { + .flat(); + if (matchingItems.length === 0) { // Nothing matches by tpl and is root item, exit early return undefined; } @@ -871,23 +790,20 @@ export class FenceService BaseClasses.MEDICAL, BaseClasses.MEDKIT, ]); - const isGearAndHasSlots - = this.itemHelper.isOfBaseclasses(rootItemBeingAdded._tpl, [ + const isGearAndHasSlots = + this.itemHelper.isOfBaseclasses(rootItemBeingAdded._tpl, [ BaseClasses.ARMORED_EQUIPMENT, BaseClasses.SEARCHABLE_ITEM, ]) && (itemDbDetails._props.Slots?.length ?? 0) > 0; // Only one match and its not medical or armored gear - if (matchingItems.length === 1 && !(isMedical || isGearAndHasSlots)) - { + if (matchingItems.length === 1 && !(isMedical || isGearAndHasSlots)) { return matchingItems[0]; } // Items have sub properties that need to be checked against - for (const item of matchingItems) - { - if (isMedical && rootItemBeingAdded.upd!.MedKit?.HpResource === item.upd!.MedKit?.HpResource) - { + for (const item of matchingItems) { + if (isMedical && rootItemBeingAdded.upd!.MedKit?.HpResource === item.upd!.MedKit?.HpResource) { // e.g. bandages with multiple use // Both undefined === both max resoruce left return item; @@ -895,11 +811,10 @@ export class FenceService // Armors/helmets etc if ( - isGearAndHasSlots - && rootItemBeingAdded.upd!.Repairable?.Durability === item.upd!.Repairable?.Durability - && rootItemBeingAdded.upd!.Repairable?.MaxDurability === item.upd!.Repairable?.MaxDurability - ) - { + isGearAndHasSlots && + rootItemBeingAdded.upd!.Repairable?.Durability === item.upd!.Repairable?.Durability && + rootItemBeingAdded.upd!.Repairable?.MaxDurability === item.upd!.Repairable?.MaxDurability + ) { return item; } } @@ -913,25 +828,21 @@ export class FenceService * @param itemDbDetails Item we want to add db details * @returns True item should be force stacked */ - protected itemShouldBeForceStacked(existingItem: Item, itemDbDetails: ITemplateItem): boolean - { + protected itemShouldBeForceStacked(existingItem: Item, itemDbDetails: ITemplateItem): boolean { // No existing item in assort - if (!existingItem) - { + if (!existingItem) { return false; } // Don't stack child items, only root items - if (existingItem.parentId !== "hideout") - { + if (existingItem.parentId !== "hideout") { return false; } return this.itemInPreventDupeCategoryList(itemDbDetails._id); } - protected itemInPreventDupeCategoryList(tpl: string): boolean - { + protected itemInPreventDupeCategoryList(tpl: string): boolean { // Item type in config list return this.itemHelper.isOfBaseclasses(tpl, this.traderConfig.fence.preventDuplicateOffersOfCategory); } @@ -946,17 +857,14 @@ export class FenceService barterSchemes: Record, itemRoot: Item, itemTemplate: ITemplateItem, - ): void - { + ): void { // Healing items - if (itemRoot.upd?.MedKit) - { + if (itemRoot.upd?.MedKit) { const itemTotalMax = itemTemplate._props.MaxHpResource!; const current = itemRoot.upd.MedKit.HpResource; // Current and max match, no adjustment necessary - if (itemTotalMax === current) - { + if (itemTotalMax === current) { return; } @@ -970,8 +878,7 @@ export class FenceService } // Adjust price based on durability - if (itemRoot.upd?.Repairable || this.itemHelper.isOfBaseclass(itemRoot._tpl, BaseClasses.KEY_MECHANICAL)) - { + if (itemRoot.upd?.Repairable || this.itemHelper.isOfBaseclass(itemRoot._tpl, BaseClasses.KEY_MECHANICAL)) { const itemQualityModifier = this.itemHelper.getItemQualityModifier(itemRoot); const basePrice = barterSchemes[itemRoot._id][0][0].count; barterSchemes[itemRoot._id][0][0].count = Math.round(basePrice * itemQualityModifier); @@ -979,14 +886,11 @@ export class FenceService } protected getMatchingItemLimit( - itemTypeLimits: Record, + itemTypeLimits: Record, itemTpl: string, - ): { current: number, max: number } | undefined - { - for (const baseTypeKey in itemTypeLimits) - { - if (this.itemHelper.isOfBaseclass(itemTpl, baseTypeKey)) - { + ): { current: number; max: number } | undefined { + for (const baseTypeKey in itemTypeLimits) { + if (this.itemHelper.isOfBaseclass(itemTpl, baseTypeKey)) { return itemTypeLimits[baseTypeKey]; } } @@ -1005,19 +909,15 @@ export class FenceService assorts: ICreateFenceAssortsResult, baseFenceAssort: ITraderAssort, loyaltyLevel: number, - ): void - { + ): void { let weaponPresetsAddedCount = 0; - if (desiredWeaponPresetsCount > 0) - { + if (desiredWeaponPresetsCount > 0) { const weaponPresetRootItems = baseFenceAssort.items.filter( (item) => item.upd?.sptPresetId && this.itemHelper.isOfBaseclass(item._tpl, BaseClasses.WEAPON), ); - while (weaponPresetsAddedCount < desiredWeaponPresetsCount) - { + while (weaponPresetsAddedCount < desiredWeaponPresetsCount) { const randomPresetRoot = this.randomUtil.getArrayValue(weaponPresetRootItems); - if (this.traderConfig.fence.blacklist.includes(randomPresetRoot._tpl)) - { + if (this.traderConfig.fence.blacklist.includes(randomPresetRoot._tpl)) { continue; } @@ -1033,13 +933,11 @@ export class FenceService // Check chosen item is below price cap const priceLimitRouble = this.traderConfig.fence.itemCategoryRoublePriceLimit[rootItemDb._parent]; - const itemPrice - = this.handbookHelper.getTemplatePriceForItems(presetWithChildrenClone) - * this.itemHelper.getItemQualityModifierForItems(presetWithChildrenClone); - if (priceLimitRouble) - { - if (itemPrice > priceLimitRouble) - { + const itemPrice = + this.handbookHelper.getTemplatePriceForItems(presetWithChildrenClone) * + this.itemHelper.getItemQualityModifierForItems(presetWithChildrenClone); + if (priceLimitRouble) { + if (itemPrice > priceLimitRouble) { // Too expensive, try again continue; } @@ -1071,16 +969,14 @@ export class FenceService } let equipmentPresetsAddedCount = 0; - if (desiredEquipmentPresetsCount <= 0) - { + if (desiredEquipmentPresetsCount <= 0) { return; } const equipmentPresetRootItems = baseFenceAssort.items.filter( (item) => item.upd?.sptPresetId && this.itemHelper.armorItemCanHoldMods(item._tpl), ); - while (equipmentPresetsAddedCount < desiredEquipmentPresetsCount) - { + while (equipmentPresetsAddedCount < desiredEquipmentPresetsCount) { const randomPresetRoot = this.randomUtil.getArrayValue(equipmentPresetRootItems); const rootItemDb = this.itemHelper.getItem(randomPresetRoot._tpl)[1]; @@ -1089,8 +985,7 @@ export class FenceService ); // Need to add mods to armors so they dont show as red in the trade screen - if (this.itemHelper.itemRequiresSoftInserts(randomPresetRoot._tpl)) - { + if (this.itemHelper.itemRequiresSoftInserts(randomPresetRoot._tpl)) { this.randomiseArmorModDurability(presetWithChildrenClone, rootItemDb); } @@ -1098,13 +993,11 @@ export class FenceService // Check chosen item is below price cap const priceLimitRouble = this.traderConfig.fence.itemCategoryRoublePriceLimit[rootItemDb._parent]; - const itemPrice - = this.handbookHelper.getTemplatePriceForItems(presetWithChildrenClone) - * this.itemHelper.getItemQualityModifierForItems(presetWithChildrenClone); - if (priceLimitRouble) - { - if (itemPrice > priceLimitRouble) - { + const itemPrice = + this.handbookHelper.getTemplatePriceForItems(presetWithChildrenClone) * + this.itemHelper.getItemQualityModifierForItems(presetWithChildrenClone); + if (priceLimitRouble) { + if (itemPrice > priceLimitRouble) { // Too expensive, try again continue; } @@ -1140,19 +1033,16 @@ export class FenceService * @param armor Armor item array to add mods into * @param itemDbDetails Armor items db template */ - protected randomiseArmorModDurability(armor: Item[], itemDbDetails: ITemplateItem): void - { + protected randomiseArmorModDurability(armor: Item[], itemDbDetails: ITemplateItem): void { // Armor has no mods, nothing to randomise const hasMods = Boolean(itemDbDetails._props.Slots); - if (!hasMods) - { + if (!hasMods) { return; } // Check for and adjust soft insert durability values const requiredSlots = itemDbDetails._props.Slots?.filter((slot) => slot._required); - if (Boolean(requiredSlots?.length)) - { + if (Boolean(requiredSlots?.length)) { this.randomiseArmorSoftInsertDurabilities(requiredSlots, armor); } @@ -1160,8 +1050,7 @@ export class FenceService const plateSlots = itemDbDetails._props.Slots?.filter((slot) => this.itemHelper.isRemovablePlateSlot(slot._name), ); - if (Boolean(plateSlots?.length)) - { + if (Boolean(plateSlots?.length)) { this.randomiseArmorInsertsDurabilities(plateSlots, armor); } } @@ -1171,18 +1060,15 @@ export class FenceService * @param softInsertSlots Slots of items to randomise * @param armorItemAndMods Array of armor + inserts to get items from */ - protected randomiseArmorSoftInsertDurabilities(softInsertSlots: Slot[], armorItemAndMods: Item[]): void - { - for (const requiredSlot of softInsertSlots!) - { + protected randomiseArmorSoftInsertDurabilities(softInsertSlots: Slot[], armorItemAndMods: Item[]): void { + for (const requiredSlot of softInsertSlots!) { const modItemDbDetails = this.itemHelper.getItem(requiredSlot._props.filters[0].Plate!)[1]; const durabilityValues = this.getRandomisedArmorDurabilityValues( modItemDbDetails, this.traderConfig.fence.armorMaxDurabilityPercentMinMax, ); const plateTpl = requiredSlot._props.filters[0].Plate; // `Plate` property appears to be the 'default' item for slot - if (plateTpl === "") - { + if (plateTpl === "") { // Some bsg plate properties are empty, skip mod continue; } @@ -1194,8 +1080,7 @@ export class FenceService this.itemHelper.addUpdObjectToItem(modItemToAdjust); - if (!modItemToAdjust.upd!.Repairable) - { + if (!modItemToAdjust.upd!.Repairable) { modItemToAdjust.upd!.Repairable = { Durability: modItemDbDetails._props.MaxDurability!, MaxDurability: modItemDbDetails._props.MaxDurability!, @@ -1206,12 +1091,11 @@ export class FenceService // 25% chance to add shots to visor items when its below max durability if ( - this.randomUtil.getChance100(25) - && modItemToAdjust.parentId === BaseClasses.ARMORED_EQUIPMENT - && modItemToAdjust.slotId === "mod_equipment_000" - && modItemToAdjust.upd!.Repairable.Durability < modItemDbDetails._props.MaxDurability! - ) - { + this.randomUtil.getChance100(25) && + modItemToAdjust.parentId === BaseClasses.ARMORED_EQUIPMENT && + modItemToAdjust.slotId === "mod_equipment_000" && + modItemToAdjust.upd!.Repairable.Durability < modItemDbDetails._props.MaxDurability! + ) { // Is damaged modItemToAdjust.upd!.FaceShield = { Hits: this.randomUtil.getInt(1, 3) }; } @@ -1224,13 +1108,10 @@ export class FenceService * @param plateSlots Slots of items to randomise * @param armorItemAndMods Array of armor + inserts to get items from */ - protected randomiseArmorInsertsDurabilities(plateSlots: Slot[], armorItemAndMods: Item[]): void - { - for (const plateSlot of plateSlots!) - { + protected randomiseArmorInsertsDurabilities(plateSlots: Slot[], armorItemAndMods: Item[]): void { + for (const plateSlot of plateSlots!) { const plateTpl = plateSlot._props.filters[0].Plate; - if (!plateTpl) - { + if (!plateTpl) { // Bsg data lacks a default plate, skip randomisng for this mod continue; } @@ -1238,13 +1119,13 @@ export class FenceService const modItemDbDetails = this.itemHelper.getItem(plateTpl)[1]; // Chance to remove plate - const plateExistsChance = this.traderConfig - .fence.chancePlateExistsInArmorPercent[modItemDbDetails._props?.armorClass ?? "3"]; - if (!this.randomUtil.getChance100(plateExistsChance)) - { + const plateExistsChance = + this.traderConfig.fence.chancePlateExistsInArmorPercent[modItemDbDetails._props?.armorClass ?? "3"]; + if (!this.randomUtil.getChance100(plateExistsChance)) { // Remove plate from armor - armorItemAndMods = armorItemAndMods - .filter((item) => item.slotId!.toLowerCase() !== plateSlot._name.toLowerCase()); + armorItemAndMods = armorItemAndMods.filter( + (item) => item.slotId!.toLowerCase() !== plateSlot._name.toLowerCase(), + ); continue; } @@ -1255,19 +1136,20 @@ export class FenceService ); // Find items mod to apply dura changes to - const modItemToAdjust = armorItemAndMods - .find((mod) => mod.slotId!.toLowerCase() === plateSlot._name.toLowerCase()); + const modItemToAdjust = armorItemAndMods.find( + (mod) => mod.slotId!.toLowerCase() === plateSlot._name.toLowerCase(), + ); - if (!modItemToAdjust) - { - this.logger.warning(`Unable to randomise armor items ${armorItemAndMods[0]._tpl} ${plateSlot._name} slot as it cannot be found, skipping`); + if (!modItemToAdjust) { + this.logger.warning( + `Unable to randomise armor items ${armorItemAndMods[0]._tpl} ${plateSlot._name} slot as it cannot be found, skipping`, + ); continue; } this.itemHelper.addUpdObjectToItem(modItemToAdjust); - if (!modItemToAdjust?.upd?.Repairable) - { + if (!modItemToAdjust?.upd?.Repairable) { modItemToAdjust!.upd!.Repairable = { Durability: modItemDbDetails._props.MaxDurability!, MaxDurability: modItemDbDetails._props.MaxDurability!, @@ -1284,13 +1166,10 @@ export class FenceService * @param itemDbDetails item being added to fence * @returns Stack size */ - protected getSingleItemStackCount(itemDbDetails: ITemplateItem): number - { - if (this.itemHelper.isOfBaseclass(itemDbDetails._id, BaseClasses.AMMO)) - { + protected getSingleItemStackCount(itemDbDetails: ITemplateItem): number { + if (this.itemHelper.isOfBaseclass(itemDbDetails._id, BaseClasses.AMMO)) { const overrideValues = this.traderConfig.fence.itemStackSizeOverrideMinMax[itemDbDetails._parent]; - if (overrideValues) - { + if (overrideValues) { return this.randomUtil.getInt(overrideValues.min, overrideValues.max); } @@ -1302,15 +1181,13 @@ export class FenceService // Check for override in config, use values if exists let overrideValues = this.traderConfig.fence.itemStackSizeOverrideMinMax[itemDbDetails._id]; - if (overrideValues) - { + if (overrideValues) { return this.randomUtil.getInt(overrideValues.min, overrideValues.max); } // Check for parent override overrideValues = this.traderConfig.fence.itemStackSizeOverrideMinMax[itemDbDetails._parent]; - if (overrideValues) - { + if (overrideValues) { return this.randomUtil.getInt(overrideValues.min, overrideValues.max); } @@ -1321,20 +1198,16 @@ export class FenceService * Remove parts of a weapon prior to being listed on flea * @param itemAndMods Weapon to remove parts from */ - protected removeRandomModsOfItem(itemAndMods: Item[]): void - { + protected removeRandomModsOfItem(itemAndMods: Item[]): void { // Items to be removed from inventory const toDelete: string[] = []; // Find mods to remove from item that could've been scavenged by other players in-raid - for (const itemMod of itemAndMods) - { - if (this.presetModItemWillBeRemoved(itemMod, toDelete)) - { + for (const itemMod of itemAndMods) { + if (this.presetModItemWillBeRemoved(itemMod, toDelete)) { // Skip if not an item const itemDbDetails = this.itemHelper.getItem(itemMod._tpl); - if (!itemDbDetails[0]) - { + if (!itemDbDetails[0]) { continue; } @@ -1344,10 +1217,8 @@ export class FenceService } // Reverse loop and remove items - for (let index = itemAndMods.length - 1; index >= 0; --index) - { - if (toDelete.includes(itemAndMods[index]._id)) - { + for (let index = itemAndMods.length - 1; index >= 0; --index) { + if (toDelete.includes(itemAndMods[index]._id)) { itemAndMods.splice(index, 1); } } @@ -1359,12 +1230,10 @@ export class FenceService * @param itemsBeingDeleted Current list of items on weapon being deleted * @returns True if item will be removed */ - protected presetModItemWillBeRemoved(weaponMod: Item, itemsBeingDeleted: string[]): boolean - { + protected presetModItemWillBeRemoved(weaponMod: Item, itemsBeingDeleted: string[]): boolean { const slotIdsThatCanFail = this.traderConfig.fence.presetSlotsToRemoveChancePercent; const removalChance = slotIdsThatCanFail[weaponMod.slotId!]; - if (!removalChance) - { + if (!removalChance) { return false; } @@ -1379,10 +1248,8 @@ export class FenceService * @param itemDetails Item being randomised * @param itemToAdjust Item being edited */ - protected randomiseItemUpdProperties(itemDetails: ITemplateItem, itemToAdjust: Item): void - { - if (!itemDetails._props) - { + protected randomiseItemUpdProperties(itemDetails: ITemplateItem, itemToAdjust: Item): void { + if (!itemDetails._props) { this.logger.error( `Item ${itemDetails._name} lacks a _props field, unable to randomise item: ${itemToAdjust._id}`, ); @@ -1391,19 +1258,17 @@ export class FenceService } // Randomise hp resource of med items - if ("MaxHpResource" in itemDetails._props && (itemDetails._props.MaxHpResource ?? 0) > 0) - { + if ("MaxHpResource" in itemDetails._props && (itemDetails._props.MaxHpResource ?? 0) > 0) { itemToAdjust.upd!.MedKit = { HpResource: this.randomUtil.getInt(1, itemDetails._props.MaxHpResource!) }; } // Randomise armor durability if ( - (itemDetails._parent === BaseClasses.ARMORED_EQUIPMENT - || itemDetails._parent === BaseClasses.FACECOVER - || itemDetails._parent === BaseClasses.ARMOR_PLATE) - && (itemDetails._props.MaxDurability ?? 0) > 0 - ) - { + (itemDetails._parent === BaseClasses.ARMORED_EQUIPMENT || + itemDetails._parent === BaseClasses.FACECOVER || + itemDetails._parent === BaseClasses.ARMOR_PLATE) && + (itemDetails._props.MaxDurability ?? 0) > 0 + ) { const values = this.getRandomisedArmorDurabilityValues( itemDetails, this.traderConfig.fence.armorMaxDurabilityPercentMinMax, @@ -1414,8 +1279,7 @@ export class FenceService } // Randomise Weapon durability - if (this.itemHelper.isOfBaseclass(itemDetails._id, BaseClasses.WEAPON)) - { + if (this.itemHelper.isOfBaseclass(itemDetails._id, BaseClasses.WEAPON)) { const weaponDurabilityLimits = this.traderConfig.fence.weaponDurabilityPercentMinMax; const maxDuraMin = (weaponDurabilityLimits.max.min / 100) * itemDetails._props.MaxDurability!; const maxDuraMax = (weaponDurabilityLimits.max.max / 100) * itemDetails._props.MaxDurability!; @@ -1433,19 +1297,19 @@ export class FenceService return; } - if (this.itemHelper.isOfBaseclass(itemDetails._id, BaseClasses.REPAIR_KITS)) - { - itemToAdjust.upd!.RepairKit = { Resource: this.randomUtil.getInt(1, itemDetails._props.MaxRepairResource!) }; + if (this.itemHelper.isOfBaseclass(itemDetails._id, BaseClasses.REPAIR_KITS)) { + itemToAdjust.upd!.RepairKit = { + Resource: this.randomUtil.getInt(1, itemDetails._props.MaxRepairResource!), + }; return; } // Mechanical key + has limited uses if ( - this.itemHelper.isOfBaseclass(itemDetails._id, BaseClasses.KEY_MECHANICAL) - && (itemDetails._props.MaximumNumberOfUsage ?? 0) > 1 - ) - { + this.itemHelper.isOfBaseclass(itemDetails._id, BaseClasses.KEY_MECHANICAL) && + (itemDetails._props.MaximumNumberOfUsage ?? 0) > 1 + ) { itemToAdjust.upd!.Key = { NumberOfUsages: this.randomUtil.getInt(0, itemDetails._props.MaximumNumberOfUsage! - 1), }; @@ -1454,8 +1318,7 @@ export class FenceService } // Randomise items that use resources (e.g. fuel) - if ((itemDetails._props.MaxResource ?? 0) > 0) - { + if ((itemDetails._props.MaxResource ?? 0) > 0) { const resourceMax = itemDetails._props.MaxResource!; const resourceCurrent = this.randomUtil.getInt(1, itemDetails._props.MaxResource!); @@ -1472,8 +1335,7 @@ export class FenceService protected getRandomisedArmorDurabilityValues( itemDetails: ITemplateItem, equipmentDurabilityLimits: IItemDurabilityCurrentMax, - ): Repairable - { + ): Repairable { const maxDuraMin = (equipmentDurabilityLimits.max.min / 100) * itemDetails._props.MaxDurability!; const maxDuraMax = (equipmentDurabilityLimits.max.max / 100) * itemDetails._props.MaxDurability!; const chosenMaxDurability = this.randomUtil.getInt(maxDuraMin, maxDuraMax); @@ -1493,12 +1355,10 @@ export class FenceService * @param limits limits as defined in config * @returns record, key: item tplId, value: current/max item count allowed */ - protected initItemLimitCounter(limits: Record): Record - { - const itemTypeCounts: Record = {}; + protected initItemLimitCounter(limits: Record): Record { + const itemTypeCounts: Record = {}; - for (const x in limits) - { + for (const x in limits) { itemTypeCounts[x] = { current: 0, max: limits[x] }; } @@ -1509,8 +1369,7 @@ export class FenceService * Get the next update timestamp for fence * @returns future timestamp */ - public getNextFenceUpdateTimestamp(): number - { + public getNextFenceUpdateTimestamp(): number { const time = this.timeUtil.getTimestamp(); const updateSeconds = this.getFenceRefreshTime(); return time + updateSeconds; @@ -1520,8 +1379,7 @@ export class FenceService * Get fence refresh time in seconds * @returns Refresh time in seconds */ - protected getFenceRefreshTime(): number - { + protected getFenceRefreshTime(): number { const fence = this.traderConfig.updateTime.find((x) => x.traderId === Traders.FENCE)!.seconds; return this.randomUtil.getInt(fence.min, fence.max); @@ -1532,13 +1390,11 @@ export class FenceService * @param pmcData Player profile * @returns FenceLevel object */ - public getFenceInfo(pmcData: IPmcData): IFenceLevel - { + public getFenceInfo(pmcData: IPmcData): IFenceLevel { const fenceSettings = this.databaseService.getGlobals().config.FenceSettings; const pmcFenceInfo = pmcData.TradersInfo[fenceSettings.FenceId]; - if (!pmcFenceInfo) - { + if (!pmcFenceInfo) { return fenceSettings.Levels["0"]; } @@ -1547,13 +1403,11 @@ export class FenceService const maxLevel = Math.max(...fenceLevels); const pmcFenceLevel = Math.floor(pmcFenceInfo.standing); - if (pmcFenceLevel < minLevel) - { + if (pmcFenceLevel < minLevel) { return fenceSettings.Levels[minLevel.toString()]; } - if (pmcFenceLevel > maxLevel) - { + if (pmcFenceLevel > maxLevel) { return fenceSettings.Levels[maxLevel.toString()]; } @@ -1565,16 +1419,13 @@ export class FenceService * @param assortId assort id to adjust * @param buyCount Count of items bought */ - public amendOrRemoveFenceOffer(assortId: string, buyCount: number): void - { + public amendOrRemoveFenceOffer(assortId: string, buyCount: number): void { let isNormalAssort = true; let fenceAssortItem = this.fenceAssort!.items.find((item) => item._id === assortId); - if (!fenceAssortItem) - { + if (!fenceAssortItem) { // Not in main assorts, check secondary section fenceAssortItem = this.fenceDiscountAssort!.items.find((item) => item._id === assortId); - if (!fenceAssortItem) - { + if (!fenceAssortItem) { this.logger.error(this.localisationService.getText("fence-unable_to_find_offer_by_id", assortId)); return; @@ -1583,8 +1434,7 @@ export class FenceService } // Player wants to buy whole stack, delete stack - if (fenceAssortItem.upd!.StackObjectsCount === buyCount) - { + if (fenceAssortItem.upd!.StackObjectsCount === buyCount) { this.deleteOffer(assortId, isNormalAssort ? this.fenceAssort!.items : this.fenceDiscountAssort!.items); return; @@ -1594,22 +1444,18 @@ export class FenceService fenceAssortItem.upd!.StackObjectsCount! -= buyCount; } - protected deleteOffer(assortId: string, assorts: Item[]): void - { + protected deleteOffer(assortId: string, assorts: Item[]): void { // Assort could have child items, remove those too const itemWithChildrenToRemove = this.itemHelper.findAndReturnChildrenAsItems(assorts, assortId); - for (const itemToRemove of itemWithChildrenToRemove) - { + for (const itemToRemove of itemWithChildrenToRemove) { let indexToRemove = assorts.findIndex((item) => item._id === itemToRemove._id); // No offer found in main assort, check discount items - if (indexToRemove === -1) - { + if (indexToRemove === -1) { indexToRemove = this.fenceDiscountAssort!.items.findIndex((item) => item._id === itemToRemove._id); this.fenceDiscountAssort!.items.splice(indexToRemove, 1); - if (indexToRemove === -1) - { + if (indexToRemove === -1) { this.logger.warning( `unable to remove fence assort item: ${itemToRemove._id} tpl: ${itemToRemove._tpl}`, ); diff --git a/project/src/services/GiftService.ts b/project/src/services/GiftService.ts index 1a891541..fbb156d4 100644 --- a/project/src/services/GiftService.ts +++ b/project/src/services/GiftService.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { ProfileHelper } from "@spt/helpers/ProfileHelper"; import { ConfigTypes } from "@spt/models/enums/ConfigTypes"; import { GiftSenderType } from "@spt/models/enums/GiftSenderType"; @@ -13,10 +12,10 @@ import { LocalisationService } from "@spt/services/LocalisationService"; import { MailSendService } from "@spt/services/MailSendService"; import { HashUtil } from "@spt/utils/HashUtil"; import { TimeUtil } from "@spt/utils/TimeUtil"; +import { inject, injectable } from "tsyringe"; @injectable() -export class GiftService -{ +export class GiftService { protected giftConfig: IGiftsConfig; constructor( @@ -27,8 +26,7 @@ export class GiftService @inject("TimeUtil") protected timeUtil: TimeUtil, @inject("ProfileHelper") protected profileHelper: ProfileHelper, @inject("ConfigServer") protected configServer: ConfigServer, - ) - { + ) { this.giftConfig = this.configServer.getConfig(ConfigTypes.GIFTS); } @@ -37,13 +35,11 @@ export class GiftService * @param giftId Gift id to check for * @returns True if it exists in db */ - public giftExists(giftId: string): boolean - { + public giftExists(giftId: string): boolean { return !!this.giftConfig.gifts[giftId]; } - public getGiftById(giftId: string): Gift - { + public getGiftById(giftId: string): Gift { return this.giftConfig.gifts[giftId]; } @@ -51,8 +47,7 @@ export class GiftService * Get dictionary of all gifts * @returns Dict keyed by gift id */ - public getGifts(): Record - { + public getGifts(): Record { return this.giftConfig.gifts; } @@ -60,8 +55,7 @@ export class GiftService * Get an array of all gift ids * @returns string array of gift ids */ - public getGiftIds(): string[] - { + public getGiftIds(): string[] { return Object.keys(this.giftConfig.gifts); } @@ -71,32 +65,26 @@ export class GiftService * @param giftId Id of gift in configs/gifts.json to send player * @returns outcome of sending gift to player */ - public sendGiftToPlayer(playerId: string, giftId: string): GiftSentResult - { + public sendGiftToPlayer(playerId: string, giftId: string): GiftSentResult { const giftData = this.giftConfig.gifts[giftId]; - if (!giftData) - { + if (!giftData) { return GiftSentResult.FAILED_GIFT_DOESNT_EXIST; } const maxGiftsToSendCount = giftData.maxToSendPlayer ?? 1; - if (this.profileHelper.playerHasRecievedMaxNumberOfGift(playerId, giftId, maxGiftsToSendCount)) - { + if (this.profileHelper.playerHasRecievedMaxNumberOfGift(playerId, giftId, maxGiftsToSendCount)) { this.logger.debug(`Player already recieved gift: ${giftId}`); return GiftSentResult.FAILED_GIFT_ALREADY_RECEIVED; } - if (giftData.items?.length > 0 && !giftData.collectionTimeHours) - { + if (giftData.items?.length > 0 && !giftData.collectionTimeHours) { this.logger.warning(`Gift ${giftId} has items but no collection time limit, defaulting to 48 hours`); } // Handle system messsages - if (giftData.sender === GiftSenderType.SYSTEM) - { + if (giftData.sender === GiftSenderType.SYSTEM) { // Has a localisable text id to send to player - if (giftData.localeTextId) - { + if (giftData.localeTextId) { this.mailSendService.sendLocalisedSystemMessageToPlayer( playerId, giftData.localeTextId, @@ -104,9 +92,7 @@ export class GiftService giftData.profileChangeEvents, this.timeUtil.getHoursAsSeconds(giftData.collectionTimeHours), ); - } - else - { + } else { this.mailSendService.sendSystemMessageToPlayer( playerId, giftData.messageText, @@ -117,8 +103,7 @@ export class GiftService } } // Handle user messages - else if (giftData.sender === GiftSenderType.USER) - { + else if (giftData.sender === GiftSenderType.USER) { this.mailSendService.sendUserMessageToPlayer( playerId, giftData.senderDetails, @@ -126,11 +111,8 @@ export class GiftService giftData.items, this.timeUtil.getHoursAsSeconds(giftData.collectionTimeHours), ); - } - else if (giftData.sender === GiftSenderType.TRADER) - { - if (giftData.localeTextId) - { + } else if (giftData.sender === GiftSenderType.TRADER) { + if (giftData.localeTextId) { this.mailSendService.sendLocalisedNpcMessageToPlayer( playerId, giftData.trader!, @@ -139,9 +121,7 @@ export class GiftService giftData.items, this.timeUtil.getHoursAsSeconds(giftData.collectionTimeHours), ); - } - else - { + } else { this.mailSendService.sendDirectNpcMessageToPlayer( playerId, giftData.trader!, @@ -151,9 +131,7 @@ export class GiftService this.timeUtil.getHoursAsSeconds(giftData.collectionTimeHours), ); } - } - else - { + } else { // TODO: further split out into different message systems like above SYSTEM method // Trader / ragfair const details: ISendMessageDetails = { @@ -169,8 +147,7 @@ export class GiftService itemsMaxStorageLifetimeSeconds: this.timeUtil.getHoursAsSeconds(giftData.collectionTimeHours), }; - if (giftData.trader) - { + if (giftData.trader) { details.trader = giftData.trader; } @@ -187,15 +164,12 @@ export class GiftService * @param giftData Gift to send player * @returns trader/user/system id */ - protected getSenderId(giftData: Gift): string | undefined - { - if (giftData.sender === GiftSenderType.TRADER) - { + protected getSenderId(giftData: Gift): string | undefined { + if (giftData.sender === GiftSenderType.TRADER) { return Traders[giftData.trader!]; } - if (giftData.sender === GiftSenderType.USER) - { + if (giftData.sender === GiftSenderType.USER) { return giftData.senderId; } } @@ -205,10 +179,8 @@ export class GiftService * @param giftData Gift to send player * @returns MessageType enum value */ - protected getMessageType(giftData: Gift): MessageType | undefined - { - switch (giftData.sender) - { + protected getMessageType(giftData: Gift): MessageType | undefined { + switch (giftData.sender) { case GiftSenderType.SYSTEM: return MessageType.SYSTEM_MESSAGE; case GiftSenderType.TRADER: @@ -216,7 +188,9 @@ export class GiftService case GiftSenderType.USER: return MessageType.USER_MESSAGE; default: - this.logger.error(this.localisationService.getText("gift-unable_to_handle_message_type_command", giftData.sender)); + this.logger.error( + this.localisationService.getText("gift-unable_to_handle_message_type_command", giftData.sender), + ); break; } } @@ -226,30 +200,25 @@ export class GiftService * @param sessionId Player id * @param day What day to give gift for */ - public sendPraporStartingGift(sessionId: string, day: number): void - { + public sendPraporStartingGift(sessionId: string, day: number): void { let giftId: string; - switch (day) - { - case 1: - { + switch (day) { + case 1: { giftId = "PraporGiftDay1"; break; } - case 2: - { + case 2: { giftId = "PraporGiftDay2"; break; } } - if (giftId) - { + if (giftId) { const giftData = this.getGiftById(giftId); - if (!this.profileHelper.playerHasRecievedMaxNumberOfGift(sessionId, giftId, 1)) // Hard-coded to send only one - { + if (!this.profileHelper.playerHasRecievedMaxNumberOfGift(sessionId, giftId, 1)) { + // Hard-coded to send only one this.sendGiftToPlayer(sessionId, giftId); } } diff --git a/project/src/services/InsuranceService.ts b/project/src/services/InsuranceService.ts index 3219a0bd..9cb5f51e 100644 --- a/project/src/services/InsuranceService.ts +++ b/project/src/services/InsuranceService.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { ItemHelper } from "@spt/helpers/ItemHelper"; import { TraderHelper } from "@spt/helpers/TraderHelper"; import { IPmcData } from "@spt/models/eft/common/IPmcData"; @@ -16,14 +15,14 @@ import { SaveServer } from "@spt/servers/SaveServer"; import { DatabaseService } from "@spt/services/DatabaseService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { MailSendService } from "@spt/services/MailSendService"; -import { ICloner } from "@spt/utils/cloners/ICloner"; import { HashUtil } from "@spt/utils/HashUtil"; import { RandomUtil } from "@spt/utils/RandomUtil"; import { TimeUtil } from "@spt/utils/TimeUtil"; +import { ICloner } from "@spt/utils/cloners/ICloner"; +import { inject, injectable } from "tsyringe"; @injectable() -export class InsuranceService -{ +export class InsuranceService { protected insured: Record> = {}; protected insuranceConfig: IInsuranceConfig; @@ -40,8 +39,7 @@ export class InsuranceService @inject("MailSendService") protected mailSendService: MailSendService, @inject("ConfigServer") protected configServer: ConfigServer, @inject("PrimaryCloner") protected cloner: ICloner, - ) - { + ) { this.insuranceConfig = this.configServer.getConfig(ConfigTypes.INSURANCE); } @@ -50,8 +48,7 @@ export class InsuranceService * @param sessionId Player id * @returns True if exists */ - public isuranceDictionaryExists(sessionId: string): boolean - { + public isuranceDictionaryExists(sessionId: string): boolean { return this.insured[sessionId] !== undefined; } @@ -60,13 +57,11 @@ export class InsuranceService * @param sessionId Profile id (session id) * @returns Item array */ - public getInsurance(sessionId: string): Record - { + public getInsurance(sessionId: string): Record { return this.insured[sessionId]; } - public resetInsurance(sessionId: string): void - { + public resetInsurance(sessionId: string): void { this.insured[sessionId] = {}; } @@ -76,21 +71,17 @@ export class InsuranceService * @param sessionID SessionId of current player * @param mapId Id of the map player died/exited that caused the insurance to be issued on */ - public sendInsuredItems(pmcData: IPmcData, sessionID: string, mapId: string): void - { + public sendInsuredItems(pmcData: IPmcData, sessionID: string, mapId: string): void { // Get insurance items for each trader const globals = this.databaseService.getGlobals(); - for (const traderId in this.getInsurance(sessionID)) - { + for (const traderId in this.getInsurance(sessionID)) { const traderBase = this.traderHelper.getTrader(traderId, sessionID); - if (!traderBase) - { + if (!traderBase) { throw new Error(this.localisationService.getText("insurance-unable_to_find_trader_by_id", traderId)); } const dialogueTemplates = this.databaseService.getTrader(traderId).dialogue; - if (!dialogueTemplates) - { + if (!dialogueTemplates) { throw new Error(this.localisationService.getText("insurance-trader_lacks_dialogue_property", traderId)); } @@ -101,8 +92,7 @@ export class InsuranceService }; const traderEnum = this.traderHelper.getTraderById(traderId); - if (!traderEnum) - { + if (!traderEnum) { throw new Error(this.localisationService.getText("insurance-trader_missing_from_enum", traderId)); } // Send "i will go look for your stuff" message from trader to player @@ -112,9 +102,7 @@ export class InsuranceService MessageType.NPC_TRADER, this.randomUtil.getArrayValue(dialogueTemplates?.insuranceStart ?? ["INSURANCE START MESSAGE MISSING"]), undefined, - this.timeUtil.getHoursAsSeconds( - globals.config.Insurance.MaxStorageTimeInHour, - ), + this.timeUtil.getHoursAsSeconds(globals.config.Insurance.MaxStorageTimeInHour), systemData, ); @@ -141,20 +129,20 @@ export class InsuranceService * @param trader Trader base used to insure items * @returns Timestamp to return items to player in seconds */ - protected getInsuranceReturnTimestamp(pmcData: IPmcData, trader: ITraderBase): number - { + protected getInsuranceReturnTimestamp(pmcData: IPmcData, trader: ITraderBase): number { // If override in config is non-zero, use that instead of trader values - if (this.insuranceConfig.returnTimeOverrideSeconds > 0) - { + if (this.insuranceConfig.returnTimeOverrideSeconds > 0) { this.logger.debug( `Insurance override used: returning in ${this.insuranceConfig.returnTimeOverrideSeconds} seconds`, ); return this.timeUtil.getTimestamp() + this.insuranceConfig.returnTimeOverrideSeconds; } - const insuranceReturnTimeBonus = pmcData.Bonuses.find((bonus) => bonus.type === BonusType.INSURANCE_RETURN_TIME); - const insuranceReturnTimeBonusPercent - = 1.0 - (insuranceReturnTimeBonus ? Math.abs(insuranceReturnTimeBonus!.value ?? 0) : 0) / 100; + const insuranceReturnTimeBonus = pmcData.Bonuses.find( + (bonus) => bonus.type === BonusType.INSURANCE_RETURN_TIME, + ); + const insuranceReturnTimeBonusPercent = + 1.0 - (insuranceReturnTimeBonus ? Math.abs(insuranceReturnTimeBonus!.value ?? 0) : 0) / 100; const traderMinReturnAsSeconds = trader.insurance.min_return_hour * TimeUtil.ONE_HOUR_AS_SECONDS; const traderMaxReturnAsSeconds = trader.insurance.max_return_hour * TimeUtil.ONE_HOUR_AS_SECONDS; @@ -165,17 +153,16 @@ export class InsuranceService const hasMarkOfUnheard = this.itemHelper.hasItemWithTpl( pmcData.Inventory.items, ItemTpl.MARKOFUNKNOWN_MARK_OF_THE_UNHEARD, - "SpecialSlot"); - if (hasMarkOfUnheard) - { + "SpecialSlot", + ); + if (hasMarkOfUnheard) { // Reduce return time by globals multipler value randomisedReturnTimeSeconds *= globals.config.Insurance.CoefOfHavingMarkOfUnknown; } // EoD has 30% faster returns const editionModifier = globals.config.Insurance.EditionSendingMessageTime[pmcData.Info.GameVersion]; - if (editionModifier) - { + if (editionModifier) { randomisedReturnTimeSeconds *= editionModifier.multiplier; } @@ -190,12 +177,10 @@ export class InsuranceService * @param sessionID The session ID to update insurance equipment packages in. * @returns void */ - protected adoptOrphanedInsEquipment(sessionID: string): void - { + protected adoptOrphanedInsEquipment(sessionID: string): void { const rootID = this.getRootItemParentID(sessionID); const insuranceData = this.getInsurance(sessionID); - for (const [traderId, items] of Object.entries(insuranceData)) - { + for (const [traderId, items] of Object.entries(insuranceData)) { this.insured[sessionID][traderId] = this.itemHelper.adoptOrphanedItems(rootID, items); } } @@ -204,11 +189,9 @@ export class InsuranceService * Store lost gear post-raid inside profile, ready for later code to pick it up and mail it * @param equipmentPkg Gear to store - generated by getGearLostInRaid() */ - public storeGearLostInRaidToSendLater(sessionID: string, equipmentPkg: IInsuranceEquipmentPkg[]): void - { + public storeGearLostInRaidToSendLater(sessionID: string, equipmentPkg: IInsuranceEquipmentPkg[]): void { // Process all insured items lost in-raid - for (const gear of equipmentPkg) - { + for (const gear of equipmentPkg) { this.addGearToSend(gear); } @@ -226,16 +209,16 @@ export class InsuranceService public mapInsuredItemsToTrader( sessionId: string, lostInsuredItems: Item[], - pmcProfile: IPmcData): IInsuranceEquipmentPkg[] - { + pmcProfile: IPmcData, + ): IInsuranceEquipmentPkg[] { const result: IInsuranceEquipmentPkg[] = []; - for (const lostItem of lostInsuredItems) - { + for (const lostItem of lostInsuredItems) { const insuranceDetails = pmcProfile.InsuredItems.find((insuredItem) => insuredItem.itemId == lostItem._id); - if (!insuranceDetails) - { - this.logger.error(`unable to find insurance details for item id: ${lostItem._id} with tpl: ${lostItem._tpl}`); + if (!insuranceDetails) { + this.logger.error( + `unable to find insurance details for item id: ${lostItem._id} with tpl: ${lostItem._tpl}`, + ); continue; } @@ -259,30 +242,26 @@ export class InsuranceService * @param itemToReturnToPlayer item to store * @param traderId Id of trader item was insured with */ - protected addGearToSend(gear: IInsuranceEquipmentPkg): void - { + protected addGearToSend(gear: IInsuranceEquipmentPkg): void { const sessionId = gear.sessionID; const pmcData = gear.pmcData; const itemToReturnToPlayer = gear.itemToReturnToPlayer; const traderId = gear.traderId; // Ensure insurance array is init - if (!this.isuranceDictionaryExists(sessionId)) - { + if (!this.isuranceDictionaryExists(sessionId)) { this.resetInsurance(sessionId); } // init trader insurance array - if (!this.insuranceTraderArrayExists(sessionId, traderId)) - { + if (!this.insuranceTraderArrayExists(sessionId, traderId)) { this.resetInsuranceTraderArray(sessionId, traderId); } this.addInsuranceItemToArray(sessionId, traderId, itemToReturnToPlayer); // Remove item from insured items array as its been processed - pmcData.InsuredItems = pmcData.InsuredItems.filter((item) => - { + pmcData.InsuredItems = pmcData.InsuredItems.filter((item) => { return item.itemId !== itemToReturnToPlayer._id; }); } @@ -293,8 +272,7 @@ export class InsuranceService * @param traderId Trader items insured with * @returns True if exists */ - protected insuranceTraderArrayExists(sessionId: string, traderId: string): boolean - { + protected insuranceTraderArrayExists(sessionId: string, traderId: string): boolean { return this.insured[sessionId][traderId] !== undefined; } @@ -303,8 +281,7 @@ export class InsuranceService * @param sessionId Player id (session id) * @param traderId Trader items insured with */ - public resetInsuranceTraderArray(sessionId: string, traderId: string): void - { + public resetInsuranceTraderArray(sessionId: string, traderId: string): void { this.insured[sessionId][traderId] = []; } @@ -314,8 +291,7 @@ export class InsuranceService * @param traderId Trader item insured with * @param itemToAdd Insured item (with children) */ - public addInsuranceItemToArray(sessionId: string, traderId: string, itemToAdd: Item): void - { + public addInsuranceItemToArray(sessionId: string, traderId: string, itemToAdd: Item): void { this.insured[sessionId][traderId].push(itemToAdd); } @@ -326,10 +302,10 @@ export class InsuranceService * @param traderId Trader item is insured with * @returns price in roubles */ - public getRoublePriceToInsureItemWithTrader(pmcData: IPmcData, inventoryItem: Item, traderId: string): number - { - const price = this.itemHelper.getStaticItemPrice(inventoryItem._tpl) - * (this.traderHelper.getLoyaltyLevel(traderId, pmcData).insurance_price_coef / 100); + public getRoublePriceToInsureItemWithTrader(pmcData: IPmcData, inventoryItem: Item, traderId: string): number { + const price = + this.itemHelper.getStaticItemPrice(inventoryItem._tpl) * + (this.traderHelper.getLoyaltyLevel(traderId, pmcData).insurance_price_coef / 100); return Math.ceil(price); } @@ -339,8 +315,7 @@ export class InsuranceService * @param sessionID Players id * @returns The root item Id. */ - public getRootItemParentID(sessionID: string): string - { + public getRootItemParentID(sessionID: string): string { // Try to use the equipment id from the profile. I'm not sure this is strictly required, but it feels neat. return this.saveServer.getProfile(sessionID)?.characters?.pmc?.Inventory?.equipment ?? this.hashUtil.generate(); } diff --git a/project/src/services/ItemBaseClassService.ts b/project/src/services/ItemBaseClassService.ts index eb1ad4f4..36ee8eec 100644 --- a/project/src/services/ItemBaseClassService.ts +++ b/project/src/services/ItemBaseClassService.ts @@ -1,15 +1,14 @@ -import { inject, injectable } from "tsyringe"; import { ITemplateItem } from "@spt/models/eft/common/tables/ITemplateItem"; import { ILogger } from "@spt/models/spt/utils/ILogger"; import { DatabaseService } from "@spt/services/DatabaseService"; import { LocalisationService } from "@spt/services/LocalisationService"; +import { inject, injectable } from "tsyringe"; /** * Cache the baseids for each item in the tiems db inside a dictionary */ @injectable() -export class ItemBaseClassService -{ +export class ItemBaseClassService { protected itemBaseClassesCache: Record = {}; protected items: Record; protected cacheGenerated = false; @@ -18,32 +17,27 @@ export class ItemBaseClassService @inject("PrimaryLogger") protected logger: ILogger, @inject("LocalisationService") protected localisationService: LocalisationService, @inject("DatabaseService") protected databaseService: DatabaseService, - ) - {} + ) {} /** * Create cache and store inside ItemBaseClassService * Store a dict of an items tpl to the base classes it and its parents have */ - public hydrateItemBaseClassCache(): void - { + public hydrateItemBaseClassCache(): void { // Clear existing cache this.itemBaseClassesCache = {}; this.items = this.databaseService.getItems(); - if (!this.items) - { + if (!this.items) { this.logger.warning(this.localisationService.getText("baseclass-missing_db_no_cache")); return; } const filteredDbItems = Object.values(this.items).filter((x) => x._type === "Item"); - for (const item of filteredDbItems) - { + for (const item of filteredDbItems) { const itemIdToUpdate = item._id; - if (!this.itemBaseClassesCache[item._id]) - { + if (!this.itemBaseClassesCache[item._id]) { this.itemBaseClassesCache[item._id] = []; } @@ -58,13 +52,11 @@ export class ItemBaseClassService * @param itemIdToUpdate item tpl to store base ids against in dictionary * @param item item being checked */ - protected addBaseItems(itemIdToUpdate: string, item: ITemplateItem): void - { + protected addBaseItems(itemIdToUpdate: string, item: ITemplateItem): void { this.itemBaseClassesCache[itemIdToUpdate].push(item._parent); const parent = this.items[item._parent]; - if (parent._parent !== "") - { + if (parent._parent !== "") { this.addBaseItems(itemIdToUpdate, parent); } } @@ -75,15 +67,12 @@ export class ItemBaseClassService * @param baseClass base class to check for * @returns true if item inherits from base class passed in */ - public itemHasBaseClass(itemTpl: string, baseClasses: string[]): boolean - { - if (!this.cacheGenerated) - { + public itemHasBaseClass(itemTpl: string, baseClasses: string[]): boolean { + if (!this.cacheGenerated) { this.hydrateItemBaseClassCache(); } - if (typeof itemTpl === "undefined") - { + if (typeof itemTpl === "undefined") { this.logger.warning("Unable to check itemTpl base class as its undefined"); return false; @@ -91,21 +80,18 @@ export class ItemBaseClassService // The cache is only generated for item templates with `_type === "Item"`, so return false for any other type, // including item templates that simply don't exist. - if (!this.cachedItemIsOfItemType(itemTpl)) - { + if (!this.cachedItemIsOfItemType(itemTpl)) { return false; } // No item in cache - if (!this.itemBaseClassesCache[itemTpl]) - { + if (!this.itemBaseClassesCache[itemTpl]) { // Hydrate again this.logger.debug(this.localisationService.getText("baseclass-item_not_found", itemTpl)); this.hydrateItemBaseClassCache(); // Check for item again, throw exception if not found - if (!this.itemBaseClassesCache[itemTpl]) - { + if (!this.itemBaseClassesCache[itemTpl]) { throw new Error(this.localisationService.getText("baseclass-item_not_found_failed", itemTpl)); } } @@ -118,8 +104,7 @@ export class ItemBaseClassService * @param itemTemplateId item to check * @returns true if item is of type Item */ - private cachedItemIsOfItemType(itemTemplateId: string): boolean - { + private cachedItemIsOfItemType(itemTemplateId: string): boolean { return this.items[itemTemplateId]?._type === "Item"; } @@ -128,15 +113,12 @@ export class ItemBaseClassService * @param itemTpl item to get base classes for * @returns array of base classes */ - public getItemBaseClasses(itemTpl: string): string[] - { - if (!this.cacheGenerated) - { + public getItemBaseClasses(itemTpl: string): string[] { + if (!this.cacheGenerated) { this.hydrateItemBaseClassCache(); } - if (!this.itemBaseClassesCache[itemTpl]) - { + if (!this.itemBaseClassesCache[itemTpl]) { return []; } diff --git a/project/src/services/ItemFilterService.ts b/project/src/services/ItemFilterService.ts index 37f176eb..2f367975 100644 --- a/project/src/services/ItemFilterService.ts +++ b/project/src/services/ItemFilterService.ts @@ -1,15 +1,14 @@ -import { inject, injectable } from "tsyringe"; import { ConfigTypes } from "@spt/models/enums/ConfigTypes"; import { IItemConfig } from "@spt/models/spt/config/IItemConfig"; import { ILogger } from "@spt/models/spt/utils/ILogger"; import { ConfigServer } from "@spt/servers/ConfigServer"; import { DatabaseServer } from "@spt/servers/DatabaseServer"; import { ICloner } from "@spt/utils/cloners/ICloner"; +import { inject, injectable } from "tsyringe"; /** Centralise the handling of blacklisting items, uses blacklist found in config/item.json, stores items that should not be used by players / broken items */ @injectable() -export class ItemFilterService -{ +export class ItemFilterService { protected itemConfig: IItemConfig; protected itemBlacklistCache: Set = new Set(); protected lootableItemBlacklistCache: Set = new Set(); @@ -19,8 +18,7 @@ export class ItemFilterService @inject("PrimaryCloner") protected cloner: ICloner, @inject("DatabaseServer") protected databaseServer: DatabaseServer, @inject("ConfigServer") protected configServer: ConfigServer, - ) - { + ) { this.itemConfig = this.configServer.getConfig(ConfigTypes.ITEM); } @@ -29,10 +27,8 @@ export class ItemFilterService * @param tpl template id * @returns true if blacklisted */ - public isItemBlacklisted(tpl: string): boolean - { - if (this.itemBlacklistCache.size === 0) - { + public isItemBlacklisted(tpl: string): boolean { + if (this.itemBlacklistCache.size === 0) { this.itemConfig.blacklist.forEach((item) => this.itemBlacklistCache.add(item)); } @@ -44,10 +40,8 @@ export class ItemFilterService * @param tpl template id * @returns true if blacklisted */ - public isLootableItemBlacklisted(tpl: string): boolean - { - if (this.lootableItemBlacklistCache.size === 0) - { + public isLootableItemBlacklisted(tpl: string): boolean { + if (this.lootableItemBlacklistCache.size === 0) { this.itemConfig.lootableItemBlacklist.forEach((item) => this.itemBlacklistCache.add(item)); } @@ -59,8 +53,7 @@ export class ItemFilterService * @param tpl item tpl to check is on blacklist * @returns True when blacklisted */ - public isItemRewardBlacklisted(tpl: string): boolean - { + public isItemRewardBlacklisted(tpl: string): boolean { return this.itemConfig.rewardItemBlacklist.includes(tpl); } @@ -68,8 +61,7 @@ export class ItemFilterService * Get an array of items that should never be given as a reward to player * @returns string array of item tpls */ - public getItemRewardBlacklist(): string[] - { + public getItemRewardBlacklist(): string[] { return this.cloner.clone(this.itemConfig.rewardItemBlacklist); } @@ -77,8 +69,7 @@ export class ItemFilterService * Return every template id blacklisted in config/item.json * @returns string array of blacklisted tempalte ids */ - public getBlacklistedItems(): string[] - { + public getBlacklistedItems(): string[] { return this.cloner.clone(this.itemConfig.blacklist); } @@ -86,8 +77,7 @@ export class ItemFilterService * Return every template id blacklisted in config/item.json/lootableItemBlacklist * @returns string array of blacklisted tempalte ids */ - public getBlacklistedLootableItems(): string[] - { + public getBlacklistedLootableItems(): string[] { return this.cloner.clone(this.itemConfig.lootableItemBlacklist); } @@ -96,8 +86,7 @@ export class ItemFilterService * @param tpl template id * @returns true if boss item */ - public isBossItem(tpl: string): boolean - { + public isBossItem(tpl: string): boolean { return this.itemConfig.bossItems.includes(tpl); } @@ -105,8 +94,7 @@ export class ItemFilterService * Return boss items in config/item.json * @returns string array of boss item tempalte ids */ - public getBossItems(): string[] - { + public getBossItems(): string[] { return this.cloner.clone(this.itemConfig.bossItems); } } diff --git a/project/src/services/LegacyLocationLifecycleService.ts b/project/src/services/LegacyLocationLifecycleService.ts index 0c114529..27db9ab4 100644 --- a/project/src/services/LegacyLocationLifecycleService.ts +++ b/project/src/services/LegacyLocationLifecycleService.ts @@ -1,4 +1,3 @@ -import { inject } from "tsyringe"; import { ApplicationContext } from "@spt/context/ApplicationContext"; import { LocationLootGenerator } from "@spt/generators/LocationLootGenerator"; import { LootGenerator } from "@spt/generators/LootGenerator"; @@ -31,13 +30,13 @@ import { MailSendService } from "@spt/services/MailSendService"; import { MatchBotDetailsCacheService } from "@spt/services/MatchBotDetailsCacheService"; import { PmcChatResponseService } from "@spt/services/PmcChatResponseService"; import { RaidTimeAdjustmentService } from "@spt/services/RaidTimeAdjustmentService"; -import { ICloner } from "@spt/utils/cloners/ICloner"; import { HashUtil } from "@spt/utils/HashUtil"; import { RandomUtil } from "@spt/utils/RandomUtil"; import { TimeUtil } from "@spt/utils/TimeUtil"; +import { ICloner } from "@spt/utils/cloners/ICloner"; +import { inject } from "tsyringe"; -export class LegacyLocationLifecycleService -{ +export class LegacyLocationLifecycleService { protected matchConfig: IMatchConfig; protected inRaidConfig: IInRaidConfig; protected traderConfig: ITraderConfig; @@ -70,8 +69,7 @@ export class LegacyLocationLifecycleService @inject("ApplicationContext") protected applicationContext: ApplicationContext, @inject("LocationLootGenerator") protected locationLootGenerator: LocationLootGenerator, @inject("PrimaryCloner") protected cloner: ICloner, - ) - { + ) { this.traderConfig = this.configServer.getConfig(ConfigTypes.TRADER); this.ragfairConfig = this.configServer.getConfig(ConfigTypes.RAGFAIR); this.hideoutConfig = this.configServer.getConfig(ConfigTypes.HIDEOUT); @@ -82,8 +80,7 @@ export class LegacyLocationLifecycleService * Handle client/match/offline/end * @deprecated */ - public endOfflineRaid(info: IEndOfflineRaidRequestData, sessionId: string): void - { + public endOfflineRaid(info: IEndOfflineRaidRequestData, sessionId: string): void { const pmcData: IPmcData = this.profileHelper.getPmcProfile(sessionId); const extractName = info.exitName; @@ -96,13 +93,11 @@ export class LegacyLocationLifecycleService // Clear bot loot cache this.botLootCacheService.clearCache(); - if (this.extractWasViaCar(extractName)) - { + if (this.extractWasViaCar(extractName)) { this.handleCarExtract(extractName, pmcData, sessionId); } - if (extractName && this.extractWasViaCoop(extractName) && this.traderConfig.fence.coopExtractGift.sendGift) - { + if (extractName && this.extractWasViaCoop(extractName) && this.traderConfig.fence.coopExtractGift.sendGift) { this.handleCoopExtract(sessionId, pmcData, extractName); this.sendCoopTakenFenceMessage(sessionId); } @@ -114,11 +109,9 @@ export class LegacyLocationLifecycleService * @param pmcData Player profile * @param sessionId Session id */ - protected handleCarExtract(extractName: string, pmcData: IPmcData, sessionId: string): void - { + protected handleCarExtract(extractName: string, pmcData: IPmcData, sessionId: string): void { // Ensure key exists for extract - if (!(extractName in pmcData.CarExtractCounts)) - { + if (!(extractName in pmcData.CarExtractCounts)) { pmcData.CarExtractCounts[extractName] = 0; } @@ -156,8 +149,7 @@ export class LegacyLocationLifecycleService * @param extractCount Number of times extract was taken * @returns Fence standing after taking extract */ - protected getFenceStandingAfterExtract(pmcData: IPmcData, baseGain: number, extractCount: number): number - { + protected getFenceStandingAfterExtract(pmcData: IPmcData, baseGain: number, extractCount: number): number { // Get current standing const fenceId: string = Traders.FENCE; let fenceStanding = Number(pmcData.TradersInfo[fenceId].standing); @@ -177,16 +169,13 @@ export class LegacyLocationLifecycleService * @param extractName name of extract * @returns true if car extract */ - protected extractWasViaCar(extractName: string): boolean - { + protected extractWasViaCar(extractName: string): boolean { // exit name is undefined on death - if (!extractName) - { + if (!extractName) { return false; } - if (extractName.toLowerCase().includes("v-ex")) - { + if (extractName.toLowerCase().includes("v-ex")) { return true; } @@ -198,11 +187,9 @@ export class LegacyLocationLifecycleService * @param extractName Name of extract player took * @returns True if coop extract */ - protected extractWasViaCoop(extractName: string): boolean - { + protected extractWasViaCoop(extractName: string): boolean { // No extract name, not a coop extract - if (!extractName) - { + if (!extractName) { return false; } @@ -215,16 +202,13 @@ export class LegacyLocationLifecycleService * @param pmcData Profile * @param extractName Name of extract taken */ - protected handleCoopExtract(sessionId: string, pmcData: IPmcData, extractName: string): void - { - if (!pmcData.CoopExtractCounts) - { + protected handleCoopExtract(sessionId: string, pmcData: IPmcData, extractName: string): void { + if (!pmcData.CoopExtractCounts) { pmcData.CoopExtractCounts = {}; } // Ensure key exists for extract - if (!(extractName in pmcData.CoopExtractCounts)) - { + if (!(extractName in pmcData.CoopExtractCounts)) { pmcData.CoopExtractCounts[extractName] = 0; } @@ -250,15 +234,13 @@ export class LegacyLocationLifecycleService scavData.TradersInfo[fenceId].loyaltyLevel = pmcData.TradersInfo[fenceId].loyaltyLevel; } - protected sendCoopTakenFenceMessage(sessionId: string): void - { + protected sendCoopTakenFenceMessage(sessionId: string): void { // Generate reward for taking coop extract const loot = this.lootGenerator.createRandomLoot(this.traderConfig.fence.coopExtractGift); const mailableLoot: Item[] = []; const parentId = this.hashUtil.generate(); - for (const item of loot) - { + for (const item of loot) { item.parentId = parentId; mailableLoot.push(item); } diff --git a/project/src/services/LocaleService.ts b/project/src/services/LocaleService.ts index 7f373e8c..f0d4682c 100644 --- a/project/src/services/LocaleService.ts +++ b/project/src/services/LocaleService.ts @@ -1,24 +1,22 @@ -import { inject, injectable } from "tsyringe"; import { ConfigTypes } from "@spt/models/enums/ConfigTypes"; import { ILocaleConfig } from "@spt/models/spt/config/ILocaleConfig"; import { ILogger } from "@spt/models/spt/utils/ILogger"; import { ConfigServer } from "@spt/servers/ConfigServer"; import { DatabaseServer } from "@spt/servers/DatabaseServer"; +import { inject, injectable } from "tsyringe"; /** * Handles getting locales from config or users machine */ @injectable() -export class LocaleService -{ +export class LocaleService { protected localeConfig: ILocaleConfig; constructor( @inject("PrimaryLogger") protected logger: ILogger, @inject("DatabaseServer") protected databaseServer: DatabaseServer, @inject("ConfigServer") protected configServer: ConfigServer, - ) - { + ) { this.localeConfig = this.configServer.getConfig(ConfigTypes.LOCALE); } @@ -26,11 +24,9 @@ export class LocaleService * Get the eft globals db file based on the configured locale in config/locale.json, if not found, fall back to 'en' * @returns dictionary */ - public getLocaleDb(): Record - { + public getLocaleDb(): Record { const desiredLocale = this.databaseServer.getTables().locales!.global[this.getDesiredGameLocale()]; - if (desiredLocale) - { + if (desiredLocale) { return desiredLocale; } @@ -46,10 +42,8 @@ export class LocaleService * if value is 'system' get system locale * @returns locale e.g en/ge/cz/cn */ - public getDesiredGameLocale(): string - { - if (this.localeConfig.gameLocale.toLowerCase() === "system") - { + public getDesiredGameLocale(): string { + if (this.localeConfig.gameLocale.toLowerCase() === "system") { return this.getPlatformForClientLocale(); } @@ -61,10 +55,8 @@ export class LocaleService * if value is 'system' get system locale * @returns locale e.g en/ge/cz/cn */ - public getDesiredServerLocale(): string - { - if (this.localeConfig.serverLocale.toLowerCase() === "system") - { + public getDesiredServerLocale(): string { + if (this.localeConfig.serverLocale.toLowerCase() === "system") { return this.getPlatformForServerLocale(); } @@ -75,8 +67,7 @@ export class LocaleService * Get array of languages supported for localisation * @returns array of locales e.g. en/fr/cn */ - public getServerSupportedLocales(): string[] - { + public getServerSupportedLocales(): string[] { return this.localeConfig.serverSupportedLocales; } @@ -84,8 +75,7 @@ export class LocaleService * Get array of languages supported for localisation * @returns array of locales e.g. en/fr/cn */ - public getLocaleFallbacks(): { [locale: string]: string } - { + public getLocaleFallbacks(): { [locale: string]: string } { return this.localeConfig.fallbacks; } @@ -93,23 +83,19 @@ export class LocaleService * Get the full locale of the computer running the server lowercased e.g. en-gb / pt-pt * @returns string */ - protected getPlatformForServerLocale(): string - { + protected getPlatformForServerLocale(): string { const platformLocale = this.getPlatformLocale(); - if (!platformLocale) - { + if (!platformLocale) { this.logger.warning("System language could not be found, falling back to english"); return "en"; } const baseNameCode = platformLocale.baseName.toLowerCase(); - if (!this.localeConfig.serverSupportedLocales.includes(baseNameCode)) - { + if (!this.localeConfig.serverSupportedLocales.includes(baseNameCode)) { // Chek if base language (e.g. CN / EN / DE) exists const languageCode = platformLocale.language.toLocaleLowerCase(); - if (this.localeConfig.serverSupportedLocales.includes(languageCode)) - { + if (this.localeConfig.serverSupportedLocales.includes(languageCode)) { return languageCode; } @@ -125,37 +111,31 @@ export class LocaleService * Get the locale of the computer running the server * @returns langage part of locale e.g. 'en' part of 'en-US' */ - protected getPlatformForClientLocale(): string - { + protected getPlatformForClientLocale(): string { const platformLocale = this.getPlatformLocale(); - if (!platformLocale) - { + if (!platformLocale) { this.logger.warning("System language could not be found, falling back to english"); return "en"; } const locales = this.databaseServer.getTables().locales!; const baseNameCode = platformLocale.baseName?.toLocaleLowerCase(); - if (baseNameCode && locales.global[baseNameCode]) - { + if (baseNameCode && locales.global[baseNameCode]) { return baseNameCode; } const languageCode = platformLocale.language?.toLowerCase(); - if (languageCode && locales.global[languageCode]) - { + if (languageCode && locales.global[languageCode]) { return languageCode; } const regionCode = platformLocale.region?.toLocaleLowerCase(); - if (regionCode && locales.global[regionCode]) - { + if (regionCode && locales.global[regionCode]) { return regionCode; } // BSG map DE to GE some reason - if (platformLocale.language === "de") - { + if (platformLocale.language === "de") { return "ge"; } @@ -167,8 +147,7 @@ export class LocaleService * This is in a function so we can overwrite it during testing * @returns The current platform locale */ - protected getPlatformLocale(): Intl.Locale - { + protected getPlatformLocale(): Intl.Locale { return new Intl.Locale(Intl.DateTimeFormat().resolvedOptions().locale); } } diff --git a/project/src/services/LocalisationService.ts b/project/src/services/LocalisationService.ts index 14707660..232a09bf 100644 --- a/project/src/services/LocalisationService.ts +++ b/project/src/services/LocalisationService.ts @@ -1,17 +1,16 @@ import path from "node:path"; -import { I18n } from "i18n"; -import { inject, injectable } from "tsyringe"; import { ILogger } from "@spt/models/spt/utils/ILogger"; import { DatabaseServer } from "@spt/servers/DatabaseServer"; import { LocaleService } from "@spt/services/LocaleService"; import { RandomUtil } from "@spt/utils/RandomUtil"; +import { I18n } from "i18n"; +import { inject, injectable } from "tsyringe"; /** * Handles translating server text into different langauges */ @injectable() -export class LocalisationService -{ +export class LocalisationService { protected i18n: I18n; constructor( @@ -19,8 +18,7 @@ export class LocalisationService @inject("RandomUtil") protected randomUtil: RandomUtil, @inject("DatabaseServer") protected databaseServer: DatabaseServer, @inject("LocaleService") protected localeService: LocaleService, - ) - { + ) { const localeFileDirectory = path.join( process.cwd(), globalThis.G_RELEASE_CONFIGURATION @@ -44,8 +42,7 @@ export class LocalisationService * @param args optional arguments * @returns Localised string */ - public getText(key: string, args?: any): string - { + public getText(key: string, args?: any): string { return args === undefined ? this.i18n.__(key.toLowerCase()) : this.i18n.__(key.toLowerCase(), args); } @@ -53,8 +50,7 @@ export class LocalisationService * Get all locale keys * @returns string array of keys */ - public getKeys(): string[] - { + public getKeys(): string[] { return Object.keys(this.databaseServer.getTables().locales!.server.en); } @@ -63,8 +59,7 @@ export class LocalisationService * @param partialKey Key to match locale keys on * @returns locale text */ - public getRandomTextThatMatchesPartialKey(partialKey: string): string - { + public getRandomTextThatMatchesPartialKey(partialKey: string): string { const filteredKeys = Object.keys(this.databaseServer.getTables().locales!.server.en).filter((x) => x.startsWith(partialKey), ); diff --git a/project/src/services/LocationLifecycleService.ts b/project/src/services/LocationLifecycleService.ts index 13297195..375cf7b0 100644 --- a/project/src/services/LocationLifecycleService.ts +++ b/project/src/services/LocationLifecycleService.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { ApplicationContext } from "@spt/context/ApplicationContext"; import { ContextVariableType } from "@spt/context/ContextVariableType"; import { LocationLootGenerator } from "@spt/generators/LocationLootGenerator"; @@ -36,14 +35,14 @@ import { MailSendService } from "@spt/services/MailSendService"; import { MatchBotDetailsCacheService } from "@spt/services/MatchBotDetailsCacheService"; import { PmcChatResponseService } from "@spt/services/PmcChatResponseService"; import { RaidTimeAdjustmentService } from "@spt/services/RaidTimeAdjustmentService"; -import { ICloner } from "@spt/utils/cloners/ICloner"; import { HashUtil } from "@spt/utils/HashUtil"; import { RandomUtil } from "@spt/utils/RandomUtil"; import { TimeUtil } from "@spt/utils/TimeUtil"; +import { ICloner } from "@spt/utils/cloners/ICloner"; +import { inject, injectable } from "tsyringe"; @injectable() -export class LocationLifecycleService -{ +export class LocationLifecycleService { protected inRaidConfig: IInRaidConfig; protected traderConfig: ITraderConfig; protected ragfairConfig: IRagfairConfig; @@ -75,8 +74,7 @@ export class LocationLifecycleService @inject("ApplicationContext") protected applicationContext: ApplicationContext, @inject("LocationLootGenerator") protected locationLootGenerator: LocationLootGenerator, @inject("PrimaryCloner") protected cloner: ICloner, - ) - { + ) { this.inRaidConfig = this.configServer.getConfig(ConfigTypes.IN_RAID); this.traderConfig = this.configServer.getConfig(ConfigTypes.TRADER); this.ragfairConfig = this.configServer.getConfig(ConfigTypes.RAGFAIR); @@ -84,8 +82,7 @@ export class LocationLifecycleService this.locationConfig = this.configServer.getConfig(ConfigTypes.LOCATION); } - public startLocalRaid(sessionId: string, request: IStartLocalRaidRequestData): IStartLocalRaidResponseData - { + public startLocalRaid(sessionId: string, request: IStartLocalRaidRequestData): IStartLocalRaidResponseData { const playerProfile = this.profileHelper.getPmcProfile(sessionId); const result: IStartLocalRaidResponseData = { @@ -106,8 +103,7 @@ export class LocationLifecycleService * @param name Map name * @returns ILocationBase */ - protected generateLocationAndLoot(name: string): ILocationBase - { + protected generateLocationAndLoot(name: string): ILocationBase { const location = this.databaseService.getLocation(name); const locationBaseClone = this.cloner.clone(location.base); @@ -115,8 +111,7 @@ export class LocationLifecycleService locationBaseClone.UnixDateTime = this.timeUtil.getTimestamp(); // Don't generate loot for hideout - if (name === "hideout") - { + if (name === "hideout") { return locationBaseClone; } @@ -125,8 +120,7 @@ export class LocationLifecycleService const raidAdjustments = this.applicationContext .getLatestValue(ContextVariableType.RAID_ADJUSTMENTS) ?.getValue(); - if (raidAdjustments) - { + if (raidAdjustments) { locationConfigClone = this.cloner.clone(this.locationConfig); // Clone values so they can be used to reset originals later this.raidTimeAdjustmentService.makeAdjustmentsToMap(raidAdjustments, locationBaseClone); } @@ -145,8 +139,7 @@ export class LocationLifecycleService name, ); - for (const spawnPoint of dynamicSpawnPoints) - { + for (const spawnPoint of dynamicSpawnPoints) { locationBaseClone.Loot.push(spawnPoint); } @@ -157,8 +150,7 @@ export class LocationLifecycleService this.logger.success(this.localisationService.getText("location-generated_success", name)); // Reset loot multipliers back to original values - if (raidAdjustments) - { + if (raidAdjustments) { this.logger.debug("Resetting loot multipliers back to their original values"); this.locationConfig.staticLootMultiplier = locationConfigClone.staticLootMultiplier; this.locationConfig.looseLootMultiplier = locationConfigClone.looseLootMultiplier; @@ -169,8 +161,7 @@ export class LocationLifecycleService return locationBaseClone; } - public endLocalRaid(sessionId: string, request: IEndLocalRaidRequestData): void - { + public endLocalRaid(sessionId: string, request: IEndLocalRaidRequestData): void { // Clear bot loot cache this.botLootCacheService.clearCache(); @@ -198,38 +189,25 @@ export class LocationLifecycleService const mapBase = this.databaseService.getLocation(locationName).base; const isDead = this.isPlayerDead(request.results); - if (!isPmc) - { - this.handlePostRaidPlayerScav( - sessionId, - pmcProfile, - scavProfile, - isDead, - request); + if (!isPmc) { + this.handlePostRaidPlayerScav(sessionId, pmcProfile, scavProfile, isDead, request); return; } - this.handlePostRaidPmc( - sessionId, - pmcProfile, - scavProfile, - postRaidProfile, - isDead, - request, - locationName); + this.handlePostRaidPmc(sessionId, pmcProfile, scavProfile, postRaidProfile, isDead, request, locationName); // Handle car extracts - if (this.extractWasViaCar(request.results.exitName)) - { + if (this.extractWasViaCar(request.results.exitName)) { this.handleCarExtract(request.results.exitName, pmcProfile, sessionId); } // Handle coop exit - if (request.results.exitName - && this.extractTakenWasCoop(request.results.exitName) - && this.traderConfig.fence.coopExtractGift.sendGift) - { + if ( + request.results.exitName && + this.extractTakenWasCoop(request.results.exitName) && + this.traderConfig.fence.coopExtractGift.sendGift + ) { this.handleCoopExtract(sessionId, pmcProfile, request.results.exitName); this.sendCoopTakenFenceMessage(sessionId); } @@ -240,16 +218,13 @@ export class LocationLifecycleService * @param extractName name of extract * @returns True if extract was by car */ - protected extractWasViaCar(extractName: string): boolean - { + protected extractWasViaCar(extractName: string): boolean { // exit name is undefined on death - if (!extractName) - { + if (!extractName) { return false; } - if (extractName.toLowerCase().includes("v-ex")) - { + if (extractName.toLowerCase().includes("v-ex")) { return true; } @@ -262,11 +237,9 @@ export class LocationLifecycleService * @param pmcData Player profile * @param sessionId Session id */ - protected handleCarExtract(extractName: string, pmcData: IPmcData, sessionId: string): void - { + protected handleCarExtract(extractName: string, pmcData: IPmcData, sessionId: string): void { // Ensure key exists for extract - if (!(extractName in pmcData.CarExtractCounts)) - { + if (!(extractName in pmcData.CarExtractCounts)) { pmcData.CarExtractCounts[extractName] = 0; } @@ -303,13 +276,11 @@ export class LocationLifecycleService * @param pmcData Profile * @param extractName Name of extract taken */ - protected handleCoopExtract(sessionId: string, pmcData: IPmcData, extractName: string): void - { + protected handleCoopExtract(sessionId: string, pmcData: IPmcData, extractName: string): void { pmcData.CoopExtractCounts ||= {}; // Ensure key exists for extract - if (!(extractName in pmcData.CoopExtractCounts)) - { + if (!(extractName in pmcData.CoopExtractCounts)) { pmcData.CoopExtractCounts[extractName] = 0; } @@ -342,8 +313,7 @@ export class LocationLifecycleService * @param extractCount Number of times extract was taken * @returns Fence standing after taking extract */ - protected getFenceStandingAfterExtract(pmcData: IPmcData, baseGain: number, extractCount: number): number - { + protected getFenceStandingAfterExtract(pmcData: IPmcData, baseGain: number, extractCount: number): number { // Get current standing const fenceId: string = Traders.FENCE; let fenceStanding = Number(pmcData.TradersInfo[fenceId].standing); @@ -358,15 +328,13 @@ export class LocationLifecycleService return Number(newFenceStanding.toFixed(2)); } - protected sendCoopTakenFenceMessage(sessionId: string): void - { + protected sendCoopTakenFenceMessage(sessionId: string): void { // Generate reward for taking coop extract const loot = this.lootGenerator.createRandomLoot(this.traderConfig.fence.coopExtractGift); const mailableLoot: Item[] = []; const parentId = this.hashUtil.generate(); - for (const item of loot) - { + for (const item of loot) { item.parentId = parentId; mailableLoot.push(item); } @@ -387,11 +355,9 @@ export class LocationLifecycleService * @param extractName Name of extract player took * @returns True if coop extract */ - protected extractTakenWasCoop(extractName: string): boolean - { + protected extractTakenWasCoop(extractName: string): boolean { // No extract name, not a coop extract - if (!extractName) - { + if (!extractName) { return false; } @@ -404,11 +370,9 @@ export class LocationLifecycleService scavProfile: IPmcData, isDead: boolean, request: IEndLocalRaidRequestData, - ): void - { + ): void { // Scav died, regen scav loadout and reset timer - if (isDead) - { + if (isDead) { this.playerScavGenerator.generate(sessionId); } @@ -458,8 +422,7 @@ export class LocationLifecycleService isDead: boolean, request: IEndLocalRaidRequestData, locationName: string, - ): void - { + ): void { // Update inventory this.inRaidHelper.setInventory(sessionId, pmcProfile, postRaidProfile); @@ -495,19 +458,10 @@ export class LocationLifecycleService this.resetSkillPointsEarnedDuringRaid(pmcProfile.Skills.Common); // Handle temp, hydration, limb hp/effects - this.healthHelper.updateProfileHealthPostRaid( - pmcProfile, - postRaidProfile.Health, - sessionId, - isDead); + this.healthHelper.updateProfileHealthPostRaid(pmcProfile, postRaidProfile.Health, sessionId, isDead); - if (isDead) - { - this.pmcChatResponseService.sendKillerResponse( - sessionId, - pmcProfile, - postRaidProfile.Stats.Eft.Aggressor, - ); + if (isDead) { + this.pmcChatResponseService.sendKillerResponse(sessionId, pmcProfile, postRaidProfile.Stats.Eft.Aggressor); this.inRaidHelper.deleteInventory(pmcProfile, sessionId); } @@ -518,8 +472,7 @@ export class LocationLifecycleService const victims = postRaidProfile.Stats.Eft.Victims.filter((victim) => ["pmcbear", "pmcusec"].includes(victim.Role.toLowerCase()), ); - if (victims?.length > 0) - { + if (victims?.length > 0) { // Player killed PMCs, send some responses to them this.pmcChatResponseService.sendVictimResponse(sessionId, victims, pmcProfile); } @@ -527,18 +480,15 @@ export class LocationLifecycleService // Handle items transferred via BTR to player this.handleBTRItemTransferEvent(sessionId, request); - if (request.lostInsuredItems?.length > 0) - { + if (request.lostInsuredItems?.length > 0) { const mappedItems = this.insuranceService.mapInsuredItemsToTrader( sessionId, request.lostInsuredItems, - request.results.profile); - - this.insuranceService.storeGearLostInRaidToSendLater( - sessionId, - mappedItems, + request.results.profile, ); + this.insuranceService.storeGearLostInRaidToSendLater(sessionId, mappedItems); + this.insuranceService.sendInsuredItems(pmcProfile, sessionId, locationName); } } @@ -551,19 +501,15 @@ export class LocationLifecycleService protected applyTraderStandingAdjustments( tradersServerProfile: Record, tradersClientProfile: Record, - ): void - { - for (const traderId in tradersClientProfile) - { + ): void { + for (const traderId in tradersClientProfile) { const serverProfileTrader = tradersServerProfile[traderId]; const clientProfileTrader = tradersClientProfile[traderId]; - if (!(serverProfileTrader && clientProfileTrader)) - { + if (!(serverProfileTrader && clientProfileTrader)) { continue; } - if (clientProfileTrader.standing !== serverProfileTrader.standing) - { + if (clientProfileTrader.standing !== serverProfileTrader.standing) { // Difference found, update server profile with values from client profile tradersServerProfile[traderId].standing = clientProfileTrader.standing; } @@ -575,28 +521,24 @@ export class LocationLifecycleService * @param sessionId Session id * @param request End raid request */ - protected handleBTRItemTransferEvent( - sessionId: string, - request: IEndLocalRaidRequestData): void - { + protected handleBTRItemTransferEvent(sessionId: string, request: IEndLocalRaidRequestData): void { const btrKey = "BTRTransferStash"; const btrContainerAndItems = request.transferItems[btrKey] ?? []; - if (btrContainerAndItems.length > 0) - { + if (btrContainerAndItems.length > 0) { const itemsToSend = btrContainerAndItems.filter((item) => item._id !== btrKey); this.btrItemDelivery(sessionId, Traders.BTR, itemsToSend); - }; + } } - protected btrItemDelivery(sessionId: string, traderId: string, items: Item[]): void - { + protected btrItemDelivery(sessionId: string, traderId: string, items: Item[]): void { const serverProfile = this.saveServer.getProfile(sessionId); const pmcData = serverProfile.characters.pmc; const dialogueTemplates = this.databaseService.getTrader(traderId).dialogue; - if (!dialogueTemplates) - { - this.logger.error(this.localisationService.getText("inraid-unable_to_deliver_item_no_trader_found", traderId)); + if (!dialogueTemplates) { + this.logger.error( + this.localisationService.getText("inraid-unable_to_deliver_item_no_trader_found", traderId), + ); return; } @@ -606,8 +548,9 @@ export class LocationLifecycleService // Remove any items that were returned by the item delivery, but also insured, from the player's insurance list // This is to stop items being duplicated by being returned from both item delivery and insurance const deliveredItemIds = items.map((item) => item._id); - pmcData.InsuredItems = pmcData.InsuredItems - .filter((insuredItem) => !deliveredItemIds.includes(insuredItem.itemId)); + pmcData.InsuredItems = pmcData.InsuredItems.filter( + (insuredItem) => !deliveredItemIds.includes(insuredItem.itemId), + ); // Send the items to the player this.mailSendService.sendLocalisedNpcMessageToPlayer( @@ -625,8 +568,7 @@ export class LocationLifecycleService * @param items Players inventory to search through * @returns an array of equipped items */ - protected getEquippedGear(items: Item[]): Item[] - { + protected getEquippedGear(items: Item[]): Item[] { // Player Slots we care about const inventorySlots = [ "FirstPrimaryWeapon", @@ -654,27 +596,21 @@ export class LocationLifecycleService let inventoryItems: Item[] = []; // Get an array of root player items - for (const item of items) - { - if (inventorySlots.includes(item.slotId)) - { + for (const item of items) { + if (inventorySlots.includes(item.slotId)) { inventoryItems.push(item); } } // Loop through these items and get all of their children let newItems = inventoryItems; - while (newItems.length > 0) - { + while (newItems.length > 0) { const foundItems = []; - for (const item of newItems) - { + for (const item of newItems) { // Find children of this item - for (const newItem of items) - { - if (newItem.parentId === item._id) - { + for (const newItem of items) { + if (newItem.parentId === item._id) { foundItems.push(newItem); } } @@ -695,8 +631,7 @@ export class LocationLifecycleService * @param statusOnExit Exit value from offraidData object * @returns true if dead */ - protected isPlayerDead(results: IEndRaidResult): boolean - { + protected isPlayerDead(results: IEndRaidResult): boolean { return ["killed", "missinginaction", "left"].includes(results.result.toLowerCase()); } @@ -704,10 +639,8 @@ export class LocationLifecycleService * Reset the skill points earned in a raid to 0, ready for next raid * @param commonSkills Profile common skills to update */ - protected resetSkillPointsEarnedDuringRaid(commonSkills: Common[]): void - { - for (const skill of commonSkills) - { + protected resetSkillPointsEarnedDuringRaid(commonSkills: Common[]): void { + for (const skill of commonSkills) { skill.PointsEarnedDuringSession = 0.0; } } @@ -718,14 +651,10 @@ export class LocationLifecycleService * @param primary main dictionary * @param secondary Secondary dictionary */ - protected mergePmcAndScavEncyclopedias(primary: IPmcData, secondary: IPmcData): void - { - function extend(target: { [key: string]: boolean }, source: Record) - { - for (const key in source) - { - if (Object.hasOwn(source, key)) - { + protected mergePmcAndScavEncyclopedias(primary: IPmcData, secondary: IPmcData): void { + function extend(target: { [key: string]: boolean }, source: Record) { + for (const key in source) { + if (Object.hasOwn(source, key)) { target[key] = source[key]; } } diff --git a/project/src/services/MailSendService.ts b/project/src/services/MailSendService.ts index acb07df9..ab3ce63f 100644 --- a/project/src/services/MailSendService.ts +++ b/project/src/services/MailSendService.ts @@ -1,11 +1,17 @@ -import { inject, injectable } from "tsyringe"; import { DialogueHelper } from "@spt/helpers/DialogueHelper"; import { ItemHelper } from "@spt/helpers/ItemHelper"; import { NotificationSendHelper } from "@spt/helpers/NotificationSendHelper"; import { NotifierHelper } from "@spt/helpers/NotifierHelper"; import { TraderHelper } from "@spt/helpers/TraderHelper"; import { Item } from "@spt/models/eft/common/tables/IItem"; -import { Dialogue, ISystemData, IUserDialogInfo, Message, MessageContentRagfair, MessageItems } from "@spt/models/eft/profile/ISptProfile"; +import { + Dialogue, + ISystemData, + IUserDialogInfo, + Message, + MessageContentRagfair, + MessageItems, +} from "@spt/models/eft/profile/ISptProfile"; import { BaseClasses } from "@spt/models/enums/BaseClasses"; import { MessageType } from "@spt/models/enums/MessageType"; import { Traders } from "@spt/models/enums/Traders"; @@ -16,10 +22,10 @@ import { DatabaseService } from "@spt/services/DatabaseService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { HashUtil } from "@spt/utils/HashUtil"; import { TimeUtil } from "@spt/utils/TimeUtil"; +import { inject, injectable } from "tsyringe"; @injectable() -export class MailSendService -{ +export class MailSendService { protected readonly systemSenderId = "59e7125688a45068a6249071"; constructor( @@ -34,8 +40,7 @@ export class MailSendService @inject("LocalisationService") protected localisationService: LocalisationService, @inject("ItemHelper") protected itemHelper: ItemHelper, @inject("TraderHelper") protected traderHelper: TraderHelper, - ) - {} + ) {} /** * Send a message from an NPC (e.g. prapor) to the player with or without items using direct message text, do not look up any locale @@ -55,10 +60,8 @@ export class MailSendService maxStorageTimeSeconds?: number, systemData?: ISystemData, ragfair?: MessageContentRagfair, - ): void - { - if (!trader) - { + ): void { + if (!trader) { this.logger.error( this.localisationService.getText("mailsend-missing_trader", { messageType: messageType, @@ -78,19 +81,16 @@ export class MailSendService }; // Add items to message - if (items?.length > 0) - { + if (items?.length > 0) { details.items = items; details.itemsMaxStorageLifetimeSeconds = maxStorageTimeSeconds ?? 172800; // 48 hours if no value supplied } - if (systemData) - { + if (systemData) { details.systemData = systemData; } - if (ragfair) - { + if (ragfair) { details.ragfairDetails = ragfair; } @@ -115,10 +115,8 @@ export class MailSendService maxStorageTimeSeconds?: number, systemData?: ISystemData, ragfair?: MessageContentRagfair, - ): void - { - if (!trader) - { + ): void { + if (!trader) { this.logger.error( this.localisationService.getText("mailsend-missing_trader", { messageType: messageType, @@ -138,19 +136,16 @@ export class MailSendService }; // Add items to message - if (items?.length > 0) - { + if (items?.length > 0) { details.items = items; details.itemsMaxStorageLifetimeSeconds = maxStorageTimeSeconds ?? 172800; // 48 hours if no value supplied } - if (systemData) - { + if (systemData) { details.systemData = systemData; } - if (ragfair) - { + if (ragfair) { details.ragfairDetails = ragfair; } @@ -170,8 +165,7 @@ export class MailSendService items: Item[] = [], maxStorageTimeSeconds?: number, profileChangeEvents?: IProfileChangeEvent[], - ): void - { + ): void { const details: ISendMessageDetails = { recipientId: sessionId, sender: MessageType.SYSTEM_MESSAGE, @@ -179,14 +173,12 @@ export class MailSendService }; // Add items to message - if (items.length > 0) - { + if (items.length > 0) { details.items = items; details.itemsMaxStorageLifetimeSeconds = maxStorageTimeSeconds ?? 172800; // 48 hours if no value supplied } - if ((profileChangeEvents?.length ?? 0) > 0) - { + if ((profileChangeEvents?.length ?? 0) > 0) { details.profileChangeEvents = profileChangeEvents; } @@ -206,8 +198,7 @@ export class MailSendService items: Item[] = [], profileChangeEvents?: IProfileChangeEvent[], maxStorageTimeSeconds?: number, - ): void - { + ): void { const details: ISendMessageDetails = { recipientId: sessionId, sender: MessageType.SYSTEM_MESSAGE, @@ -215,14 +206,12 @@ export class MailSendService }; // Add items to message - if (items?.length > 0) - { + if (items?.length > 0) { details.items = items; details.itemsMaxStorageLifetimeSeconds = maxStorageTimeSeconds ?? 172800; // 48 hours if no value supplied } - if ((profileChangeEvents?.length ?? 0) > 0) - { + if ((profileChangeEvents?.length ?? 0) > 0) { details.profileChangeEvents = profileChangeEvents; } @@ -243,8 +232,7 @@ export class MailSendService message: string, items: Item[] = [], maxStorageTimeSeconds?: number, - ): void - { + ): void { const details: ISendMessageDetails = { recipientId: sessionId, sender: MessageType.USER_MESSAGE, @@ -253,8 +241,7 @@ export class MailSendService }; // Add items to message - if (items?.length > 0) - { + if (items?.length > 0) { details.items = items; details.itemsMaxStorageLifetimeSeconds = maxStorageTimeSeconds ?? 172800; // 48 hours if no value supplied } @@ -267,8 +254,7 @@ export class MailSendService * Helper functions in this class are available to simplify common actions * @param messageDetails Details needed to send a message to the player */ - public sendMessageToPlayer(messageDetails: ISendMessageDetails): void - { + public sendMessageToPlayer(messageDetails: ISendMessageDetails): void { // Get dialog, create if doesn't exist const senderDialog = this.getDialog(messageDetails); @@ -283,16 +269,14 @@ export class MailSendService const itemsToSendToPlayer = this.processItemsBeforeAddingToMail(senderDialog.type, messageDetails); // If there's items to send to player, flag dialog as containing attachments - if ((itemsToSendToPlayer.data?.length ?? 0) > 0) - { + if ((itemsToSendToPlayer.data?.length ?? 0) > 0) { senderDialog.attachmentsNew += 1; } // Store reward items inside message and set appropriate flags inside message this.addRewardItemsToMessage(message, itemsToSendToPlayer, messageDetails.itemsMaxStorageLifetimeSeconds); - if (messageDetails.profileChangeEvents) - { + if (messageDetails.profileChangeEvents) { message.profileChangeEvents = messageDetails.profileChangeEvents; } @@ -302,10 +286,9 @@ export class MailSendService // TODO: clean up old code here // Offer Sold notifications are now separate from the main notification if ( - [MessageType.NPC_TRADER, MessageType.FLEAMARKET_MESSAGE].includes(senderDialog.type) - && messageDetails.ragfairDetails - ) - { + [MessageType.NPC_TRADER, MessageType.FLEAMARKET_MESSAGE].includes(senderDialog.type) && + messageDetails.ragfairDetails + ) { const offerSoldMessage = this.notifierHelper.createRagfairOfferSoldNotification( message, messageDetails.ragfairDetails, @@ -325,12 +308,10 @@ export class MailSendService * @param targetNpcId NPC message is sent to * @param message Text to send to NPC */ - public sendPlayerMessageToNpc(sessionId: string, targetNpcId: string, message: string): void - { + public sendPlayerMessageToNpc(sessionId: string, targetNpcId: string, message: string): void { const playerProfile = this.saveServer.getProfile(sessionId); const dialogWithNpc = playerProfile.dialogues[targetNpcId]; - if (!dialogWithNpc) - { + if (!dialogWithNpc) { this.logger.error(this.localisationService.getText("mailsend-missing_npc_dialog", targetNpcId)); return; @@ -353,8 +334,7 @@ export class MailSendService * @param messageDetails Various details on what the message must contain/do * @returns Message */ - protected createDialogMessage(dialogId: string, messageDetails: ISendMessageDetails): Message - { + protected createDialogMessage(dialogId: string, messageDetails: ISendMessageDetails): Message { const message: Message = { _id: this.hashUtil.generate(), uid: dialogId, // must match the dialog id @@ -370,14 +350,12 @@ export class MailSendService }; // Clean up empty system data - if (!message.systemData) - { + if (!message.systemData) { delete message.systemData; } // Clean up empty template id - if (!message.templateId) - { + if (!message.templateId) { delete message.templateId; } @@ -394,10 +372,8 @@ export class MailSendService message: Message, itemsToSendToPlayer: MessageItems | undefined, maxStorageTimeSeconds: number | undefined, - ): void - { - if ((itemsToSendToPlayer?.data?.length ?? 0) > 0) - { + ): void { + if ((itemsToSendToPlayer?.data?.length ?? 0) > 0) { message.items = itemsToSendToPlayer; message.hasRewards = true; message.maxStorageTime = maxStorageTimeSeconds; @@ -414,17 +390,14 @@ export class MailSendService protected processItemsBeforeAddingToMail( dialogType: MessageType, messageDetails: ISendMessageDetails, - ): MessageItems - { + ): MessageItems { const items = this.databaseService.getItems(); let itemsToSendToPlayer: MessageItems = {}; - if ((messageDetails.items?.length ?? 0) > 0) - { + if ((messageDetails.items?.length ?? 0) > 0) { // Find base item that should be the 'primary' + have its parent id be used as the dialogs 'stash' value const parentItem = this.getBaseItemFromRewards(messageDetails.items!); - if (!parentItem) - { + if (!parentItem) { this.localisationService.getText("mailsend-missing_parent", { traderId: messageDetails.trader, sender: messageDetails.sender, @@ -434,8 +407,7 @@ export class MailSendService } // No parent id, generate random id and add (doesn't need to be actual parentId from db, only unique) - if (!parentItem?.parentId) - { + if (!parentItem?.parentId) { parentItem.parentId = this.hashUtil.generate(); } @@ -444,12 +416,10 @@ export class MailSendService // Ensure Ids are unique and cont collide with items in player inventory later messageDetails.items = this.itemHelper.replaceIDs(messageDetails.items!); - for (const reward of messageDetails.items) - { + for (const reward of messageDetails.items) { // Ensure item exists in items db const itemTemplate = items[reward._tpl]; - if (!itemTemplate) - { + if (!itemTemplate) { // Can happen when modded items are insured + mod is removed this.logger.error( this.localisationService.getText("dialog-missing_item_template", { @@ -462,27 +432,24 @@ export class MailSendService } // Ensure every 'base/root' item has the same parentId + has a slotid of 'main' - if (!("slotId" in reward) || reward.slotId === "hideout" || reward.parentId === parentItem.parentId) - { + if (!("slotId" in reward) || reward.slotId === "hideout" || reward.parentId === parentItem.parentId) { // Reward items NEED a parent id + slotid reward.parentId = parentItem.parentId; reward.slotId = "main"; } // Boxes can contain sub-items - if (this.itemHelper.isOfBaseclass(itemTemplate._id, BaseClasses.AMMO_BOX)) - { + if (this.itemHelper.isOfBaseclass(itemTemplate._id, BaseClasses.AMMO_BOX)) { const boxAndCartridges: Item[] = [reward]; this.itemHelper.addCartridgesToAmmoBox(boxAndCartridges, itemTemplate); // Push box + cartridge children into array itemsToSendToPlayer.data!.push(...boxAndCartridges); - } - else - { - if ("StackSlots" in itemTemplate._props) - { - this.logger.error(this.localisationService.getText("mail-unable_to_give_gift_not_handled", itemTemplate._id)); + } else { + if ("StackSlots" in itemTemplate._props) { + this.logger.error( + this.localisationService.getText("mail-unable_to_give_gift_not_handled", itemTemplate._id), + ); } // Item is sanitised and ready to be pushed into holding array @@ -491,8 +458,7 @@ export class MailSendService } // Remove empty data property if no rewards - if (itemsToSendToPlayer.data!.length === 0) - { + if (itemsToSendToPlayer.data!.length === 0) { delete itemsToSendToPlayer.data; } } @@ -505,26 +471,22 @@ export class MailSendService * @param items Possible items to choose from * @returns Chosen 'primary' item */ - protected getBaseItemFromRewards(items: Item[]): Item - { + protected getBaseItemFromRewards(items: Item[]): Item { // Only one item in reward, return it - if (items?.length === 1) - { + if (items?.length === 1) { return items[0]; } // Find first item with slotId that indicates its a 'base' item let item = items.find((x) => ["hideout", "main"].includes(x.slotId ?? "")); - if (item) - { + if (item) { return item; } // Not a singlular item + no items have a hideout/main slotid // Look for first item without parent id item = items.find((x) => !x.parentId); - if (item) - { + if (item) { return item; } @@ -538,18 +500,17 @@ export class MailSendService * @param messageDetails Data on what message should do * @returns Relevant Dialogue */ - protected getDialog(messageDetails: ISendMessageDetails): Dialogue - { + protected getDialog(messageDetails: ISendMessageDetails): Dialogue { const dialogsInProfile = this.dialogueHelper.getDialogsForProfile(messageDetails.recipientId); const senderId = this.getMessageSenderIdByType(messageDetails); - if (!senderId) - { - throw new Error(this.localisationService.getText("mail-unable_to_find_message_sender_by_id", messageDetails.sender)); + if (!senderId) { + throw new Error( + this.localisationService.getText("mail-unable_to_find_message_sender_by_id", messageDetails.sender), + ); } // Does dialog exist let senderDialog = dialogsInProfile[senderId]; - if (!senderDialog) - { + if (!senderDialog) { // Create if doesn't dialogsInProfile[senderId] = { _id: senderId, @@ -571,32 +532,26 @@ export class MailSendService * @param messageDetails * @returns gets an id of the individual sending it */ - protected getMessageSenderIdByType(messageDetails: ISendMessageDetails): string | undefined - { - if (messageDetails.sender === MessageType.SYSTEM_MESSAGE) - { + protected getMessageSenderIdByType(messageDetails: ISendMessageDetails): string | undefined { + if (messageDetails.sender === MessageType.SYSTEM_MESSAGE) { return this.systemSenderId; } - if (messageDetails.sender === MessageType.NPC_TRADER || messageDetails.dialogType === MessageType.NPC_TRADER) - { + if (messageDetails.sender === MessageType.NPC_TRADER || messageDetails.dialogType === MessageType.NPC_TRADER) { return messageDetails.trader ? this.traderHelper.getValidTraderIdByEnumValue(messageDetails.trader) : undefined; } - if (messageDetails.sender === MessageType.USER_MESSAGE) - { + if (messageDetails.sender === MessageType.USER_MESSAGE) { return messageDetails.senderDetails?._id; } - if (messageDetails.senderDetails?._id) - { + if (messageDetails.senderDetails?._id) { return messageDetails.senderDetails._id; } - if (messageDetails.trader) - { + if (messageDetails.trader) { return this.traderHelper.getValidTraderIdByEnumValue(messageDetails.trader); } diff --git a/project/src/services/MapMarkerService.ts b/project/src/services/MapMarkerService.ts index 42b491e0..48766a16 100644 --- a/project/src/services/MapMarkerService.ts +++ b/project/src/services/MapMarkerService.ts @@ -1,18 +1,14 @@ -import { inject, injectable } from "tsyringe"; import { IPmcData } from "@spt/models/eft/common/IPmcData"; import { Item } from "@spt/models/eft/common/tables/IItem"; import { IInventoryCreateMarkerRequestData } from "@spt/models/eft/inventory/IInventoryCreateMarkerRequestData"; import { IInventoryDeleteMarkerRequestData } from "@spt/models/eft/inventory/IInventoryDeleteMarkerRequestData"; import { IInventoryEditMarkerRequestData } from "@spt/models/eft/inventory/IInventoryEditMarkerRequestData"; import { ILogger } from "@spt/models/spt/utils/ILogger"; +import { inject, injectable } from "tsyringe"; @injectable() -export class MapMarkerService -{ - constructor( - @inject("PrimaryLogger") protected logger: ILogger, - ) - {} +export class MapMarkerService { + constructor(@inject("PrimaryLogger") protected logger: ILogger) {} /** * Add note to a map item in player inventory @@ -20,11 +16,7 @@ export class MapMarkerService * @param request Add marker request * @returns Item */ - public createMarkerOnMap( - pmcData: IPmcData, - request: IInventoryCreateMarkerRequestData, - ): Item - { + public createMarkerOnMap(pmcData: IPmcData, request: IInventoryCreateMarkerRequestData): Item { // Get map from inventory const mapItem = pmcData.Inventory.items.find((i) => i._id === request.item); @@ -44,17 +36,12 @@ export class MapMarkerService * @param request Delete marker request * @returns Item */ - public deleteMarkerFromMap( - pmcData: IPmcData, - request: IInventoryDeleteMarkerRequestData, - ): Item - { + public deleteMarkerFromMap(pmcData: IPmcData, request: IInventoryDeleteMarkerRequestData): Item { // Get map from inventory const mapItem = pmcData.Inventory.items.find((item) => item._id === request.item); // remove marker - const markers = mapItem.upd.Map.Markers.filter((marker) => - { + const markers = mapItem.upd.Map.Markers.filter((marker) => { return marker.X !== request.X && marker.Y !== request.Y; }); mapItem.upd.Map.Markers = markers; @@ -68,11 +55,7 @@ export class MapMarkerService * @param request Edit marker request * @returns Item */ - public editMarkerOnMap( - pmcData: IPmcData, - request: IInventoryEditMarkerRequestData, - ): Item - { + public editMarkerOnMap(pmcData: IPmcData, request: IInventoryEditMarkerRequestData): Item { // Get map from inventory const mapItem = pmcData.Inventory.items.find((item) => item._id === request.item); @@ -89,8 +72,7 @@ export class MapMarkerService * @param mapNoteText Marker text to sanitise * @returns Sanitised map marker text */ - protected sanitiseMapMarkerText(mapNoteText: string): string - { + protected sanitiseMapMarkerText(mapNoteText: string): string { return mapNoteText.replace(/[^\p{L}\d ]/gu, ""); } } diff --git a/project/src/services/MatchBotDetailsCacheService.ts b/project/src/services/MatchBotDetailsCacheService.ts index 0a8f4356..97eb4608 100644 --- a/project/src/services/MatchBotDetailsCacheService.ts +++ b/project/src/services/MatchBotDetailsCacheService.ts @@ -1,34 +1,30 @@ -import { inject, injectable } from "tsyringe"; import { IBotBase } from "@spt/models/eft/common/tables/IBotBase"; import { ILogger } from "@spt/models/spt/utils/ILogger"; import { LocalisationService } from "@spt/services/LocalisationService"; +import { inject, injectable } from "tsyringe"; /** Cache bots in a dictionary, keyed by the bots name, keying by name isnt ideal as its not unique but this is used by the post-raid system which doesnt have any bot ids, only name */ @injectable() -export class MatchBotDetailsCacheService -{ +export class MatchBotDetailsCacheService { protected botDetailsCache: Record = {}; constructor( @inject("PrimaryLogger") protected logger: ILogger, @inject("LocalisationService") protected localisationService: LocalisationService, - ) - {} + ) {} /** * Store a bot in the cache, keyed by its name * @param botToCache Bot details to cache */ - public cacheBot(botToCache: IBotBase): void - { + public cacheBot(botToCache: IBotBase): void { this.botDetailsCache[`${botToCache.Info.Nickname.trim()}${botToCache.Info.Side}`] = botToCache; } /** * Clean the cache of all bot details */ - public clearCache(): void - { + public clearCache(): void { this.botDetailsCache = {}; } @@ -37,11 +33,9 @@ export class MatchBotDetailsCacheService * @param botName Name of bot to find * @returns Bot details */ - public getBotByNameAndSide(botName: string, botSide: string): IBotBase - { + public getBotByNameAndSide(botName: string, botSide: string): IBotBase { const botInCache = this.botDetailsCache[`${botName}${botSide}`]; - if (!botInCache) - { + if (!botInCache) { this.logger.warning(`bot not found in match bot cache: ${botName.toLowerCase()} ${botSide}`); } diff --git a/project/src/services/MatchLocationService.ts b/project/src/services/MatchLocationService.ts index c79cad0a..8cc4761c 100644 --- a/project/src/services/MatchLocationService.ts +++ b/project/src/services/MatchLocationService.ts @@ -1,26 +1,20 @@ -import { inject, injectable } from "tsyringe"; import { SaveServer } from "@spt/servers/SaveServer"; import { TimeUtil } from "@spt/utils/TimeUtil"; +import { inject, injectable } from "tsyringe"; @injectable() -export class MatchLocationService -{ +export class MatchLocationService { protected locations = {}; constructor( @inject("TimeUtil") protected timeUtil: TimeUtil, @inject("SaveServer") protected saveServer: SaveServer, - ) - {} + ) {} - public deleteGroup(info: any): void - { - for (const locationID in this.locations) - { - for (const groupID in this.locations[locationID].groups) - { - if (groupID === info.groupId) - { + public deleteGroup(info: any): void { + for (const locationID in this.locations) { + for (const groupID in this.locations[locationID].groups) { + if (groupID === info.groupId) { delete this.locations[locationID].groups[groupID]; return; } diff --git a/project/src/services/NotificationService.ts b/project/src/services/NotificationService.ts index 3f00ae3d..d10ae2b0 100644 --- a/project/src/services/NotificationService.ts +++ b/project/src/services/NotificationService.ts @@ -1,44 +1,37 @@ -import { injectable } from "tsyringe"; import { IWsNotificationEvent } from "@spt/models/eft/ws/IWsNotificationEvent"; +import { injectable } from "tsyringe"; @injectable() -export class NotificationService -{ +export class NotificationService { protected messageQueue: Record = {}; - public getMessageQueue(): Record - { + public getMessageQueue(): Record { return this.messageQueue; } - public getMessageFromQueue(sessionId: string): any[] - { + public getMessageFromQueue(sessionId: string): any[] { return this.messageQueue[sessionId]; } - public updateMessageOnQueue(sessionId: string, value: any[]): void - { + public updateMessageOnQueue(sessionId: string, value: any[]): void { this.messageQueue[sessionId] = value; } - public has(sessionID: string): boolean - { + public has(sessionID: string): boolean { return this.get(sessionID).length > 0; } /** * Pop first message from queue. */ - public pop(sessionID: string): any - { + public pop(sessionID: string): any { return this.get(sessionID).shift(); } /** * Add message to queue */ - public add(sessionID: string, message: IWsNotificationEvent): void - { + public add(sessionID: string, message: IWsNotificationEvent): void { this.get(sessionID).push(message); } @@ -46,15 +39,12 @@ export class NotificationService * Get message queue for session * @param sessionID */ - public get(sessionID: string): any[] - { - if (!sessionID) - { + public get(sessionID: string): any[] { + if (!sessionID) { throw new Error("sessionID missing"); } - if (!this.messageQueue[sessionID]) - { + if (!this.messageQueue[sessionID]) { this.messageQueue[sessionID] = []; } diff --git a/project/src/services/OpenZoneService.ts b/project/src/services/OpenZoneService.ts index c51036bd..a79d176d 100644 --- a/project/src/services/OpenZoneService.ts +++ b/project/src/services/OpenZoneService.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { ILocationBase } from "@spt/models/eft/common/ILocationBase"; import { ConfigTypes } from "@spt/models/enums/ConfigTypes"; import { ILocationConfig } from "@spt/models/spt/config/ILocationConfig"; @@ -7,11 +6,11 @@ import { ConfigServer } from "@spt/servers/ConfigServer"; import { DatabaseService } from "@spt/services/DatabaseService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { RandomUtil } from "@spt/utils/RandomUtil"; +import { inject, injectable } from "tsyringe"; /** Service for adding new zones to a maps OpenZones property */ @injectable() -export class OpenZoneService -{ +export class OpenZoneService { protected locationConfig: ILocationConfig; constructor( @@ -20,8 +19,7 @@ export class OpenZoneService @inject("DatabaseService") protected databaseService: DatabaseService, @inject("LocalisationService") protected localisationService: LocalisationService, @inject("ConfigServer") protected configServer: ConfigServer, - ) - { + ) { this.locationConfig = this.configServer.getConfig(ConfigTypes.LOCATION); } @@ -30,16 +28,13 @@ export class OpenZoneService * @param locationId map location (e.g. factory4_day) * @param zoneToAdd zone to add */ - public addZoneToMap(locationId: string, zoneToAdd: string): void - { + public addZoneToMap(locationId: string, zoneToAdd: string): void { const location = this.locationConfig.openZones[locationId]; - if (!location) - { + if (!location) { this.locationConfig.openZones[locationId] = []; } - if (!this.locationConfig.openZones[locationId].includes(zoneToAdd)) - { + if (!this.locationConfig.openZones[locationId].includes(zoneToAdd)) { this.locationConfig.openZones[locationId].push(zoneToAdd); } } @@ -47,13 +42,10 @@ export class OpenZoneService /** * Add open zones to all maps found in config/location.json to db */ - public applyZoneChangesToAllMaps(): void - { + public applyZoneChangesToAllMaps(): void { const dbLocations = this.databaseService.getLocations(); - for (const mapKey in this.locationConfig.openZones) - { - if (!dbLocations[mapKey]) - { + for (const mapKey in this.locationConfig.openZones) { + if (!dbLocations[mapKey]) { this.logger.error(this.localisationService.getText("openzone-unable_to_find_map", mapKey)); } @@ -62,10 +54,8 @@ export class OpenZoneService // Convert openzones string into array, easier to work wih const mapOpenZonesArray = dbLocationToUpdate.OpenZones.split(","); - for (const zoneToAdd of zonesToAdd) - { - if (!mapOpenZonesArray.includes(zoneToAdd)) - { + for (const zoneToAdd of zonesToAdd) { + if (!mapOpenZonesArray.includes(zoneToAdd)) { // Add new zone to array and convert array into string again mapOpenZonesArray.push(zoneToAdd); dbLocationToUpdate.OpenZones = mapOpenZonesArray.join(","); diff --git a/project/src/services/PaymentService.ts b/project/src/services/PaymentService.ts index efc0a6e1..27576f2b 100644 --- a/project/src/services/PaymentService.ts +++ b/project/src/services/PaymentService.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { HandbookHelper } from "@spt/helpers/HandbookHelper"; import { InventoryHelper } from "@spt/helpers/InventoryHelper"; import { ItemHelper } from "@spt/helpers/ItemHelper"; @@ -16,10 +15,10 @@ import { DatabaseService } from "@spt/services/DatabaseService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { HashUtil } from "@spt/utils/HashUtil"; import { HttpResponseUtil } from "@spt/utils/HttpResponseUtil"; +import { inject, injectable } from "tsyringe"; @injectable() -export class PaymentService -{ +export class PaymentService { constructor( @inject("PrimaryLogger") protected logger: ILogger, @inject("HashUtil") protected hashUtil: HashUtil, @@ -31,8 +30,7 @@ export class PaymentService @inject("InventoryHelper") protected inventoryHelper: InventoryHelper, @inject("LocalisationService") protected localisationService: LocalisationService, @inject("PaymentHelper") protected paymentHelper: PaymentHelper, - ) - {} + ) {} /** * Take money and insert items into return to server request @@ -46,8 +44,7 @@ export class PaymentService request: IProcessBuyTradeRequestData, sessionID: string, output: IItemEventRouterResponse, - ): void - { + ): void { // May need to convert to trader currency const trader = this.traderHelper.getTrader(request.tid, sessionID); @@ -55,14 +52,11 @@ export class PaymentService const currencyAmounts: { [key: string]: number } = {}; // Delete barter items and track currencies - for (const index in request.scheme_items) - { + for (const index in request.scheme_items) { // Find the corresponding item in the player's inventory. const item = pmcData.Inventory.items.find((i) => i._id === request.scheme_items[index].id); - if (item !== undefined) - { - if (!this.paymentHelper.isMoneyTpl(item._tpl)) - { + if (item !== undefined) { + if (!this.paymentHelper.isMoneyTpl(item._tpl)) { // If the item is not money, remove it from the inventory. this.inventoryHelper.removeItemByCount( pmcData, @@ -72,15 +66,11 @@ export class PaymentService output, ); request.scheme_items[index].count = 0; - } - else - { + } else { // If the item is money, add its count to the currencyAmounts object. currencyAmounts[item._tpl] = (currencyAmounts[item._tpl] || 0) + request.scheme_items[index].count; } - } - else - { + } else { // Used by `SptInsure` // Handle differently, `id` is the money type tpl const currencyTpl = request.scheme_items[index].id; @@ -92,19 +82,16 @@ export class PaymentService let totalCurrencyAmount = 0; // Loop through each type of currency involved in the trade. - for (const currencyTpl in currencyAmounts) - { + for (const currencyTpl in currencyAmounts) { const currencyAmount = currencyAmounts[currencyTpl]; totalCurrencyAmount += currencyAmount; - if (currencyAmount > 0) - { + if (currencyAmount > 0) { // Find money stacks in inventory and remove amount needed + update output object to inform client of changes this.addPaymentToOutput(pmcData, currencyTpl, currencyAmount, sessionID, output); // If there are warnings, exit early. - if (output.warnings.length > 0) - { + if (output.warnings.length > 0) { return; } @@ -118,8 +105,7 @@ export class PaymentService } // If no currency-based payment is involved, handle it separately - if (totalCurrencyAmount === 0) - { + if (totalCurrencyAmount === 0) { this.logger.debug(this.localisationService.getText("payment-zero_price_no_payment")); // Convert the handbook price to the trader's currency and update the sales sum. @@ -141,17 +127,14 @@ export class PaymentService * @param traderId Id of trader with assort * @returns Handbook rouble price of item */ - protected getTraderItemHandbookPriceRouble(traderAssortId: string, traderId: string): number - { + protected getTraderItemHandbookPriceRouble(traderAssortId: string, traderId: string): number { const purchasedAssortItem = this.traderHelper.getTraderAssortItemByAssortId(traderId, traderAssortId); - if (!purchasedAssortItem) - { + if (!purchasedAssortItem) { return 1; } const assortItemPriceRouble = this.handbookHelper.getTemplatePrice(purchasedAssortItem._tpl); - if (!assortItemPriceRouble) - { + if (!assortItemPriceRouble) { this.logger.debug( `No item price found for ${purchasedAssortItem._tpl} on trader: ${traderId} in assort: ${traderAssortId}`, ); @@ -177,11 +160,9 @@ export class PaymentService request: IProcessSellTradeRequestData, output: IItemEventRouterResponse, sessionID: string, - ): void - { + ): void { const trader = this.traderHelper.getTrader(request.tid, sessionID); - if (!trader) - { + if (!trader) { this.logger.error(`Unable to add currency to profile as trader: ${request.tid} does not exist`); return; @@ -190,39 +171,31 @@ export class PaymentService const currencyTpl = this.paymentHelper.getCurrency(trader.currency); let calcAmount = this.handbookHelper.fromRUB(this.handbookHelper.inRUB(amountToSend, currencyTpl), currencyTpl); const currencyMaxStackSize = this.itemHelper.getItem(currencyTpl)[1]._props?.StackMaxSize; - if (!currencyMaxStackSize) - { + if (!currencyMaxStackSize) { this.logger.error(`Unable to add currency: ${currencyTpl} to profile as it lacks a _props property`); return; } let skipSendingMoneyToStash = false; - for (const item of pmcData.Inventory.items) - { + for (const item of pmcData.Inventory.items) { // Item is not currency - if (item._tpl !== currencyTpl) - { + if (item._tpl !== currencyTpl) { continue; } // Item is not in the stash - if (!this.inventoryHelper.isItemInStash(pmcData, item)) - { + if (!this.inventoryHelper.isItemInStash(pmcData, item)) { continue; } // Found currency item - if (item.upd!.StackObjectsCount! < currencyMaxStackSize) - { - if (item.upd!.StackObjectsCount! + calcAmount > currencyMaxStackSize) - { + if (item.upd!.StackObjectsCount! < currencyMaxStackSize) { + if (item.upd!.StackObjectsCount! + calcAmount > currencyMaxStackSize) { // calculate difference calcAmount -= currencyMaxStackSize - item.upd!.StackObjectsCount!; item.upd!.StackObjectsCount! = currencyMaxStackSize; - } - else - { + } else { skipSendingMoneyToStash = true; item.upd!.StackObjectsCount! = item.upd!.StackObjectsCount! + calcAmount; } @@ -230,8 +203,7 @@ export class PaymentService // Inform client of change to items StackObjectsCount output.profileChanges[sessionID].items.change.push(item); - if (skipSendingMoneyToStash) - { + if (skipSendingMoneyToStash) { break; } } @@ -247,8 +219,7 @@ export class PaymentService // Ensure money is properly split to follow its max stack size limit const rewards = this.itemHelper.splitStackIntoSeparateItems(rootCurrencyReward); - if (!skipSendingMoneyToStash) - { + if (!skipSendingMoneyToStash) { const addItemToStashRequest: IAddItemsDirectRequest = { itemsWithModsToAdd: rewards, foundInRaid: false, @@ -279,8 +250,7 @@ export class PaymentService amountToPay: number, sessionID: string, output: IItemEventRouterResponse, - ): void - { + ): void { const moneyItemsInInventory = this.getSortedMoneyItemsInInventory( pmcData, currencyTpl, @@ -292,8 +262,7 @@ export class PaymentService ); // If no money in inventory or amount is not enough we return false - if (moneyItemsInInventory.length <= 0 || amountAvailable < amountToPay) - { + if (moneyItemsInInventory.length <= 0 || amountAvailable < amountToPay) { this.logger.error( this.localisationService.getText("payment-not_enough_money_to_complete_transation", { amountToPay: amountToPay, @@ -310,23 +279,18 @@ export class PaymentService } let leftToPay = amountToPay; - for (const profileMoneyItem of moneyItemsInInventory) - { + for (const profileMoneyItem of moneyItemsInInventory) { const itemAmount = profileMoneyItem.upd!.StackObjectsCount!; - if (leftToPay >= itemAmount) - { + if (leftToPay >= itemAmount) { leftToPay -= itemAmount; this.inventoryHelper.removeItem(pmcData, profileMoneyItem._id, sessionID, output); - } - else - { + } else { profileMoneyItem.upd!.StackObjectsCount! -= leftToPay; leftToPay = 0; output.profileChanges[sessionID].items.change.push(profileMoneyItem); } - if (leftToPay === 0) - { + if (leftToPay === 0) { break; } } @@ -339,11 +303,9 @@ export class PaymentService * @param playerStashId Players stash id * @returns Sorting money items */ - protected getSortedMoneyItemsInInventory(pmcData: IPmcData, currencyTpl: string, playerStashId: string): Item[] - { + protected getSortedMoneyItemsInInventory(pmcData: IPmcData, currencyTpl: string, playerStashId: string): Item[] { const moneyItemsInInventory = this.itemHelper.findBarterItems("tpl", pmcData.Inventory.items, currencyTpl); - if (moneyItemsInInventory?.length === 0) - { + if (moneyItemsInInventory?.length === 0) { this.logger.debug(`No ${currencyTpl} money items found in inventory`); } @@ -362,36 +324,30 @@ export class PaymentService * @param playerStashId Players stash id * @returns sort order */ - protected prioritiseStashSort(a: Item, b: Item, inventoryItems: Item[], playerStashId: string): number - { + protected prioritiseStashSort(a: Item, b: Item, inventoryItems: Item[], playerStashId: string): number { // a in stash, prioritise - if (a.slotId === "hideout" && b.slotId !== "hideout") - { + if (a.slotId === "hideout" && b.slotId !== "hideout") { return -1; } // b in stash, prioritise - if (a.slotId !== "hideout" && b.slotId === "hideout") - { + if (a.slotId !== "hideout" && b.slotId === "hideout") { return 1; } // both in containers - if (a.slotId === "main" && b.slotId === "main") - { + if (a.slotId === "main" && b.slotId === "main") { // Item is in inventory, not stash, deprioritise const aInStash = this.isInStash(a.parentId, inventoryItems, playerStashId); const bInStash = this.isInStash(b.parentId, inventoryItems, playerStashId); // a in stash, prioritise - if (aInStash && !bInStash) - { + if (aInStash && !bInStash) { return -1; } // b in stash, prioritise - if (!aInStash && bInStash) - { + if (!aInStash && bInStash) { return 1; } } @@ -407,19 +363,15 @@ export class PaymentService * @param playerStashId Players stash id * @returns true if its in inventory */ - protected isInStash(itemId: string | undefined, inventoryItems: Item[], playerStashId: string): boolean - { + protected isInStash(itemId: string | undefined, inventoryItems: Item[], playerStashId: string): boolean { const itemParent = inventoryItems.find((x) => x._id === itemId); - if (itemParent) - { - if (itemParent.slotId === "hideout") - { + if (itemParent) { + if (itemParent.slotId === "hideout") { return true; } - if (itemParent._id === playerStashId) - { + if (itemParent._id === playerStashId) { return true; } diff --git a/project/src/services/PlayerService.ts b/project/src/services/PlayerService.ts index bed56a65..e44f886b 100644 --- a/project/src/services/PlayerService.ts +++ b/project/src/services/PlayerService.ts @@ -1,36 +1,31 @@ -import { inject, injectable } from "tsyringe"; import { IPmcData } from "@spt/models/eft/common/IPmcData"; import { ILogger } from "@spt/models/spt/utils/ILogger"; import { DatabaseService } from "@spt/services/DatabaseService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { TimeUtil } from "@spt/utils/TimeUtil"; +import { inject, injectable } from "tsyringe"; @injectable() -export class PlayerService -{ +export class PlayerService { constructor( @inject("PrimaryLogger") protected logger: ILogger, @inject("TimeUtil") protected timeUtil: TimeUtil, @inject("LocalisationService") protected localisationService: LocalisationService, @inject("DatabaseService") protected databaseService: DatabaseService, - ) - {} + ) {} /** * Get level of player * @param pmcData Player profile * @returns Level of player */ - public calculateLevel(pmcData: IPmcData): number - { + public calculateLevel(pmcData: IPmcData): number { let accExp = 0; - for (const [level, { exp }] of this.databaseService.getGlobals().config.exp.level.exp_table.entries()) - { + for (const [level, { exp }] of this.databaseService.getGlobals().config.exp.level.exp_table.entries()) { accExp += exp; - if (pmcData.Info.Experience < accExp) - { + if (pmcData.Info.Experience < accExp) { break; } diff --git a/project/src/services/PmcChatResponseService.ts b/project/src/services/PmcChatResponseService.ts index 03f4202d..4314577f 100644 --- a/project/src/services/PmcChatResponseService.ts +++ b/project/src/services/PmcChatResponseService.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { NotificationSendHelper } from "@spt/helpers/NotificationSendHelper"; import { WeightedRandomHelper } from "@spt/helpers/WeightedRandomHelper"; import { IPmcData } from "@spt/models/eft/common/IPmcData"; @@ -16,10 +15,10 @@ import { LocalisationService } from "@spt/services/LocalisationService"; import { MatchBotDetailsCacheService } from "@spt/services/MatchBotDetailsCacheService"; import { HashUtil } from "@spt/utils/HashUtil"; import { RandomUtil } from "@spt/utils/RandomUtil"; +import { inject, injectable } from "tsyringe"; @injectable() -export class PmcChatResponseService -{ +export class PmcChatResponseService { protected pmcResponsesConfig: IPmcChatResponse; protected giftConfig: IGiftsConfig; @@ -33,8 +32,7 @@ export class PmcChatResponseService @inject("GiftService") protected giftService: GiftService, @inject("WeightedRandomHelper") protected weightedRandomHelper: WeightedRandomHelper, @inject("ConfigServer") protected configServer: ConfigServer, - ) - { + ) { this.pmcResponsesConfig = this.configServer.getConfig(ConfigTypes.PMC_CHAT_RESPONSE); this.giftConfig = this.configServer.getConfig(ConfigTypes.GIFTS); } @@ -45,19 +43,15 @@ export class PmcChatResponseService * @param pmcVictims Array of bots killed by player * @param pmcData Player profile */ - public sendVictimResponse(sessionId: string, pmcVictims: Victim[], pmcData: IPmcData): void - { - for (const victim of pmcVictims) - { - if (!this.randomUtil.getChance100(this.pmcResponsesConfig.victim.responseChancePercent)) - { + public sendVictimResponse(sessionId: string, pmcVictims: Victim[], pmcData: IPmcData): void { + for (const victim of pmcVictims) { + if (!this.randomUtil.getChance100(this.pmcResponsesConfig.victim.responseChancePercent)) { continue; } const victimDetails = this.getVictimDetails(victim); const message = this.chooseMessage(true, pmcData); - if (message) - { + if (message) { this.notificationSendHelper.sendMessageToPlayer( sessionId, victimDetails, @@ -74,28 +68,23 @@ export class PmcChatResponseService * @param pmcData Players profile * @param killer The bot who killed the player */ - public sendKillerResponse(sessionId: string, pmcData: IPmcData, killer: Aggressor): void - { - if (!killer) - { + public sendKillerResponse(sessionId: string, pmcData: IPmcData, killer: Aggressor): void { + if (!killer) { return; } - if (!this.randomUtil.getChance100(this.pmcResponsesConfig.killer.responseChancePercent)) - { + if (!this.randomUtil.getChance100(this.pmcResponsesConfig.killer.responseChancePercent)) { return; } // find bot by name in cache const killerDetailsInCache = this.matchBotDetailsCacheService.getBotByNameAndSide(killer.Name, killer.Side); - if (!killerDetailsInCache) - { + if (!killerDetailsInCache) { return; } // If kill was not a PMC, skip - if (!["pmcUSEC", "pmcBEAR"].includes(killerDetailsInCache.Info.Settings.Role)) - { + if (!["pmcUSEC", "pmcBEAR"].includes(killerDetailsInCache.Info.Settings.Role)) { return; } @@ -112,8 +101,7 @@ export class PmcChatResponseService }; const message = this.chooseMessage(false, pmcData); - if (!message) - { + if (!message) { return; } @@ -126,15 +114,13 @@ export class PmcChatResponseService * @param pmcData Player profile * @returns Message from PMC to player */ - protected chooseMessage(isVictim: boolean, pmcData: IPmcData): string | undefined - { + protected chooseMessage(isVictim: boolean, pmcData: IPmcData): string | undefined { // Positive/negative etc const responseType = this.chooseResponseType(isVictim); // Get all locale keys const possibleResponseLocaleKeys = this.getResponseLocaleKeys(responseType, isVictim); - if (possibleResponseLocaleKeys.length === 0) - { + if (possibleResponseLocaleKeys.length === 0) { this.logger.warning(this.localisationService.getText("pmcresponse-unable_to_find_key", responseType)); return undefined; @@ -148,8 +134,7 @@ export class PmcChatResponseService }); // Give the player a gift code if they were killed adn response is 'pity'. - if (responseType === "pity") - { + if (responseType === "pity") { const giftKeys = this.giftService.getGiftIds(); const randomGiftKey = this.randomUtil.getStringArrayValue(giftKeys); @@ -157,21 +142,18 @@ export class PmcChatResponseService responseText = responseText.replace(regex, randomGiftKey); } - if (this.appendSuffixToMessageEnd(isVictim)) - { + if (this.appendSuffixToMessageEnd(isVictim)) { const suffixText = this.localisationService.getText( this.randomUtil.getArrayValue(this.getResponseSuffixLocaleKeys()), ); responseText += ` ${suffixText}`; } - if (this.stripCapitalistion(isVictim)) - { + if (this.stripCapitalistion(isVictim)) { responseText = responseText.toLowerCase(); } - if (this.allCaps(isVictim)) - { + if (this.allCaps(isVictim)) { responseText = responseText.toUpperCase(); } @@ -183,8 +165,7 @@ export class PmcChatResponseService * @param isVictim Was responder a victim of player * @returns true = should be stripped */ - protected stripCapitalistion(isVictim: boolean): boolean - { + protected stripCapitalistion(isVictim: boolean): boolean { const chance = isVictim ? this.pmcResponsesConfig.victim.stripCapitalisationChancePercent : this.pmcResponsesConfig.killer.stripCapitalisationChancePercent; @@ -197,8 +178,7 @@ export class PmcChatResponseService * @param isVictim Was responder a victim of player * @returns true = should be stripped */ - protected allCaps(isVictim: boolean): boolean - { + protected allCaps(isVictim: boolean): boolean { const chance = isVictim ? this.pmcResponsesConfig.victim.allCapsChancePercent : this.pmcResponsesConfig.killer.allCapsChancePercent; @@ -211,8 +191,7 @@ export class PmcChatResponseService * @param isVictim Was responder a victim of player * @returns true = should be stripped */ - appendSuffixToMessageEnd(isVictim: boolean): boolean - { + appendSuffixToMessageEnd(isVictim: boolean): boolean { const chance = isVictim ? this.pmcResponsesConfig.victim.appendBroToMessageEndChancePercent : this.pmcResponsesConfig.killer.appendBroToMessageEndChancePercent; @@ -225,8 +204,7 @@ export class PmcChatResponseService * @param isVictim Was responder killed by player * @returns Response type (positive/negative) */ - protected chooseResponseType(isVictim = true): string - { + protected chooseResponseType(isVictim = true): string { const responseWeights = isVictim ? this.pmcResponsesConfig.victim.responseTypeWeights : this.pmcResponsesConfig.killer.responseTypeWeights; @@ -240,8 +218,7 @@ export class PmcChatResponseService * @param isVictim Was responder killed by player * @returns */ - protected getResponseLocaleKeys(keyType: string, isVictim = true): string[] - { + protected getResponseLocaleKeys(keyType: string, isVictim = true): string[] { const keyBase = isVictim ? "pmcresponse-victim_" : "pmcresponse-killer_"; const keys = this.localisationService.getKeys(); @@ -252,8 +229,7 @@ export class PmcChatResponseService * Get all locale keys that start with `pmcresponse-suffix` * @returns array of keys */ - protected getResponseSuffixLocaleKeys(): string[] - { + protected getResponseSuffixLocaleKeys(): string[] { const keys = this.localisationService.getKeys(); return keys.filter((x) => x.startsWith("pmcresponse-suffix")); @@ -264,8 +240,7 @@ export class PmcChatResponseService * @param pmcVictims Possible victims to choose from * @returns IUserDialogInfo */ - protected chooseRandomVictim(pmcVictims: Victim[]): IUserDialogInfo - { + protected chooseRandomVictim(pmcVictims: Victim[]): IUserDialogInfo { const randomVictim = this.randomUtil.getArrayValue(pmcVictims); return this.getVictimDetails(randomVictim); @@ -276,8 +251,7 @@ export class PmcChatResponseService * @param pmcVictim victim to convert * @returns IUserDialogInfo */ - protected getVictimDetails(pmcVictim: Victim): IUserDialogInfo - { + protected getVictimDetails(pmcVictim: Victim): IUserDialogInfo { const categories = [ MemberCategory.UNIQUE_ID, MemberCategory.DEFAULT, diff --git a/project/src/services/ProfileActivityService.ts b/project/src/services/ProfileActivityService.ts index 1d939dda..98ca1b54 100644 --- a/project/src/services/ProfileActivityService.ts +++ b/project/src/services/ProfileActivityService.ts @@ -1,8 +1,7 @@ import { injectable } from "tsyringe"; @injectable() -export class ProfileActivityService -{ +export class ProfileActivityService { protected profileActivityTimestamps: Record = {}; /** @@ -11,12 +10,10 @@ export class ProfileActivityService * @param minutes Minutes to check for activity in * @returns True when profile was active within past x minutes */ - public activeWithinLastMinutes(sessionId: string, minutes: number): boolean - { + public activeWithinLastMinutes(sessionId: string, minutes: number): boolean { const currentTimestamp = new Date().getTime() / 1000; const storedActivityTimestamp = this.profileActivityTimestamps[sessionId]; - if (!storedActivityTimestamp) - { + if (!storedActivityTimestamp) { // No value, no assumed activity (server offline?) return false; } @@ -30,22 +27,18 @@ export class ProfileActivityService * @param minutes How many minutes from now to search for profiles * @returns String array of profile ids */ - public getActiveProfileIdsWithinMinutes(minutes: number): string[] - { + public getActiveProfileIdsWithinMinutes(minutes: number): string[] { const currentTimestamp = new Date().getTime() / 1000; const result: string[] = []; - for (const id of Object.keys(this.profileActivityTimestamps ?? {})) - { + for (const id of Object.keys(this.profileActivityTimestamps ?? {})) { const lastActiveTimestamp = this.profileActivityTimestamps[id]; - if (!lastActiveTimestamp) - { + if (!lastActiveTimestamp) { continue; } // Profile was active in last x minutes, add to return list - if (currentTimestamp - lastActiveTimestamp < minutes * 60) - { + if (currentTimestamp - lastActiveTimestamp < minutes * 60) { result.push(id); } } @@ -57,8 +50,7 @@ export class ProfileActivityService * Update the timestamp a profile was last observed active * @param sessionId Profile to update */ - public setActivityTimestamp(sessionId: string): void - { + public setActivityTimestamp(sessionId: string): void { this.profileActivityTimestamps[sessionId] = new Date().getTime() / 1000; } } diff --git a/project/src/services/ProfileFixerService.ts b/project/src/services/ProfileFixerService.ts index 20d1fe2d..315ad33a 100644 --- a/project/src/services/ProfileFixerService.ts +++ b/project/src/services/ProfileFixerService.ts @@ -1,15 +1,14 @@ -import { inject, injectable } from "tsyringe"; import { HideoutHelper } from "@spt/helpers/HideoutHelper"; import { InventoryHelper } from "@spt/helpers/InventoryHelper"; import { ItemHelper } from "@spt/helpers/ItemHelper"; import { ProfileHelper } from "@spt/helpers/ProfileHelper"; import { TraderHelper } from "@spt/helpers/TraderHelper"; import { IPmcData } from "@spt/models/eft/common/IPmcData"; -import { Bonus, HideoutSlot, IQuestStatus, IHideoutImprovement } from "@spt/models/eft/common/tables/IBotBase"; +import { Bonus, HideoutSlot, IHideoutImprovement, IQuestStatus } from "@spt/models/eft/common/tables/IBotBase"; import { IPmcDataRepeatableQuest, IRepeatableQuest } from "@spt/models/eft/common/tables/IRepeatableQuests"; import { ITemplateItem } from "@spt/models/eft/common/tables/ITemplateItem"; import { StageBonus } from "@spt/models/eft/hideout/IHideoutArea"; -import { ISptProfile, IEquipmentBuild, IMagazineBuild, IWeaponBuild } from "@spt/models/eft/profile/ISptProfile"; +import { IEquipmentBuild, IMagazineBuild, ISptProfile, IWeaponBuild } from "@spt/models/eft/profile/ISptProfile"; import { BonusType } from "@spt/models/enums/BonusType"; import { ConfigTypes } from "@spt/models/enums/ConfigTypes"; import { HideoutAreas } from "@spt/models/enums/HideoutAreas"; @@ -21,15 +20,15 @@ import { ILogger } from "@spt/models/spt/utils/ILogger"; import { ConfigServer } from "@spt/servers/ConfigServer"; 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 { JsonUtil } from "@spt/utils/JsonUtil"; import { TimeUtil } from "@spt/utils/TimeUtil"; import { Watermark } from "@spt/utils/Watermark"; +import { ICloner } from "@spt/utils/cloners/ICloner"; +import { inject, injectable } from "tsyringe"; @injectable() -export class ProfileFixerService -{ +export class ProfileFixerService { protected coreConfig: ICoreConfig; protected ragfairConfig: IRagfairConfig; @@ -48,8 +47,7 @@ export class ProfileFixerService @inject("HashUtil") protected hashUtil: HashUtil, @inject("ConfigServer") protected configServer: ConfigServer, @inject("PrimaryCloner") protected cloner: ICloner, - ) - { + ) { this.coreConfig = this.configServer.getConfig(ConfigTypes.CORE); this.ragfairConfig = this.configServer.getConfig(ConfigTypes.RAGFAIR); } @@ -58,8 +56,7 @@ export class ProfileFixerService * Find issues in the pmc profile data that may cause issues and fix them * @param pmcProfile profile to check and fix */ - public checkForAndFixPmcProfileIssues(pmcProfile: IPmcData): void - { + public checkForAndFixPmcProfileIssues(pmcProfile: IPmcData): void { this.removeDanglingConditionCounters(pmcProfile); this.removeDanglingTaskConditionCounters(pmcProfile); this.addMissingRepeatableQuestsProperty(pmcProfile); @@ -67,13 +64,11 @@ export class ProfileFixerService this.addUnlockedInfoObjectIfMissing(pmcProfile); this.removeOrphanedQuests(pmcProfile); - if (pmcProfile.Inventory) - { + if (pmcProfile.Inventory) { this.addHideoutAreaStashes(pmcProfile); } - if (pmcProfile.Hideout) - { + if (pmcProfile.Hideout) { const globals = this.databaseService.getGlobals(); this.migrateImprovements(pmcProfile); @@ -88,77 +83,57 @@ export class ProfileFixerService this.reorderHideoutAreasWithResouceInputs(pmcProfile); - if (pmcProfile.Hideout.Areas.find((x) => x.type === HideoutAreas.GENERATOR)!.slots.length - < 6 - + globals.config.SkillsSettings.HideoutManagement.EliteSlots.Generator - .Slots - ) - { + if ( + pmcProfile.Hideout.Areas.find((x) => x.type === HideoutAreas.GENERATOR)!.slots.length < + 6 + globals.config.SkillsSettings.HideoutManagement.EliteSlots.Generator.Slots + ) { this.logger.debug("Updating generator area slots to a size of 6 + hideout management skill"); this.addEmptyObjectsToHideoutAreaSlots( HideoutAreas.GENERATOR, - 6 - + globals.config.SkillsSettings.HideoutManagement.EliteSlots - .Generator.Slots, + 6 + globals.config.SkillsSettings.HideoutManagement.EliteSlots.Generator.Slots, pmcProfile, ); } if ( - pmcProfile.Hideout.Areas.find((x) => x.type === HideoutAreas.WATER_COLLECTOR)!.slots.length - < 1 - + globals.config.SkillsSettings.HideoutManagement.EliteSlots - .WaterCollector.Slots - ) - { + pmcProfile.Hideout.Areas.find((x) => x.type === HideoutAreas.WATER_COLLECTOR)!.slots.length < + 1 + globals.config.SkillsSettings.HideoutManagement.EliteSlots.WaterCollector.Slots + ) { this.logger.debug("Updating water collector area slots to a size of 1 + hideout management skill"); this.addEmptyObjectsToHideoutAreaSlots( HideoutAreas.WATER_COLLECTOR, - 1 - + globals.config.SkillsSettings.HideoutManagement.EliteSlots - .WaterCollector.Slots, + 1 + globals.config.SkillsSettings.HideoutManagement.EliteSlots.WaterCollector.Slots, pmcProfile, ); } if ( - pmcProfile.Hideout.Areas.find((x) => x.type === HideoutAreas.AIR_FILTERING)!.slots.length - < 3 - + globals.config.SkillsSettings.HideoutManagement.EliteSlots - .AirFilteringUnit.Slots - ) - { + pmcProfile.Hideout.Areas.find((x) => x.type === HideoutAreas.AIR_FILTERING)!.slots.length < + 3 + globals.config.SkillsSettings.HideoutManagement.EliteSlots.AirFilteringUnit.Slots + ) { this.logger.debug("Updating air filter area slots to a size of 3 + hideout management skill"); this.addEmptyObjectsToHideoutAreaSlots( HideoutAreas.AIR_FILTERING, - 3 - + globals.config.SkillsSettings.HideoutManagement.EliteSlots - .AirFilteringUnit.Slots, + 3 + globals.config.SkillsSettings.HideoutManagement.EliteSlots.AirFilteringUnit.Slots, pmcProfile, ); } // BTC Farm doesnt have extra slots for hideout management, but we still check for modded stuff!! if ( - pmcProfile.Hideout.Areas.find((x) => x.type === HideoutAreas.BITCOIN_FARM)!.slots.length - < 50 - + globals.config.SkillsSettings.HideoutManagement.EliteSlots - .BitcoinFarm.Slots - ) - { + pmcProfile.Hideout.Areas.find((x) => x.type === HideoutAreas.BITCOIN_FARM)!.slots.length < + 50 + globals.config.SkillsSettings.HideoutManagement.EliteSlots.BitcoinFarm.Slots + ) { this.logger.debug("Updating bitcoin farm area slots to a size of 50 + hideout management skill"); this.addEmptyObjectsToHideoutAreaSlots( HideoutAreas.BITCOIN_FARM, - 50 - + globals.config.SkillsSettings.HideoutManagement.EliteSlots - .BitcoinFarm.Slots, + 50 + globals.config.SkillsSettings.HideoutManagement.EliteSlots.BitcoinFarm.Slots, pmcProfile, ); } } - if (pmcProfile.Skills) - { + if (pmcProfile.Skills) { this.checkForSkillsOverMaxLevel(pmcProfile); } @@ -171,33 +146,27 @@ export class ProfileFixerService * Find issues in the scav profile data that may cause issues * @param scavProfile profile to check and fix */ - public checkForAndFixScavProfileIssues(scavProfile: IPmcData): void - { + public checkForAndFixScavProfileIssues(scavProfile: IPmcData): void { this.updateProfileQuestDataValues(scavProfile); } /** - * Check for and cap profile skills at 5100. - * @param pmcProfile profile to check and fix - */ - protected checkForSkillsOverMaxLevel(pmcProfile: IPmcData): void - { + * Check for and cap profile skills at 5100. + * @param pmcProfile profile to check and fix + */ + protected checkForSkillsOverMaxLevel(pmcProfile: IPmcData): void { const skills = pmcProfile.Skills.Common; - for (let skill of skills) - { - if (skill.Progress > 5100) - { + for (const skill of skills) { + if (skill.Progress > 5100) { skill.Progress = 5100; } } } - protected addMissingGunStandContainerImprovements(pmcProfile: IPmcData): void - { + protected addMissingGunStandContainerImprovements(pmcProfile: IPmcData): void { const weaponStandArea = pmcProfile.Hideout.Areas.find((x) => x.type === HideoutAreas.WEAPON_STAND); - if (!weaponStandArea || weaponStandArea.level === 0) - { + if (!weaponStandArea || weaponStandArea.level === 0) { // No stand in profile or its level 0, skip return; } @@ -210,24 +179,20 @@ export class ProfileFixerService const hideoutSecondaryStashId = pmcProfile.Inventory.hideoutAreaStashes[HideoutAreas.WEAPON_STAND_SECONDARY]; // `hideoutAreaStashes` empty but profile has built gun stand - if (!hideoutStandStashId && stageCurrentAt) - { + if (!hideoutStandStashId && stageCurrentAt) { // Value is missing, add it pmcProfile.Inventory.hideoutAreaStashes[HideoutAreas.WEAPON_STAND] = hideoutStandAreaDb._id; - pmcProfile.Inventory.hideoutAreaStashes[HideoutAreas.WEAPON_STAND_SECONDARY] - = hideoutStandSecondaryAreaDb._id; + pmcProfile.Inventory.hideoutAreaStashes[HideoutAreas.WEAPON_STAND_SECONDARY] = + hideoutStandSecondaryAreaDb._id; // Add stash item to profile const gunStandStashItem = pmcProfile.Inventory.items.find((item) => item._id === hideoutStandAreaDb._id); - if (gunStandStashItem) - { + if (gunStandStashItem) { gunStandStashItem._tpl = stageCurrentAt.container!; this.logger.debug( `Updated existing gun stand inventory stash: ${gunStandStashItem._id} tpl to ${stageCurrentAt.container}`, ); - } - else - { + } else { pmcProfile.Inventory.items.push({ _id: hideoutStandAreaDb._id, _tpl: stageCurrentAt.container! }); this.logger.debug( `Added missing gun stand inventory stash: ${hideoutStandAreaDb._id} tpl to ${stageCurrentAt.container}`, @@ -238,15 +203,12 @@ export class ProfileFixerService const gunStandStashSecondaryItem = pmcProfile.Inventory.items.find( (item) => item._id === hideoutStandSecondaryAreaDb._id, )!; - if (gunStandStashItem) - { + if (gunStandStashItem) { gunStandStashSecondaryItem._tpl = stageCurrentAt.container!; this.logger.debug( `Updated gun stand existing inventory secondary stash: ${gunStandStashSecondaryItem._id} tpl to ${stageCurrentAt.container}`, ); - } - else - { + } else { pmcProfile.Inventory.items.push({ _id: hideoutStandSecondaryAreaDb._id, _tpl: stageCurrentAt.container!, @@ -260,16 +222,14 @@ export class ProfileFixerService } let stashItem = pmcProfile.Inventory.items?.find((x) => x._id === hideoutStandAreaDb._id); - if (!stashItem) - { + if (!stashItem) { // Stand inventory stash item doesnt exist, add it pmcProfile.Inventory.items.push({ _id: hideoutStandAreaDb._id, _tpl: stageCurrentAt.container! }); stashItem = pmcProfile.Inventory.items?.find((x) => x._id === hideoutStandAreaDb._id); } // `hideoutAreaStashes` has value related stash inventory items tpl doesnt match what's expected - if (hideoutStandStashId && stashItem!._tpl !== stageCurrentAt.container) - { + if (hideoutStandStashId && stashItem!._tpl !== stageCurrentAt.container) { this.logger.debug( `primary Stash tpl was: ${stashItem!._tpl}, but should be ${stageCurrentAt.container}, updating`, ); @@ -278,16 +238,14 @@ export class ProfileFixerService } let stashSecondaryItem = pmcProfile.Inventory.items?.find((x) => x._id === hideoutStandSecondaryAreaDb._id); - if (!stashSecondaryItem) - { + if (!stashSecondaryItem) { // Stand inventory stash item doesnt exist, add it pmcProfile.Inventory.items.push({ _id: hideoutStandSecondaryAreaDb._id, _tpl: stageCurrentAt.container! }); stashSecondaryItem = pmcProfile.Inventory.items?.find((x) => x._id === hideoutStandSecondaryAreaDb._id); } // `hideoutAreaStashes` has value related stash inventory items tpl doesnt match what's expected - if (hideoutSecondaryStashId && stashSecondaryItem?._tpl !== stageCurrentAt.container) - { + if (hideoutSecondaryStashId && stashSecondaryItem?._tpl !== stageCurrentAt.container) { this.logger.debug( `Secondary stash tpl was: ${stashSecondaryItem?._tpl}, but should be ${stageCurrentAt.container}, updating`, ); @@ -296,41 +254,35 @@ export class ProfileFixerService } } - protected addMissingHallOfFameContainerImprovements(pmcProfile: IPmcData): void - { + protected addMissingHallOfFameContainerImprovements(pmcProfile: IPmcData): void { const placeOfFameArea = pmcProfile.Hideout.Areas.find((x) => x.type === HideoutAreas.PLACE_OF_FAME); - if (!placeOfFameArea || placeOfFameArea.level === 0) - { + if (!placeOfFameArea || placeOfFameArea.level === 0) { // No place of fame in profile or its level 0, skip return; } - const placeOfFameAreaDb = this.databaseService.getHideout().areas - .find((area) => area.type === HideoutAreas.PLACE_OF_FAME); - if (!placeOfFameAreaDb) - { + const placeOfFameAreaDb = this.databaseService + .getHideout() + .areas.find((area) => area.type === HideoutAreas.PLACE_OF_FAME); + if (!placeOfFameAreaDb) { return; } const stageCurrentlyAt = placeOfFameAreaDb.stages[placeOfFameArea.level]; const placeOfFameStashId = pmcProfile.Inventory.hideoutAreaStashes[HideoutAreas.PLACE_OF_FAME]; // `hideoutAreaStashes` empty but profile has built gun stand - if (!placeOfFameStashId && stageCurrentlyAt) - { + if (!placeOfFameStashId && stageCurrentlyAt) { // Value is missing, add it pmcProfile.Inventory.hideoutAreaStashes[HideoutAreas.PLACE_OF_FAME] = placeOfFameAreaDb._id; // Add stash item to profile const placeOfFameStashItem = pmcProfile.Inventory.items.find((item) => item._id === placeOfFameAreaDb._id); - if (placeOfFameStashItem) - { + if (placeOfFameStashItem) { placeOfFameStashItem._tpl = stageCurrentlyAt.container!; this.logger.debug( `Updated existing place of fame inventory stash: ${placeOfFameStashItem._id} tpl to ${stageCurrentlyAt.container}`, ); - } - else - { + } else { pmcProfile.Inventory.items.push({ _id: placeOfFameAreaDb._id, _tpl: stageCurrentlyAt.container! }); this.logger.debug( `Added missing place of fame inventory stash: ${placeOfFameAreaDb._id} tpl to ${stageCurrentlyAt.container}`, @@ -341,16 +293,14 @@ export class ProfileFixerService } let stashItem = pmcProfile.Inventory.items?.find((x) => x._id === placeOfFameAreaDb._id); - if (!stashItem) - { + if (!stashItem) { // Stand inventory stash item doesnt exist, add it pmcProfile.Inventory.items.push({ _id: placeOfFameAreaDb._id, _tpl: stageCurrentlyAt.container! }); stashItem = pmcProfile.Inventory.items?.find((x) => x._id === placeOfFameAreaDb._id); } // `hideoutAreaStashes` has value related stash inventory items tpl doesnt match what's expected - if (placeOfFameStashId && stashItem!._tpl !== stageCurrentlyAt.container) - { + if (placeOfFameStashId && stashItem!._tpl !== stageCurrentlyAt.container) { this.logger.debug( `primary Stash tpl was: ${stashItem?._tpl}, but should be ${stageCurrentlyAt.container}, updating`, ); @@ -359,34 +309,27 @@ export class ProfileFixerService } } - protected ensureGunStandLevelsMatch(pmcProfile: IPmcData): void - { + protected ensureGunStandLevelsMatch(pmcProfile: IPmcData): void { // only proceed if stand is level 1 or above const gunStandParent = pmcProfile.Hideout.Areas.find((x) => x.type === HideoutAreas.WEAPON_STAND); - if (gunStandParent && gunStandParent.level > 0) - { + if (gunStandParent && gunStandParent.level > 0) { const gunStandChild = pmcProfile.Hideout.Areas.find((x) => x.type === HideoutAreas.WEAPON_STAND_SECONDARY); - if (gunStandChild && gunStandParent.level !== gunStandChild.level) - { + if (gunStandChild && gunStandParent.level !== gunStandChild.level) { this.logger.success("Upgraded gun stand levels to match"); gunStandChild.level = gunStandParent.level; } } } - protected addHideoutAreaStashes(pmcProfile: IPmcData): void - { - if (!pmcProfile?.Inventory?.hideoutAreaStashes) - { + protected addHideoutAreaStashes(pmcProfile: IPmcData): void { + if (!pmcProfile?.Inventory?.hideoutAreaStashes) { this.logger.debug("Added missing hideoutAreaStashes to inventory"); pmcProfile.Inventory.hideoutAreaStashes = {}; } } - protected addMissingHideoutWallAreas(pmcProfile: IPmcData): void - { - if (!pmcProfile.Hideout.Areas.some((x) => x.type === HideoutAreas.WEAPON_STAND)) - { + protected addMissingHideoutWallAreas(pmcProfile: IPmcData): void { + if (!pmcProfile.Hideout.Areas.some((x) => x.type === HideoutAreas.WEAPON_STAND)) { pmcProfile.Hideout.Areas.push({ type: 24, level: 0, @@ -399,8 +342,7 @@ export class ProfileFixerService }); } - if (!pmcProfile.Hideout.Areas.some((x) => x.type === HideoutAreas.WEAPON_STAND_SECONDARY)) - { + if (!pmcProfile.Hideout.Areas.some((x) => x.type === HideoutAreas.WEAPON_STAND_SECONDARY)) { pmcProfile.Hideout.Areas.push({ type: 25, level: 0, @@ -418,10 +360,8 @@ export class ProfileFixerService * Add tag to profile to indicate when it was made * @param fullProfile */ - public addMissingSptVersionTagToProfile(fullProfile: ISptProfile): void - { - if (!fullProfile.spt) - { + public addMissingSptVersionTagToProfile(fullProfile: ISptProfile): void { + if (!fullProfile.spt) { this.logger.debug("Adding spt object to profile"); fullProfile.spt = { version: this.watermark.getVersionTag(), @@ -436,31 +376,24 @@ export class ProfileFixerService * Remove unused condition counters * @param pmcProfile profile to remove old counters from */ - public removeDanglingConditionCounters(pmcProfile: IPmcData): void - { - if (pmcProfile.TaskConditionCounters) - { - for (const counterId in pmcProfile.TaskConditionCounters) - { + public removeDanglingConditionCounters(pmcProfile: IPmcData): void { + if (pmcProfile.TaskConditionCounters) { + for (const counterId in pmcProfile.TaskConditionCounters) { const counter = pmcProfile.TaskConditionCounters[counterId]; - if (!counter.sourceId) - { + if (!counter.sourceId) { delete pmcProfile.TaskConditionCounters[counterId]; } } } } - public addLighthouseKeeperIfMissing(pmcProfile: IPmcData): void - { - if (!pmcProfile.TradersInfo) - { + public addLighthouseKeeperIfMissing(pmcProfile: IPmcData): void { + if (!pmcProfile.TradersInfo) { return; } // only add if other traders exist, means this is pre-patch 13 profile - if (!pmcProfile.TradersInfo[Traders.LIGHTHOUSEKEEPER] && Object.keys(pmcProfile.TradersInfo).length > 0) - { + if (!pmcProfile.TradersInfo[Traders.LIGHTHOUSEKEEPER] && Object.keys(pmcProfile.TradersInfo).length > 0) { this.logger.warning("Added missing Lighthouse keeper trader to pmc profile"); pmcProfile.TradersInfo[Traders.LIGHTHOUSEKEEPER] = { unlocked: false, @@ -473,10 +406,8 @@ export class ProfileFixerService } } - protected addUnlockedInfoObjectIfMissing(pmcProfile: IPmcData): void - { - if (!pmcProfile.UnlockedInfo) - { + protected addUnlockedInfoObjectIfMissing(pmcProfile: IPmcData): void { + if (!pmcProfile.UnlockedInfo) { this.logger.debug("Adding UnlockedInfo object to profile"); pmcProfile.UnlockedInfo = { unlockedProductionRecipe: [] }; } @@ -486,20 +417,16 @@ export class ProfileFixerService * Repeatable quests leave behind TaskConditionCounter objects that make the profile bloat with time, remove them * @param pmcProfile Player profile to check */ - protected removeDanglingTaskConditionCounters(pmcProfile: IPmcData): void - { - if (pmcProfile.TaskConditionCounters) - { + protected removeDanglingTaskConditionCounters(pmcProfile: IPmcData): void { + if (pmcProfile.TaskConditionCounters) { const taskConditionKeysToRemove: string[] = []; const activeRepeatableQuests = this.getActiveRepeatableQuests(pmcProfile.RepeatableQuests); const achievements = this.databaseService.getAchievements(); // Loop over TaskConditionCounters objects and add once we want to remove to counterKeysToRemove - for (const [key, taskConditionCounter] of Object.entries(pmcProfile.TaskConditionCounters)) - { + for (const [key, taskConditionCounter] of Object.entries(pmcProfile.TaskConditionCounters)) { // Only check if profile has repeatable quests - if (pmcProfile.RepeatableQuests && activeRepeatableQuests.length > 0) - { + if (pmcProfile.RepeatableQuests && activeRepeatableQuests.length > 0) { const existsInActiveRepeatableQuests = activeRepeatableQuests.some( (quest) => quest._id === taskConditionCounter.sourceId, ); @@ -511,28 +438,23 @@ export class ProfileFixerService ); // If task conditions id is neither in activeQuests, quests or achievements - it's stale and should be cleaned up - if (!(existsInActiveRepeatableQuests || existsInQuests || isAchievementTracker)) - { + if (!(existsInActiveRepeatableQuests || existsInQuests || isAchievementTracker)) { taskConditionKeysToRemove.push(key); } } } - for (const counterKeyToRemove of taskConditionKeysToRemove) - { + for (const counterKeyToRemove of taskConditionKeysToRemove) { this.logger.debug(`Removed ${counterKeyToRemove} TaskConditionCounter object`); delete pmcProfile.TaskConditionCounters[counterKeyToRemove]; } } } - protected getActiveRepeatableQuests(repeatableQuests: IPmcDataRepeatableQuest[]): IRepeatableQuest[] - { + protected getActiveRepeatableQuests(repeatableQuests: IPmcDataRepeatableQuest[]): IRepeatableQuest[] { let activeQuests: IRepeatableQuest[] = []; - for (const repeatableQuest of repeatableQuests) - { - if (repeatableQuest.activeQuests.length > 0) - { + for (const repeatableQuest of repeatableQuests) { + if (repeatableQuest.activeQuests.length > 0) { // daily/weekly collection has active quests in them, add to array and return activeQuests = activeQuests.concat(repeatableQuest.activeQuests); } @@ -541,23 +463,18 @@ export class ProfileFixerService return activeQuests; } - protected fixNullTraderSalesSums(pmcProfile: IPmcData): void - { - for (const traderId in pmcProfile.TradersInfo) - { + protected fixNullTraderSalesSums(pmcProfile: IPmcData): void { + for (const traderId in pmcProfile.TradersInfo) { const trader = pmcProfile.TradersInfo[traderId]; - if (trader?.salesSum === undefined) - { + if (trader?.salesSum === undefined) { this.logger.warning(`trader ${traderId} has a undefined salesSum value, resetting to 0`); trader.salesSum = 0; } } } - protected addMissingBonusesProperty(pmcProfile: IPmcData): void - { - if (typeof pmcProfile.Bonuses === "undefined") - { + protected addMissingBonusesProperty(pmcProfile: IPmcData): void { + if (typeof pmcProfile.Bonuses === "undefined") { pmcProfile.Bonuses = []; this.logger.debug("Missing Bonuses property added to profile"); } @@ -569,10 +486,8 @@ export class ProfileFixerService * quest.statusTimers keys are numeric as strings e.g. "2" * @param profile profile to update */ - protected updateProfileQuestDataValues(profile: IPmcData): void - { - if (!profile.Quests) - { + protected updateProfileQuestDataValues(profile: IPmcData): void { + if (!profile.Quests) { return; } @@ -581,29 +496,24 @@ export class ProfileFixerService const questsToDelete: IQuestStatus[] = []; const fullProfile = this.profileHelper.getFullProfile(profile.sessionId); const isDevProfile = fullProfile?.info.edition.toLowerCase() === "spt developer"; - for (const quest of profile.Quests) - { + for (const quest of profile.Quests) { // Old profiles had quests with a bad status of 0 (invalid) added to profile, remove them // E.g. compensation for damage showing before standing check was added to getClientQuests() - if (quest.status === 0 && quest.availableAfter === 0 && !isDevProfile) - { + if (quest.status === 0 && quest.availableAfter === 0 && !isDevProfile) { questsToDelete.push(quest); continue; } - if (quest.status && Number.isNaN(Number.parseInt((quest.status)))) - { + if (quest.status && Number.isNaN(Number.parseInt((quest.status)))) { fixes[quest.status] = (fixes[quest.status] ?? 0) + 1; const newQuestStatus = QuestStatus[quest.status]; quest.status = (newQuestStatus); } - for (const statusTimer in quest.statusTimers) - { - if (Number.isNaN(Number.parseInt(statusTimer))) - { + for (const statusTimer in quest.statusTimers) { + if (Number.isNaN(Number.parseInt(statusTimer))) { timerFixes[statusTimer] = (timerFixes[statusTimer] ?? 0) + 1; const newKey = QuestStatus[statusTimer]; @@ -613,13 +523,11 @@ export class ProfileFixerService } } - for (const questToDelete of questsToDelete) - { + for (const questToDelete of questsToDelete) { profile.Quests.splice(profile.Quests.indexOf(questToDelete), 1); } - if (Object.keys(fixes).length > 0) - { + if (Object.keys(fixes).length > 0) { this.logger.debug( `Updated quests values: ${Object.entries(fixes) .map(([k, v]) => `(${k}: ${v} times)`) @@ -627,8 +535,7 @@ export class ProfileFixerService ); } - if (Object.keys(timerFixes).length > 0) - { + if (Object.keys(timerFixes).length > 0) { this.logger.debug( `Updated statusTimers values: ${Object.entries(timerFixes) .map(([k, v]) => `(${k}: ${v} times)`) @@ -637,34 +544,27 @@ export class ProfileFixerService } } - protected addMissingRepeatableQuestsProperty(pmcProfile: IPmcData): void - { - if (pmcProfile.RepeatableQuests) - { + protected addMissingRepeatableQuestsProperty(pmcProfile: IPmcData): void { + if (pmcProfile.RepeatableQuests) { let repeatablesCompatible = true; - for (const currentRepeatable of pmcProfile.RepeatableQuests) - { + for (const currentRepeatable of pmcProfile.RepeatableQuests) { if ( !( - currentRepeatable.changeRequirement - && currentRepeatable.activeQuests.every( + currentRepeatable.changeRequirement && + currentRepeatable.activeQuests.every( (x) => typeof x.changeCost !== "undefined" && typeof x.changeStandingCost !== "undefined", ) ) - ) - { + ) { repeatablesCompatible = false; break; } } - if (!repeatablesCompatible) - { + if (!repeatablesCompatible) { pmcProfile.RepeatableQuests = []; this.logger.debug("Missing RepeatableQuests property added to profile"); } - } - else - { + } else { pmcProfile.RepeatableQuests = []; } } @@ -673,29 +573,22 @@ export class ProfileFixerService * Some profiles have hideout maxed and therefore no improvements * @param pmcProfile Profile to add improvement data to */ - protected addMissingWallImprovements(pmcProfile: IPmcData): void - { + protected addMissingWallImprovements(pmcProfile: IPmcData): void { const profileWallArea = pmcProfile.Hideout.Areas.find((x) => x.type === HideoutAreas.EMERGENCY_WALL)!; - const wallDb = this.databaseService.getHideout().areas - .find((x) => x.type === HideoutAreas.EMERGENCY_WALL); + const wallDb = this.databaseService.getHideout().areas.find((x) => x.type === HideoutAreas.EMERGENCY_WALL); - if (profileWallArea.level > 0) - { - for (let i = 0; i < profileWallArea.level; i++) - { + if (profileWallArea.level > 0) { + for (let i = 0; i < profileWallArea.level; i++) { // Get wall stage from db const wallStageDb = wallDb!.stages[i]; - if (wallStageDb.improvements.length === 0) - { + if (wallStageDb.improvements.length === 0) { // No improvements, skip continue; } - for (const improvement of wallStageDb.improvements) - { + for (const improvement of wallStageDb.improvements) { // Don't overwrite existing improvement - if (pmcProfile.Hideout.Improvement[improvement.id]) - { + if (pmcProfile.Hideout.Improvement[improvement.id]) { continue; } @@ -714,13 +607,10 @@ export class ProfileFixerService * A new property was added to slot items "locationIndex", if this is missing, the hideout slot item must be removed * @param pmcProfile Profile to find and remove slots from */ - protected removeResourcesFromSlotsInHideoutWithoutLocationIndexValue(pmcProfile: IPmcData): void - { - for (const area of pmcProfile.Hideout.Areas) - { + protected removeResourcesFromSlotsInHideoutWithoutLocationIndexValue(pmcProfile: IPmcData): void { + for (const area of pmcProfile.Hideout.Areas) { // Skip areas with no resource slots - if (area.slots.length === 0) - { + if (area.slots.length === 0) { continue; } @@ -739,8 +629,7 @@ export class ProfileFixerService * Hideout slots need to be in a specific order, locationIndex in ascending order * @param pmcProfile profile to edit */ - protected reorderHideoutAreasWithResouceInputs(pmcProfile: IPmcData): void - { + protected reorderHideoutAreasWithResouceInputs(pmcProfile: IPmcData): void { const areasToCheck = [ HideoutAreas.AIR_FILTERING, HideoutAreas.GENERATOR, @@ -748,23 +637,19 @@ export class ProfileFixerService HideoutAreas.WATER_COLLECTOR, ]; - for (const areaId of areasToCheck) - { + for (const areaId of areasToCheck) { const area = pmcProfile.Hideout.Areas.find((area) => area.type === areaId); - if (!area) - { + if (!area) { this.logger.debug(`unable to sort: ${area!.type} (${areaId}) slots, no area found`); continue; } - if (!area.slots || area.slots.length === 0) - { + if (!area.slots || area.slots.length === 0) { this.logger.debug(`unable to sort ${areaId} slots, no slots found`); continue; } - area.slots = area.slots.sort((a, b) => - { + area.slots = area.slots.sort((a, b) => { return a.locationIndex > b.locationIndex ? 1 : -1; }); } @@ -779,18 +664,14 @@ export class ProfileFixerService areaType: HideoutAreas, emptyItemCount: number, pmcProfile: IPmcData, - ): void - { + ): void { const area = pmcProfile.Hideout.Areas.find((x) => x.type === areaType); area!.slots = this.addObjectsToArray(emptyItemCount, area!.slots); } - protected addObjectsToArray(count: number, slots: HideoutSlot[]): HideoutSlot[] - { - for (let i = 0; i < count; i++) - { - if (!slots.some((x) => x.locationIndex === i)) - { + protected addObjectsToArray(count: number, slots: HideoutSlot[]): HideoutSlot[] { + for (let i = 0; i < count; i++) { + if (!slots.some((x) => x.locationIndex === i)) { slots.push({ locationIndex: i }); } } @@ -802,53 +683,44 @@ export class ProfileFixerService * Iterate over players hideout areas and find what's build, look for missing bonuses those areas give and add them if missing * @param pmcProfile Profile to update */ - public addMissingHideoutBonusesToProfile(pmcProfile: IPmcData): void - { + public addMissingHideoutBonusesToProfile(pmcProfile: IPmcData): void { const profileHideoutAreas = pmcProfile.Hideout.Areas; const profileBonuses = pmcProfile.Bonuses; const dbHideoutAreas = this.databaseService.getHideout().areas; - for (const area of profileHideoutAreas) - { + for (const area of profileHideoutAreas) { const areaType = area.type; const level = area.level; - if (level === 0) - { + if (level === 0) { continue; } // Get array of hideout area upgrade levels to check for bonuses // Zero indexed const areaLevelsToCheck: number[] = []; - for (let index = 0; index < level + 1; index++) - { + for (let index = 0; index < level + 1; index++) { areaLevelsToCheck.push(index); } // Iterate over area levels, check for bonuses, add if needed const dbArea = dbHideoutAreas.find((x) => x.type === areaType); - if (!dbArea) - { + if (!dbArea) { continue; } - for (const level of areaLevelsToCheck) - { + for (const level of areaLevelsToCheck) { // Get areas level bonuses from db const levelBonuses = dbArea.stages[level]?.bonuses; - if (!levelBonuses || levelBonuses.length === 0) - { + if (!levelBonuses || levelBonuses.length === 0) { continue; } // Iterate over each bonus for the areas level - for (const bonus of levelBonuses) - { + for (const bonus of levelBonuses) { // Check if profile has bonus const profileBonus = this.getBonusFromProfile(profileBonuses, bonus); - if (!profileBonus) - { + if (!profileBonus) { // no bonus, add to profile this.logger.debug( `Profile has level ${level} area ${ @@ -867,21 +739,17 @@ export class ProfileFixerService * @param bonus bonus to find * @returns matching bonus */ - protected getBonusFromProfile(profileBonuses: Bonus[], bonus: StageBonus): Bonus | undefined - { + protected getBonusFromProfile(profileBonuses: Bonus[], bonus: StageBonus): Bonus | undefined { // match by id first, used by "TextBonus" bonuses - if (bonus.id) - { + if (bonus.id) { return profileBonuses.find((x) => x.id === bonus.id); } - if (bonus.type === BonusType.STASH_SIZE) - { + if (bonus.type === BonusType.STASH_SIZE) { return profileBonuses.find((x) => x.type === bonus.type && x.templateId === bonus.templateId); } - if (bonus.type === BonusType.ADDITIONAL_SLOTS) - { + if (bonus.type === BonusType.ADDITIONAL_SLOTS) { return profileBonuses.find( (x) => x.type === bonus.type && x.value === bonus.value && x.visible === bonus.visible, ); @@ -895,8 +763,7 @@ export class ProfileFixerService * @param sessionId Session id * @param pmcProfile Profile to check inventory of */ - public checkForOrphanedModdedItems(sessionId: string, fullProfile: ISptProfile): void - { + public checkForOrphanedModdedItems(sessionId: string, fullProfile: ISptProfile): void { const itemsDb = this.databaseService.getItems(); const pmcProfile = fullProfile.characters.pmc; @@ -905,17 +772,13 @@ export class ProfileFixerService const inventoryItemsToCheck = pmcProfile.Inventory.items.filter((item) => ["hideout", "main"].includes(item.slotId ?? ""), ); - if (inventoryItemsToCheck) - { + if (inventoryItemsToCheck) { // Check each item in inventory to ensure item exists in itemdb - for (const item of inventoryItemsToCheck) - { - if (!itemsDb[item._tpl]) - { + for (const item of inventoryItemsToCheck) { + if (!itemsDb[item._tpl]) { this.logger.error(this.localisationService.getText("fixer-mod_item_found", item._tpl)); - if (this.coreConfig.fixes.removeModItemsFromProfile) - { + if (this.coreConfig.fixes.removeModItemsFromProfile) { this.logger.success( `Deleting item from inventory and insurance with id: ${item._id} tpl: ${item._tpl}`, ); @@ -927,63 +790,51 @@ export class ProfileFixerService } } - if (fullProfile.userbuilds) - { + if (fullProfile.userbuilds) { // Remove invalid builds from weapon, equipment and magazine build lists const weaponBuilds = fullProfile.userbuilds?.weaponBuilds || []; - fullProfile.userbuilds.weaponBuilds = weaponBuilds.filter((weaponBuild) => - { + fullProfile.userbuilds.weaponBuilds = weaponBuilds.filter((weaponBuild) => { return !this.shouldRemoveWeaponEquipmentBuild("weapon", weaponBuild, itemsDb); }); const equipmentBuilds = fullProfile.userbuilds?.equipmentBuilds || []; - fullProfile.userbuilds.equipmentBuilds = equipmentBuilds.filter((equipmentBuild) => - { + fullProfile.userbuilds.equipmentBuilds = equipmentBuilds.filter((equipmentBuild) => { return !this.shouldRemoveWeaponEquipmentBuild("equipment", equipmentBuild, itemsDb); }); const magazineBuilds = fullProfile.userbuilds?.magazineBuilds || []; - fullProfile.userbuilds.magazineBuilds = magazineBuilds.filter((magazineBuild) => - { + fullProfile.userbuilds.magazineBuilds = magazineBuilds.filter((magazineBuild) => { return !this.shouldRemoveMagazineBuild(magazineBuild, itemsDb); }); } // Iterate over dialogs, looking for messages with items not found in item db, remove message if item found - for (const dialogId in fullProfile.dialogues) - { + for (const dialogId in fullProfile.dialogues) { const dialog = fullProfile.dialogues[dialogId]; - if (!dialog?.messages) - { + if (!dialog?.messages) { continue; // Skip dialog with no messages } // Iterate over all messages in dialog - for (const [_, message] of Object.entries(dialog.messages)) - { - if (!message.items?.data) - { + for (const [_, message] of Object.entries(dialog.messages)) { + if (!message.items?.data) { continue; // Skip message with no items } // Fix message with no items but have the flags to indicate items to collect - if (message.items.data.length === 0 && message.hasRewards) - { + if (message.items.data.length === 0 && message.hasRewards) { message.hasRewards = false; message.rewardCollected = true; continue; } // Iterate over all items in message - for (const item of message.items.data) - { + for (const item of message.items.data) { // Check item exists in itemsDb - if (!itemsDb[item._tpl]) - { + if (!itemsDb[item._tpl]) { this.logger.error(this.localisationService.getText("fixer-mod_item_found", item._tpl)); - if (this.coreConfig.fixes.removeModItemsFromProfile) - { + if (this.coreConfig.fixes.removeModItemsFromProfile) { dialog.messages.splice( dialog.messages.findIndex((x) => x._id === message._id), 1, @@ -1000,28 +851,21 @@ export class ProfileFixerService } const clothing = this.databaseService.getTemplates().customization; - for (const [_, suitId] of Object.entries(fullProfile.suits)) - { - if (!clothing[suitId]) - { + for (const [_, suitId] of Object.entries(fullProfile.suits)) { + if (!clothing[suitId]) { this.logger.error(this.localisationService.getText("fixer-clothing_item_found", suitId)); - if (this.coreConfig.fixes.removeModItemsFromProfile) - { + if (this.coreConfig.fixes.removeModItemsFromProfile) { fullProfile.suits.splice(fullProfile.suits.indexOf(suitId), 1); this.logger.warning(`Non-default suit purchase: ${suitId} removed from profile`); } } } - for (const repeatable of fullProfile.characters.pmc.RepeatableQuests ?? []) - { - for (const [_, activeQuest] of Object.entries(repeatable.activeQuests ?? [])) - { - if (!this.traderHelper.traderEnumHasValue(activeQuest.traderId)) - { + for (const repeatable of fullProfile.characters.pmc.RepeatableQuests ?? []) { + for (const [_, activeQuest] of Object.entries(repeatable.activeQuests ?? [])) { + if (!this.traderHelper.traderEnumHasValue(activeQuest.traderId)) { this.logger.error(this.localisationService.getText("fixer-trader_found", activeQuest.traderId)); - if (this.coreConfig.fixes.removeModItemsFromProfile) - { + if (this.coreConfig.fixes.removeModItemsFromProfile) { this.logger.warning( `Non-default quest: ${activeQuest._id} from trader: ${activeQuest.traderId} removed from RepeatableQuests list in profile`, ); @@ -1034,19 +878,14 @@ export class ProfileFixerService continue; } - for (const successReward of activeQuest.rewards.Success!) - { - if (successReward.type === "Item") - { - for (const rewardItem of successReward.items!) - { - if (!itemsDb[rewardItem._tpl]) - { + for (const successReward of activeQuest.rewards.Success!) { + if (successReward.type === "Item") { + for (const rewardItem of successReward.items!) { + if (!itemsDb[rewardItem._tpl]) { this.logger.error( this.localisationService.getText("fixer-mod_item_found", rewardItem._tpl), ); - if (this.coreConfig.fixes.removeModItemsFromProfile) - { + if (this.coreConfig.fixes.removeModItemsFromProfile) { this.logger.warning( `Non-default quest: ${activeQuest._id} from trader: ${activeQuest.traderId} removed from RepeatableQuests list in profile`, ); @@ -1062,13 +901,10 @@ export class ProfileFixerService } } - for (const traderId in fullProfile.traderPurchases) - { - if (!this.traderHelper.traderEnumHasValue(traderId)) - { + for (const traderId in fullProfile.traderPurchases) { + if (!this.traderHelper.traderEnumHasValue(traderId)) { this.logger.error(this.localisationService.getText("fixer-trader_found", traderId)); - if (this.coreConfig.fixes.removeModItemsFromProfile) - { + if (this.coreConfig.fixes.removeModItemsFromProfile) { this.logger.warning(`Non-default trader: ${traderId} removed from traderPurchases list in profile`); delete fullProfile.traderPurchases[traderId]; } @@ -1086,17 +922,13 @@ export class ProfileFixerService buildType: string, build: IWeaponBuild | IEquipmentBuild, itemsDb: Record, - ): boolean - { - for (const item of build.Items) - { + ): boolean { + for (const item of build.Items) { // Check item exists in itemsDb - if (!itemsDb[item._tpl]) - { + if (!itemsDb[item._tpl]) { this.logger.error(this.localisationService.getText("fixer-mod_item_found", item._tpl)); - if (this.coreConfig.fixes.removeModItemsFromProfile) - { + if (this.coreConfig.fixes.removeModItemsFromProfile) { this.logger.warning( `Item: ${item._tpl} has resulted in the deletion of ${buildType} build: ${build.Name}`, ); @@ -1119,23 +951,18 @@ export class ProfileFixerService protected shouldRemoveMagazineBuild( magazineBuild: IMagazineBuild, itemsDb: Record, - ): boolean - { - for (const item of magazineBuild.Items) - { + ): boolean { + for (const item of magazineBuild.Items) { // Magazine builds can have undefined items in them, skip those - if (!item) - { + if (!item) { continue; } // Check item exists in itemsDb - if (!itemsDb[item.TemplateId]) - { + if (!itemsDb[item.TemplateId]) { this.logger.error(this.localisationService.getText("fixer-mod_item_found", item.TemplateId)); - if (this.coreConfig.fixes.removeModItemsFromProfile) - { + if (this.coreConfig.fixes.removeModItemsFromProfile) { this.logger.warning( `Item: ${item.TemplateId} has resulted in the deletion of magazine build: ${magazineBuild.Name}`, ); @@ -1154,42 +981,34 @@ export class ProfileFixerService * Attempt to fix common item issues that corrupt profiles * @param pmcProfile Profile to check items of */ - public fixProfileBreakingInventoryItemIssues(pmcProfile: IPmcData): void - { + public fixProfileBreakingInventoryItemIssues(pmcProfile: IPmcData): void { // Create a mapping of all inventory items, keyed by _id value - const itemMapping = pmcProfile.Inventory.items.reduce((acc, curr) => - { + const itemMapping = pmcProfile.Inventory.items.reduce((acc, curr) => { acc[curr._id] = acc[curr._id] || []; acc[curr._id].push(curr); return acc; }, {}); - for (const key in itemMapping) - { + for (const key in itemMapping) { // Only one item for this id, not a dupe - if (itemMapping[key].length === 1) - { + if (itemMapping[key].length === 1) { continue; } this.logger.warning(`${itemMapping[key].length - 1} duplicate(s) found for item: ${key}`); const itemAJson = this.jsonUtil.serialize(itemMapping[key][0]); const itemBJson = this.jsonUtil.serialize(itemMapping[key][1]); - if (itemAJson === itemBJson) - { + if (itemAJson === itemBJson) { // Both items match, we can safely delete one const indexOfItemToRemove = pmcProfile.Inventory.items.findIndex((x) => x._id === key); pmcProfile.Inventory.items.splice(indexOfItemToRemove, 1); this.logger.warning(`Deleted duplicate item: ${key}`); - } - else - { + } else { // Items are different, replace ID with unique value // Only replace ID if items have no children, we dont want orphaned children const itemsHaveChildren = pmcProfile.Inventory.items.some((x) => x.parentId === key); - if (!itemsHaveChildren) - { + if (!itemsHaveChildren) { const itemToAdjust = pmcProfile.Inventory.items.find((x) => x._id === key)!; itemToAdjust._id = this.hashUtil.generate(); this.logger.warning(`Replace duplicate item Id: ${key} with ${itemToAdjust._id}`); @@ -1198,25 +1017,21 @@ export class ProfileFixerService } // Iterate over all inventory items - for (const item of pmcProfile.Inventory.items.filter((x) => x.slotId)) - { - if (!item.upd) - { + for (const item of pmcProfile.Inventory.items.filter((x) => x.slotId)) { + if (!item.upd) { // Ignore items without a upd object continue; } // Check items with a tag that contains non alphanumeric characters const regxp = /([/w"\\'])/g; - if (item.upd.Tag?.Name && regxp.test(item.upd.Tag?.Name)) - { + if (item.upd.Tag?.Name && regxp.test(item.upd.Tag?.Name)) { this.logger.warning(`Fixed item: ${item._id}s Tag value, removed invalid characters`); item.upd.Tag.Name = item.upd.Tag.Name.replace(regxp, ""); } // Check items with StackObjectsCount (undefined) - if (item.upd?.StackObjectsCount === undefined) - { + if (item.upd?.StackObjectsCount === undefined) { this.logger.warning(`Fixed item: ${item._id}s undefined StackObjectsCount value, now set to 1`); item.upd.StackObjectsCount = 1; } @@ -1228,8 +1043,7 @@ export class ProfileFixerService const playerIsUsec = pmcProfile.Info.Side.toLowerCase() === "usec"; // Check Head - if (!customizationDb[pmcProfile.Customization.Head]) - { + if (!customizationDb[pmcProfile.Customization.Head]) { const defaultHead = playerIsUsec ? customizationDbArray.find((x) => x._name === "DefaultUsecHead") : customizationDbArray.find((x) => x._name === "DefaultBearHead"); @@ -1237,30 +1051,27 @@ export class ProfileFixerService } // check Body - if (!customizationDb[pmcProfile.Customization.Body]) - { - const defaultBody - = pmcProfile.Info.Side.toLowerCase() === "usec" + if (!customizationDb[pmcProfile.Customization.Body]) { + const defaultBody = + pmcProfile.Info.Side.toLowerCase() === "usec" ? customizationDbArray.find((x) => x._name === "DefaultUsecBody") : customizationDbArray.find((x) => x._name === "DefaultBearBody"); pmcProfile.Customization.Body = defaultBody!._id; } // check Hands - if (!customizationDb[pmcProfile.Customization.Hands]) - { - const defaultHands - = pmcProfile.Info.Side.toLowerCase() === "usec" + if (!customizationDb[pmcProfile.Customization.Hands]) { + const defaultHands = + pmcProfile.Info.Side.toLowerCase() === "usec" ? customizationDbArray.find((x) => x._name === "DefaultUsecHands") : customizationDbArray.find((x) => x._name === "DefaultBearHands"); pmcProfile.Customization.Hands = defaultHands!._id; } // check Hands - if (!customizationDb[pmcProfile.Customization.Feet]) - { - const defaultFeet - = pmcProfile.Info.Side.toLowerCase() === "usec" + if (!customizationDb[pmcProfile.Customization.Feet]) { + const defaultFeet = + pmcProfile.Info.Side.toLowerCase() === "usec" ? customizationDbArray.find((x) => x._name === "DefaultUsecFeet") : customizationDbArray.find((x) => x._name === "DefaultBearFeet"); pmcProfile.Customization.Feet = defaultFeet!._id; @@ -1271,10 +1082,8 @@ export class ProfileFixerService * Add `Improvements` object to hideout if missing - added in eft 13.0.21469 * @param pmcProfile profile to update */ - public addMissingUpgradesPropertyToHideout(pmcProfile: IPmcData): void - { - if (!pmcProfile.Hideout.Improvement) - { + public addMissingUpgradesPropertyToHideout(pmcProfile: IPmcData): void { + if (!pmcProfile.Hideout.Improvement) { pmcProfile.Hideout.Improvement = {}; } } @@ -1283,32 +1092,26 @@ export class ProfileFixerService * Iterate over associated profile template and check all hideout areas exist, add if not * @param fullProfile Profile to update */ - public addMissingHideoutAreasToProfile(fullProfile: ISptProfile): void - { + public addMissingHideoutAreasToProfile(fullProfile: ISptProfile): void { const pmcProfile = fullProfile.characters.pmc; // No profile, probably new account being created - if (!pmcProfile?.Hideout) - { + if (!pmcProfile?.Hideout) { return; } const profileTemplates = this.databaseService.getTemplates().profiles[fullProfile.info.edition]; - if (!profileTemplates) - { + if (!profileTemplates) { return; } const profileTemplate = profileTemplates[pmcProfile.Info.Side.toLowerCase()]; - if (!profileTemplate) - { + if (!profileTemplate) { return; } // Get all areas from templates/profiles.json - for (const area of profileTemplate.character.Hideout.Areas) - { - if (!pmcProfile.Hideout.Areas.some((x) => x.type === area.type)) - { + for (const area of profileTemplate.character.Hideout.Areas) { + if (!pmcProfile.Hideout.Areas.some((x) => x.type === area.type)) { pmcProfile.Hideout.Areas.push(area); this.logger.debug(`Added missing hideout area ${area.type} to profile`); } @@ -1319,12 +1122,9 @@ export class ProfileFixerService * These used to be used for storing scav case rewards, rewards are now generated on pickup * @param pmcProfile Profile to update */ - public removeLegacyScavCaseProductionCrafts(pmcProfile: IPmcData): void - { - for (const prodKey in pmcProfile.Hideout?.Production) - { - if (prodKey.startsWith("ScavCase")) - { + public removeLegacyScavCaseProductionCrafts(pmcProfile: IPmcData): void { + for (const prodKey in pmcProfile.Hideout?.Production) { + if (prodKey.startsWith("ScavCase")) { delete pmcProfile.Hideout.Production[prodKey]; } } @@ -1335,12 +1135,10 @@ export class ProfileFixerService * We store the old AID value in new field `sessionId` * @param fullProfile Profile to update */ - public fixIncorrectAidValue(fullProfile: ISptProfile): void - { + public fixIncorrectAidValue(fullProfile: ISptProfile): void { // Not a number, regenerate // biome-ignore lint/suspicious/noGlobalIsNan: - if (isNaN(fullProfile.characters.pmc.aid) || !fullProfile.info.aid) - { + if (isNaN(fullProfile.characters.pmc.aid) || !fullProfile.info.aid) { fullProfile.characters.pmc.sessionId = (fullProfile.characters.pmc.aid); fullProfile.characters.pmc.aid = this.hashUtil.generateAccountId(); @@ -1359,11 +1157,9 @@ export class ProfileFixerService * Bsg nested `stats` into a sub object called 'eft' * @param fullProfile Profile to check for and migrate stats data */ - public migrateStatsToNewStructure(fullProfile: ISptProfile): void - { + public migrateStatsToNewStructure(fullProfile: ISptProfile): void { // Data is in old structure, migrate - if ("OverallCounters" in fullProfile.characters.pmc.Stats) - { + if ("OverallCounters" in fullProfile.characters.pmc.Stats) { this.logger.debug("Migrating stats object into new structure"); const statsCopy = this.cloner.clone(fullProfile.characters.pmc.Stats); @@ -1378,29 +1174,23 @@ export class ProfileFixerService * 26126 (7th August) requires bonuses to have an ID, these were not included in the default profile presets * @param pmcProfile Profile to add missing IDs to */ - public addMissingIdsToBonuses(pmcProfile: IPmcData): void - { + public addMissingIdsToBonuses(pmcProfile: IPmcData): void { let foundBonus = false; - for (const bonus of pmcProfile.Bonuses) - { - if (bonus.id) - { + for (const bonus of pmcProfile.Bonuses) { + if (bonus.id) { // Exists already, skip continue; } // Bonus lacks id, find matching hideout area / stage / bonus - for (const area of this.databaseService.getHideout().areas) - { + for (const area of this.databaseService.getHideout().areas) { // TODO: skip if no stages - for (const stageIndex in area.stages) - { + for (const stageIndex in area.stages) { const stageInfo = area.stages[stageIndex]; const matchingBonus = stageInfo.bonuses.find( (x) => x.templateId === bonus.templateId && x.type === bonus.type, ); - if (matchingBonus) - { + if (matchingBonus) { // Add id to bonus, flag bonus as found and exit stage loop bonus.id = matchingBonus.id; this.logger.debug(`Added missing Id: ${bonus.id} to bonus: ${bonus.type}`); @@ -1410,8 +1200,7 @@ export class ProfileFixerService } // We've found the bonus we're after, break out of area loop - if (foundBonus) - { + if (foundBonus) { foundBonus = false; break; } @@ -1422,11 +1211,9 @@ export class ProfileFixerService /** * 3.8.0 utilized the wrong ProductionTime for bitcoin, fix it if it's found */ - public fixBitcoinProductionTime(pmcProfile: IPmcData): void - { + public fixBitcoinProductionTime(pmcProfile: IPmcData): void { const btcProd = pmcProfile.Hideout?.Production[HideoutHelper.bitcoinFarm]; - if (btcProd) - { + if (btcProd) { btcProd.ProductionTime = this.hideoutHelper.getAdjustedCraftTimeWithSkills( pmcProfile, HideoutHelper.bitcoinProductionId, @@ -1438,10 +1225,8 @@ export class ProfileFixerService * At some point the property name was changed,migrate data across to new name * @param pmcProfile Profile to migrate improvements in */ - protected migrateImprovements(pmcProfile: IPmcData): void - { - if ("Improvements" in pmcProfile.Hideout) - { + protected migrateImprovements(pmcProfile: IPmcData): void { + if ("Improvements" in pmcProfile.Hideout) { const improvements = pmcProfile.Hideout.Improvements as Record; pmcProfile.Hideout.Improvement = this.cloner.clone(improvements); delete pmcProfile.Hideout.Improvements; @@ -1453,21 +1238,17 @@ export class ProfileFixerService * After removing mods that add quests, the quest panel will break without removing these * @param pmcProfile Profile to remove dead quests from */ - protected removeOrphanedQuests(pmcProfile: IPmcData): void - { + protected removeOrphanedQuests(pmcProfile: IPmcData): void { const quests = this.databaseService.getQuests(); const profileQuests = pmcProfile.Quests; const repeatableQuests: IRepeatableQuest[] = []; - for (const repeatableQuestType of pmcProfile.RepeatableQuests) - { + for (const repeatableQuestType of pmcProfile.RepeatableQuests) { repeatableQuests.push(...repeatableQuestType.activeQuests); } - for (let i = profileQuests.length - 1; i >= 0; i--) - { - if (!(quests[profileQuests[i].qid] || repeatableQuests.some((x) => x._id === profileQuests[i].qid))) - { + for (let i = profileQuests.length - 1; i >= 0; i--) { + if (!(quests[profileQuests[i].qid] || repeatableQuests.some((x) => x._id === profileQuests[i].qid))) { profileQuests.splice(i, 1); this.logger.success("Successfully removed orphaned quest that doesnt exist in our quest data"); } @@ -1478,12 +1259,9 @@ export class ProfileFixerService * If someone has run a mod from pre-3.8.0, it results in an invalid `nextResupply` value * Resolve this by setting the nextResupply to 0 if it's undefined */ - protected fixNullTraderNextResupply(pmcProfile: IPmcData): void - { - for (const [traderId, trader] of Object.entries(pmcProfile.TradersInfo)) - { - if (trader?.nextResupply === undefined) - { + protected fixNullTraderNextResupply(pmcProfile: IPmcData): void { + for (const [traderId, trader] of Object.entries(pmcProfile.TradersInfo)) { + if (trader?.nextResupply === undefined) { this.logger.warning(`trader ${traderId} has a undefined nextResupply value, resetting to 0`); trader.nextResupply = 0; } diff --git a/project/src/services/ProfileSnapshotService.ts b/project/src/services/ProfileSnapshotService.ts index f911f922..db360ff6 100644 --- a/project/src/services/ProfileSnapshotService.ts +++ b/project/src/services/ProfileSnapshotService.ts @@ -1,22 +1,19 @@ -import { inject, injectable } from "tsyringe"; import { ISptProfile } from "@spt/models/eft/profile/ISptProfile"; import { ICloner } from "@spt/utils/cloners/ICloner"; +import { inject, injectable } from "tsyringe"; @injectable() -export class ProfileSnapshotService -{ +export class ProfileSnapshotService { protected storedProfileSnapshots: Record = {}; - constructor(@inject("PrimaryCloner") protected cloner: ICloner) - {} + constructor(@inject("PrimaryCloner") protected cloner: ICloner) {} /** * Store a profile into an in-memory object * @param sessionID session id - acts as the key * @param profile - profile to save */ - public storeProfileSnapshot(sessionID: string, profile: ISptProfile): void - { + public storeProfileSnapshot(sessionID: string, profile: ISptProfile): void { this.storedProfileSnapshots[sessionID] = this.cloner.clone(profile); } @@ -25,10 +22,8 @@ export class ProfileSnapshotService * @param sessionID key * @returns A player profile object */ - public getProfileSnapshot(sessionID: string): ISptProfile | undefined - { - if (this.storedProfileSnapshots[sessionID]) - { + public getProfileSnapshot(sessionID: string): ISptProfile | undefined { + if (this.storedProfileSnapshots[sessionID]) { return this.storedProfileSnapshots[sessionID]; } @@ -40,10 +35,8 @@ export class ProfileSnapshotService * @param sessionID key * @returns true if exists */ - public hasProfileSnapshot(sessionID: string): boolean - { - if (this.storedProfileSnapshots[sessionID]) - { + public hasProfileSnapshot(sessionID: string): boolean { + if (this.storedProfileSnapshots[sessionID]) { return true; } @@ -54,8 +47,7 @@ export class ProfileSnapshotService * Remove a stored profile by key * @param sessionID key */ - public clearProfileSnapshot(sessionID: string): void - { + public clearProfileSnapshot(sessionID: string): void { delete this.storedProfileSnapshots[sessionID]; } } diff --git a/project/src/services/RagfairCategoriesService.ts b/project/src/services/RagfairCategoriesService.ts index 4d6651cb..2e676633 100644 --- a/project/src/services/RagfairCategoriesService.ts +++ b/project/src/services/RagfairCategoriesService.ts @@ -1,18 +1,16 @@ -import { inject, injectable } from "tsyringe"; import { PaymentHelper } from "@spt/helpers/PaymentHelper"; import { IRagfairOffer } from "@spt/models/eft/ragfair/IRagfairOffer"; import { ISearchRequestData, OfferOwnerType } from "@spt/models/eft/ragfair/ISearchRequestData"; import { MemberCategory } from "@spt/models/enums/MemberCategory"; import { ILogger } from "@spt/models/spt/utils/ILogger"; +import { inject, injectable } from "tsyringe"; @injectable() -export class RagfairCategoriesService -{ +export class RagfairCategoriesService { constructor( @inject("PrimaryLogger") protected logger: ILogger, @inject("PaymentHelper") protected paymentHelper: PaymentHelper, - ) - {} + ) {} /** * Get a dictionary of each item the play can see in their flea menu, filtered by what is available for them to buy @@ -25,46 +23,39 @@ export class RagfairCategoriesService offers: IRagfairOffer[], searchRequestData: ISearchRequestData, fleaUnlocked: boolean, - ): Record - { + ): Record { // Get offers valid for search request, then reduce them down to just the counts return offers - .filter((offer) => - { + .filter((offer) => { const isTraderOffer = offer.user.memberType === MemberCategory.TRADER; // Not level 15 and offer is from player, skip - if (!(fleaUnlocked || isTraderOffer)) - { + if (!(fleaUnlocked || isTraderOffer)) { return false; } // Remove items not for money when `removeBartering` is enabled if ( - searchRequestData.removeBartering - && (offer.requirements.length > 1 || !this.paymentHelper.isMoneyTpl(offer.requirements[0]._tpl)) - ) - { + searchRequestData.removeBartering && + (offer.requirements.length > 1 || !this.paymentHelper.isMoneyTpl(offer.requirements[0]._tpl)) + ) { return false; } // Remove when filter set to players only + offer is from trader - if (searchRequestData.offerOwnerType === OfferOwnerType.PLAYEROWNERTYPE && isTraderOffer) - { + if (searchRequestData.offerOwnerType === OfferOwnerType.PLAYEROWNERTYPE && isTraderOffer) { return false; } // Remove when filter set to traders only + offer is not from trader - if (searchRequestData.offerOwnerType === OfferOwnerType.TRADEROWNERTYPE && !isTraderOffer) - { + if (searchRequestData.offerOwnerType === OfferOwnerType.TRADEROWNERTYPE && !isTraderOffer) { return false; } // Passed checks, its a valid offer to process return true; }) - .reduce((acc, offer) => - { + .reduce((acc, offer) => { const itemTpl = offer.items[0]._tpl; // Increment the category or add if doesnt exist acc[itemTpl] = (acc[itemTpl] || 0) + 1; diff --git a/project/src/services/RagfairLinkedItemService.ts b/project/src/services/RagfairLinkedItemService.ts index 5c148f93..963d9a71 100644 --- a/project/src/services/RagfairLinkedItemService.ts +++ b/project/src/services/RagfairLinkedItemService.ts @@ -1,24 +1,20 @@ -import { inject, injectable } from "tsyringe"; import { ItemHelper } from "@spt/helpers/ItemHelper"; import { ITemplateItem } from "@spt/models/eft/common/tables/ITemplateItem"; import { BaseClasses } from "@spt/models/enums/BaseClasses"; import { DatabaseService } from "@spt/services/DatabaseService"; +import { inject, injectable } from "tsyringe"; @injectable() -export class RagfairLinkedItemService -{ +export class RagfairLinkedItemService { protected linkedItemsCache: Record> = {}; constructor( @inject("DatabaseService") protected databaseService: DatabaseService, @inject("ItemHelper") protected itemHelper: ItemHelper, - ) - {} + ) {} - public getLinkedItems(linkedSearchId: string): Set - { - if (Object.keys(this.linkedItemsCache).length === 0) - { + public getLinkedItems(linkedSearchId: string): Set { + if (Object.keys(this.linkedItemsCache).length === 0) { this.buildLinkedItemTable(); } @@ -30,11 +26,9 @@ export class RagfairLinkedItemService * @param itemTpl Item to get sub-items for * @returns ITemplateItem array */ - public getLinkedDbItems(itemTpl: string): ITemplateItem[] - { + public getLinkedDbItems(itemTpl: string): ITemplateItem[] { const linkedItemsToWeaponTpls = this.getLinkedItems(itemTpl); - return [...linkedItemsToWeaponTpls].map((x) => - { + return [...linkedItemsToWeaponTpls].map((x) => { const itemDetails = this.itemHelper.getItem(x); return itemDetails[1]; }); @@ -43,27 +37,21 @@ export class RagfairLinkedItemService /** * Create Dictionary of every item and the items associated with it */ - protected buildLinkedItemTable(): void - { + protected buildLinkedItemTable(): void { const linkedItems: Record = {}; - const getLinkedItems = (id: string) => - { - if (!(id in linkedItems)) - { + const getLinkedItems = (id: string) => { + if (!(id in linkedItems)) { linkedItems[id] = new Set(); } return linkedItems[id]; }; - for (const item of Object.values(this.databaseService.getItems())) - { + for (const item of Object.values(this.databaseService.getItems())) { const itemLinkedSet = getLinkedItems(item._id); // TODO - move into own protected function - const applyLinkedItems = (items: string[]) => - { - for (const linkedItemId of items) - { + const applyLinkedItems = (items: string[]) => { + for (const linkedItemId of items) { itemLinkedSet.add(linkedItemId); getLinkedItems(linkedItemId).add(item._id); } @@ -74,8 +62,7 @@ export class RagfairLinkedItemService applyLinkedItems(this.getFilters(item, "Cartridges")); // Edge case, ensure ammo for revolves is included - if (item._parent === BaseClasses.REVOLVER) - { + if (item._parent === BaseClasses.REVOLVER) { // Find magazine for revolver this.addRevolverCylinderAmmoToLinkedItems(item, applyLinkedItems); } @@ -92,15 +79,12 @@ export class RagfairLinkedItemService protected addRevolverCylinderAmmoToLinkedItems( cylinder: ITemplateItem, applyLinkedItems: (items: string[]) => void, - ): void - { + ): void { const cylinderMod = cylinder._props.Slots?.find((x) => x._name === "mod_magazine"); - if (cylinderMod) - { + if (cylinderMod) { // Get the first cylinder filter tpl const cylinderTpl = cylinderMod._props.filters[0]?.Filter[0]; - if (cylinderTpl) - { + if (cylinderTpl) { // Get db data for cylinder tpl, add found slots info (camora_xxx) to linked items on revolver weapon const cylinderItem = this.itemHelper.getItem(cylinderTpl)[1]; applyLinkedItems(this.getFilters(cylinderItem, "Slots")); @@ -114,27 +98,21 @@ export class RagfairLinkedItemService * @param slot * @returns array of ids */ - protected getFilters(item: ITemplateItem, slot: string): string[] - { - if (!(slot in item._props && item._props[slot].length)) - { + protected getFilters(item: ITemplateItem, slot: string): string[] { + if (!(slot in item._props && item._props[slot].length)) { // item slot doesnt exist return []; } const filters: string[] = []; - for (const sub of item._props[slot]) - { - if (!("_props" in sub && "filters" in sub._props)) - { + for (const sub of item._props[slot]) { + if (!("_props" in sub && "filters" in sub._props)) { // not a filter continue; } - for (const filter of sub._props.filters) - { - for (const f of filter.Filter) - { + for (const filter of sub._props.filters) { + for (const f of filter.Filter) { filters.push(f); } } diff --git a/project/src/services/RagfairOfferService.ts b/project/src/services/RagfairOfferService.ts index 164e0bdd..203457bc 100644 --- a/project/src/services/RagfairOfferService.ts +++ b/project/src/services/RagfairOfferService.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { ItemHelper } from "@spt/helpers/ItemHelper"; import { ProfileHelper } from "@spt/helpers/ProfileHelper"; import { RagfairServerHelper } from "@spt/helpers/RagfairServerHelper"; @@ -12,14 +11,14 @@ import { ConfigServer } from "@spt/servers/ConfigServer"; import { SaveServer } from "@spt/servers/SaveServer"; import { DatabaseService } from "@spt/services/DatabaseService"; import { LocalisationService } from "@spt/services/LocalisationService"; -import { ICloner } from "@spt/utils/cloners/ICloner"; import { HttpResponseUtil } from "@spt/utils/HttpResponseUtil"; import { RagfairOfferHolder } from "@spt/utils/RagfairOfferHolder"; import { TimeUtil } from "@spt/utils/TimeUtil"; +import { ICloner } from "@spt/utils/cloners/ICloner"; +import { inject, injectable } from "tsyringe"; @injectable() -export class RagfairOfferService -{ +export class RagfairOfferService { protected playerOffersLoaded = false; /** Offer id + offer object */ protected expiredOffers: Record = {}; @@ -40,8 +39,7 @@ export class RagfairOfferService @inject("LocalisationService") protected localisationService: LocalisationService, @inject("ConfigServer") protected configServer: ConfigServer, @inject("PrimaryCloner") protected cloner: ICloner, - ) - { + ) { this.ragfairConfig = this.configServer.getConfig(ConfigTypes.RAGFAIR); this.ragfairOfferHandler = new RagfairOfferHolder( this.ragfairConfig.dynamic.offerItemCount.max, @@ -54,28 +52,23 @@ export class RagfairOfferService * Get all offers * @returns IRagfairOffer array */ - public getOffers(): IRagfairOffer[] - { + public getOffers(): IRagfairOffer[] { return this.ragfairOfferHandler.getOffers(); } - public getOfferByOfferId(offerId: string): IRagfairOffer | undefined - { + public getOfferByOfferId(offerId: string): IRagfairOffer | undefined { return this.ragfairOfferHandler.getOfferById(offerId); } - public getOffersOfType(templateId: string): IRagfairOffer[] | undefined - { + public getOffersOfType(templateId: string): IRagfairOffer[] | undefined { return this.ragfairOfferHandler.getOffersByTemplate(templateId); } - public addOffer(offer: IRagfairOffer): void - { + public addOffer(offer: IRagfairOffer): void { this.ragfairOfferHandler.addOffer(offer); } - public addOfferToExpired(staleOffer: IRagfairOffer): void - { + public addOfferToExpired(staleOffer: IRagfairOffer): void { this.expiredOffers[staleOffer._id] = staleOffer; } @@ -83,8 +76,7 @@ export class RagfairOfferService * Get total count of current expired offers * @returns Number of expired offers */ - public getExpiredOfferCount(): number - { + public getExpiredOfferCount(): number { return Object.keys(this.expiredOffers).length; } @@ -92,12 +84,10 @@ export class RagfairOfferService * Get an array of arrays of expired offer items + children * @returns Expired offer assorts */ - public getExpiredOfferAssorts(): Item[][] - { + public getExpiredOfferAssorts(): Item[][] { const expiredItems: Item[][] = []; - for (const expiredOfferId in this.expiredOffers) - { + for (const expiredOfferId in this.expiredOffers) { const expiredOffer = this.expiredOffers[expiredOfferId]; expiredItems.push(expiredOffer.items); } @@ -108,8 +98,7 @@ export class RagfairOfferService /** * Clear out internal expiredOffers dictionary of all items */ - public resetExpiredOffers(): void - { + public resetExpiredOffers(): void { this.expiredOffers = {}; } @@ -118,8 +107,7 @@ export class RagfairOfferService * @param offerId offer id to check for * @returns offer exists - true */ - public doesOfferExist(offerId: string): boolean - { + public doesOfferExist(offerId: string): boolean { return this.ragfairOfferHandler.getOfferById(offerId) !== undefined; } @@ -127,11 +115,9 @@ export class RagfairOfferService * Remove an offer from ragfair by offer id * @param offerId Offer id to remove */ - public removeOfferById(offerId: string): void - { + public removeOfferById(offerId: string): void { const offer = this.ragfairOfferHandler.getOfferById(offerId); - if (!offer) - { + if (!offer) { this.logger.warning( this.localisationService.getText("ragfair-unable_to_remove_offer_doesnt_exist", offerId), ); @@ -147,21 +133,17 @@ export class RagfairOfferService * @param offerId Offer to adjust stack size of * @param amount How much to deduct from offers stack size */ - public removeOfferStack(offerId: string, amount: number): void - { + public removeOfferStack(offerId: string, amount: number): void { const offer = this.ragfairOfferHandler.getOfferById(offerId); - if (offer) - { + if (offer) { offer.items[0].upd!.StackObjectsCount! -= amount; - if (offer.items[0].upd!.StackObjectsCount! <= 0) - { + if (offer.items[0].upd!.StackObjectsCount! <= 0) { this.processStaleOffer(offer); } } } - public removeAllOffersByTrader(traderId: string): void - { + public removeAllOffersByTrader(traderId: string): void { this.ragfairOfferHandler.removeAllOffersByTrader(traderId); } @@ -170,35 +152,28 @@ export class RagfairOfferService * @param traderID Trader to check * @returns true if they do */ - public traderOffersNeedRefreshing(traderID: string): boolean - { + public traderOffersNeedRefreshing(traderID: string): boolean { const trader = this.databaseService.getTrader(traderID); - if (!trader || !trader.base) - { + if (!trader || !trader.base) { this.logger.error(this.localisationService.getText("ragfair-trader_missing_base_file", traderID)); return false; } // No value, occurs when first run, trader offers need to be added to flea - if (typeof trader.base.refreshTraderRagfairOffers !== "boolean") - { + if (typeof trader.base.refreshTraderRagfairOffers !== "boolean") { trader.base.refreshTraderRagfairOffers = true; } return trader.base.refreshTraderRagfairOffers; } - public addPlayerOffers(): void - { - if (!this.playerOffersLoaded) - { - for (const sessionID in this.saveServer.getProfiles()) - { + public addPlayerOffers(): void { + if (!this.playerOffersLoaded) { + for (const sessionID in this.saveServer.getProfiles()) { const pmcData = this.saveServer.getProfile(sessionID).characters.pmc; - if (pmcData.RagfairInfo === undefined || pmcData.RagfairInfo.offers === undefined) - { + if (pmcData.RagfairInfo === undefined || pmcData.RagfairInfo.offers === undefined) { // Profile is wiped continue; } @@ -209,11 +184,9 @@ export class RagfairOfferService } } - public expireStaleOffers(): void - { + public expireStaleOffers(): void { const time = this.timeUtil.getTimestamp(); - for (const staleOffer of this.ragfairOfferHandler.getStaleOffers(time)) - { + for (const staleOffer of this.ragfairOfferHandler.getStaleOffers(time)) { this.processStaleOffer(staleOffer); } } @@ -222,28 +195,24 @@ export class RagfairOfferService * Remove stale offer from flea * @param staleOffer Stale offer to process */ - protected processStaleOffer(staleOffer: IRagfairOffer): void - { + protected processStaleOffer(staleOffer: IRagfairOffer): void { const staleOfferUserId = staleOffer.user.id; const isTrader = this.ragfairServerHelper.isTrader(staleOfferUserId); const isPlayer = this.profileHelper.isPlayer(staleOfferUserId.replace(/^pmc/, "")); // Skip trader offers, managed by RagfairServer.update() - if (isTrader) - { + if (isTrader) { return; } // Handle dynamic offer - if (!(isTrader || isPlayer)) - { + if (!(isTrader || isPlayer)) { // Dynamic offer this.addOfferToExpired(staleOffer); } // Handle player offer - items need returning/XP adjusting. Checking if offer has actually expired or not. - if (isPlayer && staleOffer.endTime <= this.timeUtil.getTimestamp()) - { + if (isPlayer && staleOffer.endTime <= this.timeUtil.getTimestamp()) { this.returnPlayerOffer(staleOffer); return; } @@ -252,20 +221,19 @@ export class RagfairOfferService this.removeOfferById(staleOffer._id); } - protected returnPlayerOffer(playerOffer: IRagfairOffer): void - { + protected returnPlayerOffer(playerOffer: IRagfairOffer): void { const pmcId = String(playerOffer.user.id); const profile = this.profileHelper.getProfileByPmcId(pmcId); - if (!profile) - { - this.logger.error(`Unable to return flea offer ${playerOffer._id} as the profile: ${pmcId} could not be found`); + if (!profile) { + this.logger.error( + `Unable to return flea offer ${playerOffer._id} as the profile: ${pmcId} could not be found`, + ); return; } const offerinProfileIndex = profile.RagfairInfo.offers.findIndex((o) => o._id === playerOffer._id); - if (offerinProfileIndex === -1) - { + if (offerinProfileIndex === -1) { this.logger.warning( this.localisationService.getText("ragfair-unable_to_find_offer_to_remove", playerOffer._id), ); @@ -277,8 +245,7 @@ export class RagfairOfferService profile.RagfairInfo.isRatingGrowing = false; const firstOfferItem = playerOffer.items[0]; - if (firstOfferItem.upd!.StackObjectsCount! > firstOfferItem.upd!.OriginalStackObjectsCount!) - { + if (firstOfferItem.upd!.StackObjectsCount! > firstOfferItem.upd!.OriginalStackObjectsCount!) { playerOffer.items[0].upd!.StackObjectsCount = firstOfferItem.upd!.OriginalStackObjectsCount; } delete playerOffer.items[0].upd!.OriginalStackObjectsCount; @@ -298,8 +265,7 @@ export class RagfairOfferService * @param items Offer items to unstack * @returns Unstacked array of items */ - protected unstackOfferItems(items: Item[]): Item[] - { + protected unstackOfferItems(items: Item[]): Item[] { const result: Item[] = []; const rootItem = items[0]; const itemDetails = this.itemHelper.getItem(rootItem._tpl); @@ -308,11 +274,9 @@ export class RagfairOfferService const totalItemCount = rootItem.upd?.StackObjectsCount ?? 1; // Items within stack tolerance, return existing data - no changes needed - if (totalItemCount <= itemMaxStackSize) - { + if (totalItemCount <= itemMaxStackSize) { // Edge case - Ensure items stack count isnt < 1 - if (items[0]?.upd?.StackObjectsCount < 1) - { + if (items[0]?.upd?.StackObjectsCount < 1) { items[0].upd.StackObjectsCount = 1; } @@ -320,15 +284,13 @@ export class RagfairOfferService } // Single item with no children e.g. ammo, use existing de-stacking code - if (items.length === 1) - { + if (items.length === 1) { return this.itemHelper.splitStack(rootItem); } // Item with children, needs special handling // Force new item to have stack size of 1 - for (let index = 0; index < totalItemCount; index++) - { + for (let index = 0; index < totalItemCount; index++) { const itemAndChildrenClone = this.cloner.clone(items); // Ensure upd object exits @@ -340,7 +302,8 @@ export class RagfairOfferService // Ensure items IDs are unique to prevent collisions when added to player inventory const reparentedItemAndChildren = this.itemHelper.reparentItemAndChildren( itemAndChildrenClone[0], - itemAndChildrenClone); + itemAndChildrenClone, + ); this.itemHelper.remapRootItemId(reparentedItemAndChildren); result.push(...reparentedItemAndChildren); diff --git a/project/src/services/RagfairPriceService.ts b/project/src/services/RagfairPriceService.ts index 4dc3f484..d8fe0a15 100644 --- a/project/src/services/RagfairPriceService.ts +++ b/project/src/services/RagfairPriceService.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { OnLoad } from "@spt/di/OnLoad"; import { HandbookHelper } from "@spt/helpers/HandbookHelper"; import { ItemHelper } from "@spt/helpers/ItemHelper"; @@ -19,13 +18,13 @@ import { ConfigServer } from "@spt/servers/ConfigServer"; import { DatabaseService } from "@spt/services/DatabaseService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { RandomUtil } from "@spt/utils/RandomUtil"; +import { inject, injectable } from "tsyringe"; /** * Stores flea prices for items as well as methods to interact with them */ @injectable() -export class RagfairPriceService implements OnLoad -{ +export class RagfairPriceService implements OnLoad { protected ragfairConfig: IRagfairConfig; protected prices: IRagfairServerPrices = { static: {}, dynamic: {} }; @@ -40,34 +39,27 @@ export class RagfairPriceService implements OnLoad @inject("RandomUtil") protected randomUtil: RandomUtil, @inject("LocalisationService") protected localisationService: LocalisationService, @inject("ConfigServer") protected configServer: ConfigServer, - ) - { + ) { this.ragfairConfig = this.configServer.getConfig(ConfigTypes.RAGFAIR); } /** * Generate static (handbook) and dynamic (prices.json) flea prices, store inside class as dictionaries */ - public async onLoad(): Promise - { + public async onLoad(): Promise { this.refreshStaticPrices(); this.refreshDynamicPrices(); } - public getRoute(): string - { + public getRoute(): string { return "RagfairPriceService"; } /** * Iterate over all items of type "Item" in db and get template price, store in cache */ - public refreshStaticPrices(): void - { - for (const item of Object.values(this.databaseService.getItems()).filter( - (x) => x._type === "Item", - )) - { + public refreshStaticPrices(): void { + for (const item of Object.values(this.databaseService.getItems()).filter((x) => x._type === "Item")) { this.prices.static[item._id] = Math.round(this.handbookHelper.getTemplatePrice(item._id)); } } @@ -75,8 +67,7 @@ export class RagfairPriceService implements OnLoad /** * Copy the prices.json data into our dynamic price dictionary */ - public refreshDynamicPrices(): void - { + public refreshDynamicPrices(): void { const pricesTable = this.databaseService.getPrices(); this.prices.dynamic = { ...this.prices.dynamic, ...pricesTable }; } @@ -87,16 +78,17 @@ export class RagfairPriceService implements OnLoad * @param tplId Item tpl id to get price for * @returns price in roubles */ - public getFleaPriceForItem(tplId: string): number - { + public getFleaPriceForItem(tplId: string): number { // Get dynamic price (templates/prices), if that doesnt exist get price from static array (templates/handbook) let itemPrice = this.getDynamicPriceForItem(tplId) || this.getStaticPriceForItem(tplId); - if (itemPrice === undefined) - { + if (itemPrice === undefined) { const itemFromDb = this.itemHelper.getItem(tplId); const itemName = itemFromDb[0] ? itemFromDb[1]?._name : ""; this.logger.warning( - this.localisationService.getText("ragfair-unable_to_find_item_price_for_item_in_flea_handbook", { tpl: tplId, name: itemName }), + this.localisationService.getText("ragfair-unable_to_find_item_price_for_item_in_flea_handbook", { + tpl: tplId, + name: itemName, + }), ); } @@ -111,17 +103,14 @@ export class RagfairPriceService implements OnLoad * @param offerItems offer item + children to process * @returns Rouble price */ - public getFleaPriceForOfferItems(offerItems: Item[]): number - { + public getFleaPriceForOfferItems(offerItems: Item[]): number { // Preset weapons take the direct prices.json value, otherwise they're massivly inflated - if (this.itemHelper.isOfBaseclass(offerItems[0]._tpl, BaseClasses.WEAPON)) - { + if (this.itemHelper.isOfBaseclass(offerItems[0]._tpl, BaseClasses.WEAPON)) { return this.getFleaPriceForItem(offerItems[0]._tpl); } let totalPrice = 0; - for (const item of offerItems) - { + for (const item of offerItems) { totalPrice += this.getFleaPriceForItem(item._tpl); } @@ -133,11 +122,9 @@ export class RagfairPriceService implements OnLoad * @param itemTpl item template id to look up * @returns price in roubles */ - public getDynamicPriceForItem(itemTpl: string): number - { + public getDynamicPriceForItem(itemTpl: string): number { // If the price doesn't exist in the cache yet, try to find it - if (!this.prices.dynamic[itemTpl]) - { + if (!this.prices.dynamic[itemTpl]) { this.prices.dynamic[itemTpl] = this.databaseService.getPrices()[itemTpl]; } @@ -149,15 +136,12 @@ export class RagfairPriceService implements OnLoad * @param itemTpl item template id to look up * @returns price in roubles */ - public getStaticPriceForItem(itemTpl: string): number - { + public getStaticPriceForItem(itemTpl: string): number { // If the price doesn't exist in the cache yet, try to find it - if (!this.prices.static[itemTpl]) - { + if (!this.prices.static[itemTpl]) { // Store the price in the cache only if it exists const itemPrice = Math.round(this.handbookHelper.getTemplatePrice(itemTpl)); - if (itemPrice !== 0) - { + if (itemPrice !== 0) { this.prices.static[itemTpl] = itemPrice; } } @@ -170,8 +154,7 @@ export class RagfairPriceService implements OnLoad * This will refresh the caches prior to building the output * @returns Dictionary of item tpls and rouble cost */ - public getAllFleaPrices(): Record - { + public getAllFleaPrices(): Record { // Refresh the caches so we include any newly added custom items this.refreshDynamicPrices(); this.refreshStaticPrices(); @@ -181,8 +164,7 @@ export class RagfairPriceService implements OnLoad return { ...this.prices.dynamic, ...this.prices.static }; } - public getAllStaticPrices(): Record - { + public getAllStaticPrices(): Record { // Refresh the cache so we include any newly added custom items this.refreshStaticPrices(); @@ -195,8 +177,7 @@ export class RagfairPriceService implements OnLoad * @param b numerical value b * @returns different in percent */ - protected getPriceDifference(a: number, b: number): number - { + protected getPriceDifference(a: number, b: number): number { return (100 * a) / (a + b); } @@ -205,12 +186,10 @@ export class RagfairPriceService implements OnLoad * @param barterScheme * @returns Rouble price */ - public getBarterPrice(barterScheme: IBarterScheme[]): number - { + public getBarterPrice(barterScheme: IBarterScheme[]): number { let price = 0; - for (const item of barterScheme) - { + for (const item of barterScheme) { price += this.getStaticPriceForItem(item._tpl) * item.count; } @@ -224,17 +203,14 @@ export class RagfairPriceService implements OnLoad * @param isPackOffer Price is for a pack type offer * @returns cost of item in desired currency */ - public getDynamicOfferPriceForOffer(offerItems: Item[], desiredCurrency: string, isPackOffer: boolean): number - { + public getDynamicOfferPriceForOffer(offerItems: Item[], desiredCurrency: string, isPackOffer: boolean): number { // Price to return. let price = 0; // Iterate over each item in the offer. - for (const item of offerItems) - { + for (const item of offerItems) { // Skip over armour inserts as those are not factored into item prices. - if (this.itemHelper.isOfBaseclass(item._tpl, BaseClasses.BUILT_IN_INSERTS)) - { + if (this.itemHelper.isOfBaseclass(item._tpl, BaseClasses.BUILT_IN_INSERTS)) { continue; } @@ -242,10 +218,9 @@ export class RagfairPriceService implements OnLoad // Check if the item is a weapon preset. if ( - item?.upd?.sptPresetId - && this.presetHelper.isPresetBaseClass(item.upd.sptPresetId, BaseClasses.WEAPON) - ) - { + item?.upd?.sptPresetId && + this.presetHelper.isPresetBaseClass(item.upd.sptPresetId, BaseClasses.WEAPON) + ) { // This is a weapon preset, which has it's own price calculation that takes into account the mods in the // preset. Since we've already calculated the price for the preset entire preset in // `getDynamicItemPrice`, we can skip the rest of the items in the offer. @@ -270,63 +245,53 @@ export class RagfairPriceService implements OnLoad item?: Item, offerItems?: Item[], isPackOffer?: boolean, - ): number - { + ): number { let isPreset = false; let price = this.getFleaPriceForItem(itemTemplateId); // Adjust price if below handbook price, based on config. - if (this.ragfairConfig.dynamic.offerAdjustment.adjustPriceWhenBelowHandbookPrice) - { + if (this.ragfairConfig.dynamic.offerAdjustment.adjustPriceWhenBelowHandbookPrice) { price = this.adjustPriceIfBelowHandbook(price, itemTemplateId); } // Use trader price if higher, based on config. - if (this.ragfairConfig.dynamic.useTraderPriceForOffersIfHigher) - { + if (this.ragfairConfig.dynamic.useTraderPriceForOffersIfHigher) { const traderPrice = this.traderHelper.getHighestSellToTraderPrice(itemTemplateId); - if (traderPrice > price) - { + if (traderPrice > price) { price = traderPrice; } } // Prices for weapon presets are handled differently. if ( - item?.upd?.sptPresetId - && offerItems - && this.presetHelper.isPresetBaseClass(item.upd.sptPresetId, BaseClasses.WEAPON) - ) - { + item?.upd?.sptPresetId && + offerItems && + this.presetHelper.isPresetBaseClass(item.upd.sptPresetId, BaseClasses.WEAPON) + ) { price = this.getWeaponPresetPrice(item, offerItems, price); isPreset = true; } // Check for existence of manual price adjustment multiplier const multiplier = this.ragfairConfig.dynamic.itemPriceMultiplier[itemTemplateId]; - if (multiplier) - { + if (multiplier) { price *= multiplier; } // The quality of the item affects the price. - if (item) - { + if (item) { const qualityModifier = this.itemHelper.getItemQualityModifier(item); price *= qualityModifier; } // Make adjustments for unreasonably priced items. - for (const baseClassTemplateId of Object.keys(this.ragfairConfig.dynamic.unreasonableModPrices)) - { - if (this.itemHelper.isOfBaseclass(itemTemplateId, baseClassTemplateId)) - { + for (const baseClassTemplateId of Object.keys(this.ragfairConfig.dynamic.unreasonableModPrices)) { + if (this.itemHelper.isOfBaseclass(itemTemplateId, baseClassTemplateId)) { // Found an unreasonable price type. - const unreasonableModifier: IUnreasonableModPrices - = this.ragfairConfig.dynamic.unreasonableModPrices[baseClassTemplateId]; + const unreasonableModifier: IUnreasonableModPrices = + this.ragfairConfig.dynamic.unreasonableModPrices[baseClassTemplateId]; - if (unreasonableModifier.enabled) - { + if (unreasonableModifier.enabled) { price = this.adjustUnreasonablePrice( this.databaseService.getHandbook().Items, unreasonableModifier, @@ -343,13 +308,11 @@ export class RagfairPriceService implements OnLoad // Convert to different currency if required. const roublesId = Money.ROUBLES; - if (desiredCurrency !== roublesId) - { + if (desiredCurrency !== roublesId) { price = this.handbookHelper.fromRUB(price, desiredCurrency); } - if (price < 1) - { + if (price < 1) { return 1; } return price; @@ -368,20 +331,16 @@ export class RagfairPriceService implements OnLoad unreasonableItemChange: IUnreasonableModPrices, itemTpl: string, price: number, - ): number - { + ): number { const itemHandbookPrice = handbookPrices.find((handbookItem) => handbookItem.Id === itemTpl); - if (!itemHandbookPrice) - { + if (!itemHandbookPrice) { return price; } // Flea price is over handbook price - if (price > itemHandbookPrice.Price * unreasonableItemChange.handbookPriceOverMultiplier) - { + if (price > itemHandbookPrice.Price * unreasonableItemChange.handbookPriceOverMultiplier) { // Skip extreme values - if (price <= 1) - { + if (price <= 1) { return price; } @@ -398,17 +357,14 @@ export class RagfairPriceService implements OnLoad * @param isPack Offer is a pack * @returns MinMax values */ - protected getOfferTypeRangeValues(isPreset: boolean, isPack: boolean): MinMax - { + protected getOfferTypeRangeValues(isPreset: boolean, isPack: boolean): MinMax { // Use different min/max values if the item is a preset or pack const priceRanges = this.ragfairConfig.dynamic.priceRanges; - if (isPreset) - { + if (isPreset) { return priceRanges.preset; } - if (isPack) - { + if (isPack) { return priceRanges.pack; } @@ -421,18 +377,16 @@ export class RagfairPriceService implements OnLoad * @param itemTpl item template Id being checked * @returns adjusted price value in roubles */ - protected adjustPriceIfBelowHandbook(itemPrice: number, itemTpl: string): number - { + protected adjustPriceIfBelowHandbook(itemPrice: number, itemTpl: string): number { const itemHandbookPrice = this.getStaticPriceForItem(itemTpl); const priceDifferencePercent = this.getPriceDifference(itemHandbookPrice, itemPrice); // Only adjust price if difference is > a percent AND item price passes threshold set in config if ( - priceDifferencePercent - > this.ragfairConfig.dynamic.offerAdjustment.maxPriceDifferenceBelowHandbookPercent - && itemPrice >= this.ragfairConfig.dynamic.offerAdjustment.priceThreshholdRub - ) - { + priceDifferencePercent > + this.ragfairConfig.dynamic.offerAdjustment.maxPriceDifferenceBelowHandbookPercent && + itemPrice >= this.ragfairConfig.dynamic.offerAdjustment.priceThreshholdRub + ) { // const itemDetails = this.itemHelper.getItem(itemTpl); // this.logger.debug(`item below handbook price ${itemDetails[1]._name} handbook: ${itemHandbookPrice} flea: ${itemPrice} ${priceDifferencePercent}%`); return Math.round(itemHandbookPrice * this.ragfairConfig.dynamic.offerAdjustment.handbookPriceMultipier); @@ -447,8 +401,7 @@ export class RagfairPriceService implements OnLoad * @param rangeValues min and max to adjust price by * @returns multiplied price */ - protected randomiseOfferPrice(existingPrice: number, rangeValues: MinMax): number - { + protected randomiseOfferPrice(existingPrice: number, rangeValues: MinMax): number { // Multiply by 100 to get 2 decimal places of precision const multiplier = this.randomUtil.getBiasedRandomNumber(rangeValues.min * 100, rangeValues.max * 100, 2, 2); @@ -463,12 +416,10 @@ export class RagfairPriceService implements OnLoad * @param existingPrice price of existing base weapon * @returns price of weapon in roubles */ - protected getWeaponPresetPrice(weaponRootItem: Item, weaponWithChildren: Item[], existingPrice: number): number - { + protected getWeaponPresetPrice(weaponRootItem: Item, weaponWithChildren: Item[], existingPrice: number): number { // Get the default preset for this weapon const presetResult = this.getWeaponPreset(weaponRootItem); - if (presetResult.isDefault) - { + if (presetResult.isDefault) { return this.getFleaPriceForItem(weaponRootItem._tpl); } @@ -479,15 +430,13 @@ export class RagfairPriceService implements OnLoad // Add up extra mods price let extraModsPrice = 0; - for (const mod of newOrReplacedModsInPresetVsDefault) - { + for (const mod of newOrReplacedModsInPresetVsDefault) { // Use handbook or trader price, whatever is higher (dont use dynamic flea price as purchased item cannot be relisted) extraModsPrice += this.getHighestHandbookOrTraderPriceAsRouble(mod._tpl); } // Only deduct cost of replaced mods if there's replaced/new mods - if (newOrReplacedModsInPresetVsDefault.length >= 1) - { + if (newOrReplacedModsInPresetVsDefault.length >= 1) { // Add up cost of mods replaced const modsReplacedByNewMods = newOrReplacedModsInPresetVsDefault.filter((x) => presetResult.preset._items.some((y) => y.slotId === x.slotId), @@ -495,8 +444,7 @@ export class RagfairPriceService implements OnLoad // Add up replaced mods price let replacedModsPrice = 0; - for (const replacedMod of modsReplacedByNewMods) - { + for (const replacedMod of modsReplacedByNewMods) { replacedModsPrice += this.getHighestHandbookOrTraderPriceAsRouble(replacedMod._tpl); } @@ -513,12 +461,10 @@ export class RagfairPriceService implements OnLoad * @param itemTpl Item to get highest price of * @returns rouble cost */ - protected getHighestHandbookOrTraderPriceAsRouble(itemTpl: string): number - { + protected getHighestHandbookOrTraderPriceAsRouble(itemTpl: string): number { let price = this.getStaticPriceForItem(itemTpl); const traderPrice = this.traderHelper.getHighestSellToTraderPrice(itemTpl); - if (traderPrice > price) - { + if (traderPrice > price) { price = traderPrice; } @@ -531,22 +477,17 @@ export class RagfairPriceService implements OnLoad * @param presets weapon presets to choose from * @returns Default preset object */ - protected getWeaponPreset(weapon: Item): { isDefault: boolean, preset: IPreset } - { + protected getWeaponPreset(weapon: Item): { isDefault: boolean; preset: IPreset } { const defaultPreset = this.presetHelper.getDefaultPreset(weapon._tpl); - if (defaultPreset) - { + if (defaultPreset) { return { isDefault: true, preset: defaultPreset }; } const nonDefaultPresets = this.presetHelper.getPresets(weapon._tpl); - if (nonDefaultPresets.length === 1) - { + if (nonDefaultPresets.length === 1) { this.logger.debug( `Item Id: ${weapon._tpl} has no default encyclopedia entry but only one preset (${nonDefaultPresets[0]._name}), choosing preset (${nonDefaultPresets[0]._name})`, ); - } - else - { + } else { this.logger.debug( `Item Id: ${weapon._tpl} has no default encyclopedia entry, choosing first preset (${nonDefaultPresets[0]._name}) of ${nonDefaultPresets.length}`, ); diff --git a/project/src/services/RagfairRequiredItemsService.ts b/project/src/services/RagfairRequiredItemsService.ts index 7e67d1c3..9601bd94 100644 --- a/project/src/services/RagfairRequiredItemsService.ts +++ b/project/src/services/RagfairRequiredItemsService.ts @@ -1,45 +1,36 @@ -import { inject, injectable } from "tsyringe"; import { PaymentHelper } from "@spt/helpers/PaymentHelper"; import { IRagfairOffer } from "@spt/models/eft/ragfair/IRagfairOffer"; import { ILogger } from "@spt/models/spt/utils/ILogger"; import { RagfairOfferService } from "@spt/services/RagfairOfferService"; +import { inject, injectable } from "tsyringe"; @injectable() -export class RagfairRequiredItemsService -{ +export class RagfairRequiredItemsService { protected requiredItemsCache = {}; constructor( @inject("PrimaryLogger") protected logger: ILogger, @inject("PaymentHelper") protected paymentHelper: PaymentHelper, @inject("RagfairOfferService") protected ragfairOfferService: RagfairOfferService, - ) - {} + ) {} - public getRequiredItemsById(searchId: string): IRagfairOffer[] - { + public getRequiredItemsById(searchId: string): IRagfairOffer[] { return Array.from(this.requiredItemsCache[searchId] ?? {}) || []; } - public buildRequiredItemTable(): void - { + public buildRequiredItemTable(): void { const requiredItems = {}; - const getRequiredItems = (id: string) => - { - if (!(id in requiredItems)) - { + const getRequiredItems = (id: string) => { + if (!(id in requiredItems)) { requiredItems[id] = new Set(); } return requiredItems[id]; }; - for (const offer of this.ragfairOfferService.getOffers()) - { - for (const requirement of offer.requirements) - { - if (this.paymentHelper.isMoneyTpl(requirement._tpl)) - { + for (const offer of this.ragfairOfferService.getOffers()) { + for (const requirement of offer.requirements) { + if (this.paymentHelper.isMoneyTpl(requirement._tpl)) { // This would just be too noisy. continue; } diff --git a/project/src/services/RagfairTaxService.ts b/project/src/services/RagfairTaxService.ts index f647db25..77b884ef 100644 --- a/project/src/services/RagfairTaxService.ts +++ b/project/src/services/RagfairTaxService.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { ItemHelper } from "@spt/helpers/ItemHelper"; import { IPmcData } from "@spt/models/eft/common/IPmcData"; import { Item } from "@spt/models/eft/common/tables/IItem"; @@ -8,10 +7,10 @@ import { BonusType } from "@spt/models/enums/BonusType"; import { ILogger } from "@spt/models/spt/utils/ILogger"; import { DatabaseService } from "@spt/services/DatabaseService"; import { RagfairPriceService } from "@spt/services/RagfairPriceService"; +import { inject, injectable } from "tsyringe"; @injectable() -export class RagfairTaxService -{ +export class RagfairTaxService { protected playerOfferTaxCache: Record = {}; constructor( @@ -19,21 +18,17 @@ export class RagfairTaxService @inject("DatabaseService") protected databaseService: DatabaseService, @inject("RagfairPriceService") protected ragfairPriceService: RagfairPriceService, @inject("ItemHelper") protected itemHelper: ItemHelper, - ) - {} + ) {} - public storeClientOfferTaxValue(sessionId: string, offer: IStorePlayerOfferTaxAmountRequestData): void - { + public storeClientOfferTaxValue(sessionId: string, offer: IStorePlayerOfferTaxAmountRequestData): void { this.playerOfferTaxCache[offer.id] = offer; } - public clearStoredOfferTaxById(offerIdToRemove: string): void - { + public clearStoredOfferTaxById(offerIdToRemove: string): void { delete this.playerOfferTaxCache[offerIdToRemove]; } - public getStoredClientOfferTaxValueById(offerIdToGet: string): IStorePlayerOfferTaxAmountRequestData - { + public getStoredClientOfferTaxValueById(offerIdToGet: string): IStorePlayerOfferTaxAmountRequestData { return this.playerOfferTaxCache[offerIdToGet]; } @@ -53,15 +48,12 @@ export class RagfairTaxService requirementsValue: number, offerItemCount: number, sellInOnePiece: boolean, - ): number - { - if (!requirementsValue) - { + ): number { + if (!requirementsValue) { return 0; } - if (!offerItemCount) - { + if (!offerItemCount) { return 0; } @@ -77,12 +69,9 @@ export class RagfairTaxService let itemPriceMult = Math.log10(itemWorth / requirementsPrice); let requirementPriceMult = Math.log10(requirementsPrice / itemWorth); - if (requirementsPrice >= itemWorth) - { + if (requirementsPrice >= itemWorth) { requirementPriceMult = requirementPriceMult ** 1.08; - } - else - { + } else { itemPriceMult = itemPriceMult ** 1.08; } @@ -92,8 +81,8 @@ export class RagfairTaxService const hideoutFleaTaxDiscountBonus = pmcData.Bonuses.find((b) => b.type === BonusType.RAGFAIR_COMMISSION); const taxDiscountPercent = hideoutFleaTaxDiscountBonus ? Math.abs(hideoutFleaTaxDiscountBonus!.value ?? 0) : 0; - const tax - = itemWorth * itemTaxMult * itemPriceMult + requirementsPrice * requirementTaxMult * requirementPriceMult; + const tax = + itemWorth * itemTaxMult * itemPriceMult + requirementsPrice * requirementTaxMult * requirementPriceMult; const discountedTax = tax * (1.0 - taxDiscountPercent / 100.0); const itemComissionMult = itemTemplate._props.RagFairCommissionModifier ? itemTemplate._props.RagFairCommissionModifier @@ -118,21 +107,16 @@ export class RagfairTaxService itemCount: number, pmcData: IPmcData, isRootItem = true, - ): number - { + ): number { let worth = this.ragfairPriceService.getFleaPriceForItem(item._tpl); // In client, all item slots are traversed and any items contained within have their values added - if (isRootItem) - { + if (isRootItem) { // Since we get a flat list of all child items, we only want to recurse from parent item const itemChildren = this.itemHelper.findAndReturnChildrenAsItems(pmcData.Inventory.items, item._id); - if (itemChildren.length > 1) - { - for (const child of itemChildren) - { - if (child._id === item._id) - { + if (itemChildren.length > 1) { + for (const child of itemChildren) { + if (child._id === item._id) { continue; } @@ -147,46 +131,39 @@ export class RagfairTaxService } } - if ("Dogtag" in item.upd!) - { + if ("Dogtag" in item.upd!) { worth *= item.upd!.Dogtag!.Level; } - if ("Key" in item.upd! && (itemTemplate._props.MaximumNumberOfUsage ?? 0) > 0) - { - worth - = (worth / itemTemplate._props.MaximumNumberOfUsage!) - * (itemTemplate._props.MaximumNumberOfUsage! - item.upd!.Key!.NumberOfUsages); + if ("Key" in item.upd! && (itemTemplate._props.MaximumNumberOfUsage ?? 0) > 0) { + worth = + (worth / itemTemplate._props.MaximumNumberOfUsage!) * + (itemTemplate._props.MaximumNumberOfUsage! - item.upd!.Key!.NumberOfUsages); } - if ("Resource" in item.upd! && itemTemplate._props.MaxResource! > 0) - { + if ("Resource" in item.upd! && itemTemplate._props.MaxResource! > 0) { worth = worth * 0.1 + ((worth * 0.9) / itemTemplate._props.MaxResource!) * item.upd.Resource!.Value; } - if ("SideEffect" in item.upd! && itemTemplate._props.MaxResource! > 0) - { + if ("SideEffect" in item.upd! && itemTemplate._props.MaxResource! > 0) { worth = worth * 0.1 + ((worth * 0.9) / itemTemplate._props.MaxResource!) * item.upd.SideEffect!.Value; } - if ("MedKit" in item.upd! && itemTemplate._props.MaxHpResource! > 0) - { + if ("MedKit" in item.upd! && itemTemplate._props.MaxHpResource! > 0) { worth = (worth / itemTemplate._props.MaxHpResource!) * item.upd.MedKit!.HpResource; } - if ("FoodDrink" in item.upd! && itemTemplate._props.MaxResource! > 0) - { + if ("FoodDrink" in item.upd! && itemTemplate._props.MaxResource! > 0) { worth = (worth / itemTemplate._props.MaxResource!) * item.upd.FoodDrink!.HpPercent; } - if ("Repairable" in item.upd! && itemTemplate._props.armorClass > 0) - { + if ("Repairable" in item.upd! && itemTemplate._props.armorClass > 0) { const num2 = 0.01 * 0.0 ** item.upd.Repairable!.MaxDurability; - worth - = worth * (item.upd.Repairable!.MaxDurability / itemTemplate._props.Durability! - num2) - - Math.floor( - itemTemplate._props.RepairCost! - * (item.upd.Repairable!.MaxDurability - item.upd.Repairable!.Durability), + worth = + worth * (item.upd.Repairable!.MaxDurability / itemTemplate._props.Durability! - num2) - + Math.floor( + itemTemplate._props.RepairCost! * + (item.upd.Repairable!.MaxDurability - item.upd.Repairable!.Durability), ); } diff --git a/project/src/services/RaidTimeAdjustmentService.ts b/project/src/services/RaidTimeAdjustmentService.ts index 3d480f55..c15fcd96 100644 --- a/project/src/services/RaidTimeAdjustmentService.ts +++ b/project/src/services/RaidTimeAdjustmentService.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { ApplicationContext } from "@spt/context/ApplicationContext"; import { ContextVariableType } from "@spt/context/ContextVariableType"; import { WeightedRandomHelper } from "@spt/helpers/WeightedRandomHelper"; @@ -6,20 +5,16 @@ import { ILocationBase } from "@spt/models/eft/common/ILocationBase"; import { IGetRaidTimeRequest } from "@spt/models/eft/game/IGetRaidTimeRequest"; import { ExtractChange, IGetRaidTimeResponse } from "@spt/models/eft/game/IGetRaidTimeResponse"; import { ConfigTypes } from "@spt/models/enums/ConfigTypes"; -import { - ILocationConfig, - IScavRaidTimeLocationSettings, - LootMultiplier, -} from "@spt/models/spt/config/ILocationConfig"; +import { ILocationConfig, IScavRaidTimeLocationSettings, LootMultiplier } from "@spt/models/spt/config/ILocationConfig"; import { IRaidChanges } from "@spt/models/spt/location/IRaidChanges"; 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 { inject, injectable } from "tsyringe"; @injectable() -export class RaidTimeAdjustmentService -{ +export class RaidTimeAdjustmentService { protected locationConfig: ILocationConfig; constructor( @@ -29,8 +24,7 @@ export class RaidTimeAdjustmentService @inject("WeightedRandomHelper") protected weightedRandomHelper: WeightedRandomHelper, @inject("ApplicationContext") protected applicationContext: ApplicationContext, @inject("ConfigServer") protected configServer: ConfigServer, - ) - { + ) { this.locationConfig = this.configServer.getConfig(ConfigTypes.LOCATION); } @@ -40,8 +34,7 @@ export class RaidTimeAdjustmentService * @param raidAdjustments Changes to process on map * @param mapBase Map to adjust */ - public makeAdjustmentsToMap(raidAdjustments: IRaidChanges, mapBase: ILocationBase): void - { + public makeAdjustmentsToMap(raidAdjustments: IRaidChanges, mapBase: ILocationBase): void { this.logger.debug( `Adjusting dynamic loot multipliers to ${raidAdjustments.dynamicLootPercent}% and static loot multipliers to ${raidAdjustments.staticLootPercent}% of original`, ); @@ -51,8 +44,7 @@ export class RaidTimeAdjustmentService this.adjustLootMultipliers(this.locationConfig.staticLootMultiplier, raidAdjustments.staticLootPercent); const mapSettings = this.getMapSettings(mapBase.Id); - if (mapSettings.adjustWaves) - { + if (mapSettings.adjustWaves) { // Make alterations to bot spawn waves now player is simulated spawning later this.adjustWaves(mapBase, raidAdjustments); } @@ -63,10 +55,8 @@ export class RaidTimeAdjustmentService * @param mapLootMultiplers Multiplers to adjust * @param loosePercent Percent to change values to */ - protected adjustLootMultipliers(mapLootMultiplers: LootMultiplier, loosePercent: number): void - { - for (const key in mapLootMultiplers) - { + protected adjustLootMultipliers(mapLootMultiplers: LootMultiplier, loosePercent: number): void { + for (const key in mapLootMultiplers) { mapLootMultiplers[key] = this.randomUtil.getPercentOfValue(mapLootMultiplers[key], loosePercent); } } @@ -76,15 +66,13 @@ export class RaidTimeAdjustmentService * @param mapBase map to adjust * @param raidAdjustments Map adjustments */ - protected adjustWaves(mapBase: ILocationBase, raidAdjustments: IRaidChanges): void - { + protected adjustWaves(mapBase: ILocationBase, raidAdjustments: IRaidChanges): void { // Remove waves that spawned before the player joined const originalWaveCount = mapBase.waves.length; mapBase.waves = mapBase.waves.filter((x) => x.time_max > raidAdjustments.simulatedRaidStartSeconds); // Adjust wave min/max times to match new simulated start - for (const wave of mapBase.waves) - { + for (const wave of mapBase.waves) { // Dont let time fall below 0 wave.time_min -= Math.max(raidAdjustments.simulatedRaidStartSeconds, 0); wave.time_max -= Math.max(raidAdjustments.simulatedRaidStartSeconds, 0); @@ -103,8 +91,7 @@ export class RaidTimeAdjustmentService * @param request Raid adjustment request * @returns Response to send to client */ - public getRaidAdjustments(sessionId: string, request: IGetRaidTimeRequest): IGetRaidTimeResponse - { + public getRaidAdjustments(sessionId: string, request: IGetRaidTimeRequest): IGetRaidTimeResponse { const globals = this.databaseService.getGlobals(); const mapBase: ILocationBase = this.databaseService.getLocation(request.Location.toLowerCase()).base; const baseEscapeTimeMinutes = mapBase.EscapeTimeLimit; @@ -118,8 +105,7 @@ export class RaidTimeAdjustmentService }; // Pmc raid, send default - if (request.Side.toLowerCase() === "pmc") - { + if (request.Side.toLowerCase() === "pmc") { return result; } @@ -127,8 +113,7 @@ export class RaidTimeAdjustmentService const mapSettings = this.getMapSettings(request.Location); // Chance of reducing raid time for scav, not guaranteed - if (!this.randomUtil.getChance100(mapSettings.reducedChancePercent)) - { + if (!this.randomUtil.getChance100(mapSettings.reducedChancePercent)) { // Send default return result; } @@ -147,8 +132,7 @@ export class RaidTimeAdjustmentService // Time player spawns into the raid if it was online const simulatedRaidStartTimeMinutes = baseEscapeTimeMinutes - newRaidTimeMinutes; - if (mapSettings.reduceLootByPercent) - { + if (mapSettings.reduceLootByPercent) { // Store time reduction percent in app context so loot gen can pick it up later this.applicationContext.addValue(ContextVariableType.RAID_ADJUSTMENTS, { dynamicLootPercent: Math.max(raidTimeRemainingPercent, mapSettings.minDynamicLootPercent), @@ -171,8 +155,7 @@ export class RaidTimeAdjustmentService ); const exitAdjustments = this.getExitAdjustments(mapBase, newRaidTimeMinutes); - if (exitAdjustments) - { + if (exitAdjustments) { result.ExitChanges.push(...exitAdjustments); } @@ -184,11 +167,9 @@ export class RaidTimeAdjustmentService * @param location Map Location e.g. bigmap * @returns IScavRaidTimeLocationSettings */ - protected getMapSettings(location: string): IScavRaidTimeLocationSettings - { + protected getMapSettings(location: string): IScavRaidTimeLocationSettings { const mapSettings = this.locationConfig.scavRaidTimeSettings.maps[location.toLowerCase()]; - if (!mapSettings) - { + if (!mapSettings) { this.logger.warning(`Unable to find scav raid time settings for map: ${location}, using defaults`); return this.locationConfig.scavRaidTimeSettings.maps.default; } @@ -202,14 +183,11 @@ export class RaidTimeAdjustmentService * @param newRaidTimeMinutes How long raid is in minutes * @returns List of exit changes to send to client */ - protected getExitAdjustments(mapBase: ILocationBase, newRaidTimeMinutes: number): ExtractChange[] | undefined - { + protected getExitAdjustments(mapBase: ILocationBase, newRaidTimeMinutes: number): ExtractChange[] | undefined { const result: ExtractChange[] = []; // Adjust train exits only - for (const exit of mapBase.exits) - { - if (exit.PassageRequirement !== "Train") - { + for (const exit of mapBase.exits) { + if (exit.PassageRequirement !== "Train") { continue; } @@ -241,17 +219,16 @@ export class RaidTimeAdjustmentService // // I added 2 seconds just to be safe... // - const trainArrivalDelaySeconds - = this.locationConfig.scavRaidTimeSettings.settings.trainArrivalDelayObservedSeconds; + const trainArrivalDelaySeconds = + this.locationConfig.scavRaidTimeSettings.settings.trainArrivalDelayObservedSeconds; // Determine the earliest possible time in the raid when the train would leave - const earliestPossibleDepartureMinutes - = (exit.MinTime + exit.Count + exit.ExfiltrationTime + trainArrivalDelaySeconds) / 60; + const earliestPossibleDepartureMinutes = + (exit.MinTime + exit.Count + exit.ExfiltrationTime + trainArrivalDelaySeconds) / 60; // If raid is after last moment train can leave, assume train has already left, disable extract const mostPossibleTimeRemainingAfterDeparture = mapBase.EscapeTimeLimit - earliestPossibleDepartureMinutes; - if (newRaidTimeMinutes < mostPossibleTimeRemainingAfterDeparture) - { + if (newRaidTimeMinutes < mostPossibleTimeRemainingAfterDeparture) { exitChange.Chance = 0; this.logger.debug( diff --git a/project/src/services/RepairService.ts b/project/src/services/RepairService.ts index 396fd83f..f8146d11 100644 --- a/project/src/services/RepairService.ts +++ b/project/src/services/RepairService.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { ItemHelper } from "@spt/helpers/ItemHelper"; import { ProfileHelper } from "@spt/helpers/ProfileHelper"; import { RepairHelper } from "@spt/helpers/RepairHelper"; @@ -24,10 +23,10 @@ import { DatabaseService } from "@spt/services/DatabaseService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { PaymentService } from "@spt/services/PaymentService"; import { RandomUtil } from "@spt/utils/RandomUtil"; +import { inject, injectable } from "tsyringe"; @injectable() -export class RepairService -{ +export class RepairService { protected repairConfig: IRepairConfig; constructor( @inject("PrimaryLogger") protected logger: ILogger, @@ -41,8 +40,7 @@ export class RepairService @inject("RepairHelper") protected repairHelper: RepairHelper, @inject("LocalisationService") protected localisationService: LocalisationService, @inject("ConfigServer") protected configServer: ConfigServer, - ) - { + ) { this.repairConfig = this.configServer.getConfig(ConfigTypes.REPAIR); } @@ -59,18 +57,20 @@ export class RepairService pmcData: IPmcData, repairItemDetails: RepairItem, traderId: string, - ): RepairDetails - { + ): RepairDetails { const itemToRepair = pmcData.Inventory.items.find((item) => item._id === repairItemDetails._id); - if (!itemToRepair) - { - throw new Error(this.localisationService.getText("repair-unable_to_find_item_in_inventory_cant_repair", repairItemDetails._id)); + if (!itemToRepair) { + throw new Error( + this.localisationService.getText( + "repair-unable_to_find_item_in_inventory_cant_repair", + repairItemDetails._id, + ), + ); } const priceCoef = this.traderHelper.getLoyaltyLevel(traderId, pmcData).repair_price_coef; const traderRepairDetails = this.traderHelper.getTrader(traderId, sessionID)?.repair; - if (!traderRepairDetails) - { + if (!traderRepairDetails) { throw new Error(this.localisationService.getText("repair-unable_to_find_trader_details_by_id", traderId)); } const repairQualityMultiplier = Number(traderRepairDetails.quality); @@ -92,9 +92,10 @@ export class RepairService // get repair price const itemRepairCost = items[itemToRepair._tpl]._props.RepairCost; - if (!itemRepairCost) - { - throw new Error(this.localisationService.getText("repair-unable_to_find_item_repair_cost", itemToRepair._tpl)); + if (!itemRepairCost) { + throw new Error( + this.localisationService.getText("repair-unable_to_find_item_repair_cost", itemToRepair._tpl), + ); } const repairCost = Math.round( itemRepairCost * repairItemDetails.count * repairRate * this.repairConfig.priceMultiplier, @@ -128,8 +129,7 @@ export class RepairService repairCost: number, traderId: string, output: IItemEventRouterResponse, - ): void - { + ): void { const options: IProcessBuyTradeRequestData = { scheme_items: [ { @@ -154,18 +154,15 @@ export class RepairService * @param repairDetails details of item repaired, cost/item * @param pmcData Profile to add points to */ - public addRepairSkillPoints(sessionId: string, repairDetails: RepairDetails, pmcData: IPmcData): void - { + public addRepairSkillPoints(sessionId: string, repairDetails: RepairDetails, pmcData: IPmcData): void { // Handle kit repair of weapon if ( - repairDetails.repairedByKit - && this.itemHelper.isOfBaseclass(repairDetails.repairedItem._tpl, BaseClasses.WEAPON) - ) - { + repairDetails.repairedByKit && + this.itemHelper.isOfBaseclass(repairDetails.repairedItem._tpl, BaseClasses.WEAPON) + ) { const skillPoints = this.getWeaponRepairSkillPoints(repairDetails); - if (skillPoints > 0) - { + if (skillPoints > 0) { this.logger.debug(`Added: ${skillPoints} WEAPON_TREATMENT skill`); this.profileHelper.addSkillPointsToPlayer(pmcData, SkillTypes.WEAPON_TREATMENT, skillPoints, true); } @@ -173,16 +170,14 @@ export class RepairService // Handle kit repair of armor if ( - repairDetails.repairedByKit - && this.itemHelper.isOfBaseclasses(repairDetails.repairedItem._tpl, [ + repairDetails.repairedByKit && + this.itemHelper.isOfBaseclasses(repairDetails.repairedItem._tpl, [ BaseClasses.ARMOR_PLATE, BaseClasses.BUILT_IN_INSERTS, ]) - ) - { + ) { const itemDetails = this.itemHelper.getItem(repairDetails.repairedItem._tpl); - if (!itemDetails[0]) - { + if (!itemDetails[0]) { // No item found this.logger.error( this.localisationService.getText( @@ -196,12 +191,16 @@ export class RepairService const isHeavyArmor = itemDetails[1]._props.ArmorType === "Heavy"; const vestSkillToLevel = isHeavyArmor ? SkillTypes.HEAVY_VESTS : SkillTypes.LIGHT_VESTS; - if (!repairDetails.repairPoints) - { - throw new Error(this.localisationService.getText("repair-item_has_no_repair_points", repairDetails.repairedItem._tpl)); + if (!repairDetails.repairPoints) { + throw new Error( + this.localisationService.getText( + "repair-item_has_no_repair_points", + repairDetails.repairedItem._tpl, + ), + ); } - const pointsToAddToVestSkill - = repairDetails.repairPoints * this.repairConfig.armorKitSkillPointGainPerRepairPointMultiplier; + const pointsToAddToVestSkill = + repairDetails.repairPoints * this.repairConfig.armorKitSkillPointGainPerRepairPointMultiplier; this.logger.debug(`Added: ${pointsToAddToVestSkill} ${vestSkillToLevel} skill`); this.profileHelper.addSkillPointsToPlayer(pmcData, vestSkillToLevel, pointsToAddToVestSkill); @@ -209,17 +208,14 @@ export class RepairService // Handle giving INT to player - differs if using kit/trader and weapon vs armor const intellectGainedFromRepair = this.getIntellectGainedFromRepair(repairDetails); - if (intellectGainedFromRepair > 0) - { + if (intellectGainedFromRepair > 0) { this.logger.debug(`Added: ${intellectGainedFromRepair} intellect skill`); this.profileHelper.addSkillPointsToPlayer(pmcData, SkillTypes.INTELLECT, intellectGainedFromRepair); } } - protected getIntellectGainedFromRepair(repairDetails: RepairDetails): number - { - if (repairDetails.repairedByKit) - { + protected getIntellectGainedFromRepair(repairDetails: RepairDetails): number { + if (repairDetails.repairedByKit) { // Weapons/armor have different multipliers const intRepairMultiplier = this.itemHelper.isOfBaseclass( repairDetails.repairedItem._tpl, @@ -229,9 +225,13 @@ export class RepairService : this.repairConfig.repairKitIntellectGainMultiplier.armor; // Limit gain to a max value defined in config.maxIntellectGainPerRepair - if (!repairDetails.repairPoints) - { - throw new Error(this.localisationService.getText("repair-item_has_no_repair_points", repairDetails.repairedItem._tpl)); + if (!repairDetails.repairPoints) { + throw new Error( + this.localisationService.getText( + "repair-item_has_no_repair_points", + repairDetails.repairedItem._tpl, + ), + ); } return Math.min( @@ -249,8 +249,7 @@ export class RepairService * @param repairDetails the repair details to calculate skill points for * @returns the number of skill points to reward the user */ - protected getWeaponRepairSkillPoints(repairDetails: RepairDetails): number - { + protected getWeaponRepairSkillPoints(repairDetails: RepairDetails): number { // This formula and associated configs is calculated based on 30 repairs done on live // The points always came out 2-aligned, which is why there's a divide/multiply by 2 with ceil calls const gainMult = this.repairConfig.weaponTreatment.pointGainMultiplier; @@ -266,14 +265,12 @@ export class RepairService // You can both crit fail and succeed at the same time, for fun (Balances out to 0 with default settings) // Add a random chance to crit-fail - if (Math.random() <= this.repairConfig.weaponTreatment.critFailureChance) - { + if (Math.random() <= this.repairConfig.weaponTreatment.critFailureChance) { skillPoints -= this.repairConfig.weaponTreatment.critFailureAmount; } // Add a random chance to crit-succeed - if (Math.random() <= this.repairConfig.weaponTreatment.critSuccessChance) - { + if (Math.random() <= this.repairConfig.weaponTreatment.critSuccessChance) { skillPoints += this.repairConfig.weaponTreatment.critSuccessAmount; } @@ -294,12 +291,10 @@ export class RepairService repairKits: RepairKitsInfo[], itemToRepairId: string, output: IItemEventRouterResponse, - ): RepairDetails - { + ): RepairDetails { // Find item to repair in inventory const itemToRepair = pmcData.Inventory.items.find((x: { _id: string }) => x._id === itemToRepairId); - if (itemToRepair === undefined) - { + if (itemToRepair === undefined) { throw new Error(this.localisationService.getText("repair-item_not_found_unable_to_repair", itemToRepairId)); } @@ -323,12 +318,12 @@ export class RepairService ); // Find and use repair kit defined in body - for (const repairKit of repairKits) - { + for (const repairKit of repairKits) { const repairKitInInventory = pmcData.Inventory.items.find((item) => item._id === repairKit._id); - if (!repairKitInInventory) - { - throw new Error(this.localisationService.getText("repair-repair_kit_not_found_in_inventory", repairKit._id)); + if (!repairKitInInventory) { + throw new Error( + this.localisationService.getText("repair-repair_kit_not_found_in_inventory", repairKit._id), + ); } const repairKitDetails = itemsDb[repairKitInInventory._tpl]; const repairKitReductionAmount = repairKit.count; @@ -357,18 +352,16 @@ export class RepairService * @param pmcData Player profile * @returns Number to divide kit points by */ - protected getKitDivisor(itemToRepairDetails: ITemplateItem, isArmor: boolean, pmcData: IPmcData): number - { + protected getKitDivisor(itemToRepairDetails: ITemplateItem, isArmor: boolean, pmcData: IPmcData): number { const globals = this.databaseService.getGlobals(); const globalRepairSettings = globals.config.RepairSettings; const intellectRepairPointsPerLevel = globals.config.SkillsSettings.Intellect.RepairPointsCostReduction; - const profileIntellectLevel - = this.profileHelper.getSkillFromProfile(pmcData, SkillTypes.INTELLECT)?.Progress ?? 0; + const profileIntellectLevel = + this.profileHelper.getSkillFromProfile(pmcData, SkillTypes.INTELLECT)?.Progress ?? 0; const intellectPointReduction = intellectRepairPointsPerLevel * Math.trunc(profileIntellectLevel / 100); - if (isArmor) - { + if (isArmor) { const durabilityPointCostArmor = globalRepairSettings.durabilityPointCostArmor; const repairArmorBonus = this.getBonusMultiplierValue(BonusType.REPAIR_ARMOR_BONUS, pmcData); const armorBonus = 1.0 - (repairArmorBonus - 1.0) - intellectPointReduction; @@ -395,12 +388,10 @@ export class RepairService * @param pmcData Player profile to look in for skill * @returns Multiplier value */ - protected getBonusMultiplierValue(skillBonus: BonusType, pmcData: IPmcData): number - { + protected getBonusMultiplierValue(skillBonus: BonusType, pmcData: IPmcData): number { const bonusesMatched = pmcData?.Bonuses?.filter((b) => b.type === skillBonus); let value = 1; - if (bonusesMatched) - { + if (bonusesMatched) { const summedPercentage = bonusesMatched.map((b) => b.value ?? 0).reduce((v1, v2) => v1 + v2, 0); value = 1 + summedPercentage / 100; } @@ -414,15 +405,12 @@ export class RepairService * @param applyRandomizeDurabilityLoss Value from repair config * @returns True if loss should be applied */ - protected shouldRepairKitApplyDurabilityLoss(pmcData: IPmcData, applyRandomizeDurabilityLoss: boolean): boolean - { + protected shouldRepairKitApplyDurabilityLoss(pmcData: IPmcData, applyRandomizeDurabilityLoss: boolean): boolean { let shouldApplyDurabilityLoss = applyRandomizeDurabilityLoss; - if (shouldApplyDurabilityLoss) - { + if (shouldApplyDurabilityLoss) { // Random loss not disabled via config, perform charisma check const hasEliteCharisma = this.profileHelper.hasEliteSkillLevel(SkillTypes.CHARISMA, pmcData); - if (hasEliteCharisma) - { + if (hasEliteCharisma) { // 50/50 chance of loss being ignored at elite level shouldApplyDurabilityLoss = this.randomUtil.getChance100(50); } @@ -436,16 +424,13 @@ export class RepairService * @param repairKitDetails Repair kit details from db * @param repairKitInInventory Repair kit to update */ - protected addMaxResourceToKitIfMissing(repairKitDetails: ITemplateItem, repairKitInInventory: Item): void - { + protected addMaxResourceToKitIfMissing(repairKitDetails: ITemplateItem, repairKitInInventory: Item): void { const maxRepairAmount = repairKitDetails._props.MaxRepairResource!; - if (!repairKitInInventory.upd) - { + if (!repairKitInInventory.upd) { this.logger.debug(`Repair kit: ${repairKitInInventory._id} in inventory lacks upd object, adding`); repairKitInInventory.upd = { RepairKit: { Resource: maxRepairAmount } }; } - if (!repairKitInInventory.upd.RepairKit?.Resource) - { + if (!repairKitInInventory.upd.RepairKit?.Resource) { repairKitInInventory.upd.RepairKit = { Resource: maxRepairAmount }; } } @@ -455,16 +440,13 @@ export class RepairService * @param repairDetails Repair details of item * @param pmcData Player profile */ - public addBuffToItem(repairDetails: RepairDetails, pmcData: IPmcData): void - { + public addBuffToItem(repairDetails: RepairDetails, pmcData: IPmcData): void { // Buffs are repair kit only - if (!repairDetails.repairedByKit) - { + if (!repairDetails.repairedByKit) { return; } - if (this.shouldBuffItem(repairDetails, pmcData)) - { + if (this.shouldBuffItem(repairDetails, pmcData)) { if ( this.itemHelper.isOfBaseclasses(repairDetails.repairedItem._tpl, [ BaseClasses.ARMOR, @@ -472,13 +454,10 @@ export class RepairService BaseClasses.HEADWEAR, BaseClasses.ARMOR_PLATE, ]) - ) - { + ) { const armorConfig = this.repairConfig.repairKit.armor; this.addBuff(armorConfig, repairDetails.repairedItem); - } - else if (this.itemHelper.isOfBaseclass(repairDetails.repairedItem._tpl, BaseClasses.WEAPON)) - { + } else if (this.itemHelper.isOfBaseclass(repairDetails.repairedItem._tpl, BaseClasses.WEAPON)) { const weaponConfig = this.repairConfig.repairKit.weapon; this.addBuff(weaponConfig, repairDetails.repairedItem); } @@ -491,8 +470,7 @@ export class RepairService * @param itemConfig weapon/armor config * @param repairDetails Details for item to repair */ - public addBuff(itemConfig: BonusSettings, item: Item): void - { + public addBuff(itemConfig: BonusSettings, item: Item): void { const bonusRarity = this.weightedRandomHelper.getWeightedValue(itemConfig.rarityWeight); const bonusType = this.weightedRandomHelper.getWeightedValue(itemConfig.bonusTypeWeight); @@ -520,56 +498,52 @@ export class RepairService * @param pmcData Player profile * @returns True if item should have buff applied */ - protected shouldBuffItem(repairDetails: RepairDetails, pmcData: IPmcData): boolean - { + protected shouldBuffItem(repairDetails: RepairDetails, pmcData: IPmcData): boolean { const globals = this.databaseService.getGlobals(); const hasTemplate = this.itemHelper.getItem(repairDetails.repairedItem._tpl); - if (!hasTemplate[0]) - { + if (!hasTemplate[0]) { return false; } const template = hasTemplate[1]; // Returns SkillTypes.LIGHT_VESTS/HEAVY_VESTS/WEAPON_TREATMENT const itemSkillType = this.getItemSkillType(template); - if (!itemSkillType) - { + if (!itemSkillType) { return false; } // Skill < level 10 + repairing weapon if ( - itemSkillType === SkillTypes.WEAPON_TREATMENT - && this.profileHelper.getSkillFromProfile(pmcData, SkillTypes.WEAPON_TREATMENT)?.Progress < 1000 - ) - { + itemSkillType === SkillTypes.WEAPON_TREATMENT && + this.profileHelper.getSkillFromProfile(pmcData, SkillTypes.WEAPON_TREATMENT)?.Progress < 1000 + ) { return false; } // Skill < level 10 + repairing armor if ( - [SkillTypes.LIGHT_VESTS, SkillTypes.HEAVY_VESTS].includes(itemSkillType) - && this.profileHelper.getSkillFromProfile(pmcData, itemSkillType)?.Progress < 1000 - ) - { + [SkillTypes.LIGHT_VESTS, SkillTypes.HEAVY_VESTS].includes(itemSkillType) && + this.profileHelper.getSkillFromProfile(pmcData, itemSkillType)?.Progress < 1000 + ) { return false; } - const commonBuffMinChanceValue - = globals.config.SkillsSettings[itemSkillType as string].BuffSettings.CommonBuffMinChanceValue; - const commonBuffChanceLevelBonus - = globals.config.SkillsSettings[itemSkillType as string].BuffSettings.CommonBuffChanceLevelBonus; - const receivedDurabilityMaxPercent - = globals.config.SkillsSettings[itemSkillType as string].BuffSettings.ReceivedDurabilityMaxPercent; + const commonBuffMinChanceValue = + globals.config.SkillsSettings[itemSkillType as string].BuffSettings.CommonBuffMinChanceValue; + const commonBuffChanceLevelBonus = + globals.config.SkillsSettings[itemSkillType as string].BuffSettings.CommonBuffChanceLevelBonus; + const receivedDurabilityMaxPercent = + globals.config.SkillsSettings[itemSkillType as string].BuffSettings.ReceivedDurabilityMaxPercent; const skillLevel = Math.trunc( (this.profileHelper.getSkillFromProfile(pmcData, itemSkillType)?.Progress ?? 0) / 100, ); - if (!repairDetails.repairPoints) - { - throw new Error(this.localisationService.getText("repair-item_has_no_repair_points", repairDetails.repairedItem._tpl)); + if (!repairDetails.repairPoints) { + throw new Error( + this.localisationService.getText("repair-item_has_no_repair_points", repairDetails.repairedItem._tpl), + ); } const durabilityToRestorePercent = repairDetails.repairPoints / template._props.MaxDurability!; const durabilityMultiplier = this.getDurabilityMultiplier( @@ -579,8 +553,7 @@ export class RepairService const doBuff = commonBuffMinChanceValue + commonBuffChanceLevelBonus * skillLevel * durabilityMultiplier; - if (Math.random() <= doBuff) - { + if (Math.random() <= doBuff) { return true; } @@ -592,8 +565,7 @@ export class RepairService * @param itemTemplate Item to check for skill * @returns Skill name */ - protected getItemSkillType(itemTemplate: ITemplateItem): SkillTypes | undefined - { + protected getItemSkillType(itemTemplate: ITemplateItem): SkillTypes | undefined { const isArmorRelated = this.itemHelper.isOfBaseclasses(itemTemplate._id, [ BaseClasses.ARMOR, BaseClasses.VEST, @@ -601,27 +573,22 @@ export class RepairService BaseClasses.ARMOR_PLATE, ]); - if (isArmorRelated) - { + if (isArmorRelated) { const armorType = itemTemplate._props.ArmorType; - if (armorType === "Light") - { + if (armorType === "Light") { return SkillTypes.LIGHT_VESTS; } - if (armorType === "Heavy") - { + if (armorType === "Heavy") { return SkillTypes.HEAVY_VESTS; } } - if (this.itemHelper.isOfBaseclass(itemTemplate._id, BaseClasses.WEAPON)) - { + if (this.itemHelper.isOfBaseclass(itemTemplate._id, BaseClasses.WEAPON)) { return SkillTypes.WEAPON_TREATMENT; } - if (this.itemHelper.isOfBaseclass(itemTemplate._id, BaseClasses.KNIFE)) - { + if (this.itemHelper.isOfBaseclass(itemTemplate._id, BaseClasses.KNIFE)) { return SkillTypes.MELEE; } @@ -634,8 +601,7 @@ export class RepairService * @param receiveDurabilityPercent current durability percent * @returns durability multiplier value */ - protected getDurabilityMultiplier(receiveDurabilityMaxPercent: number, receiveDurabilityPercent: number): number - { + protected getDurabilityMultiplier(receiveDurabilityMaxPercent: number, receiveDurabilityPercent: number): number { // Ensure the max percent is at least 0.01 const validMaxPercent = Math.max(0.01, receiveDurabilityMaxPercent); // Calculate the ratio and constrain it between 0.01 and 1 @@ -643,8 +609,7 @@ export class RepairService } } -export class RepairDetails -{ +export class RepairDetails { repairCost?: number; repairPoints?: number; repairedItem: Item; diff --git a/project/src/services/SeasonalEventService.ts b/project/src/services/SeasonalEventService.ts index 396fd5b2..9611156c 100644 --- a/project/src/services/SeasonalEventService.ts +++ b/project/src/services/SeasonalEventService.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { BotHelper } from "@spt/helpers/BotHelper"; import { ProfileHelper } from "@spt/helpers/ProfileHelper"; import { IConfig } from "@spt/models/eft/common/IGlobals"; @@ -19,10 +18,10 @@ import { DatabaseService } from "@spt/services/DatabaseService"; import { GiftService } from "@spt/services/GiftService"; import { LocalisationService } from "@spt/services/LocalisationService"; import { DatabaseImporter } from "@spt/utils/DatabaseImporter"; +import { inject, injectable } from "tsyringe"; @injectable() -export class SeasonalEventService -{ +export class SeasonalEventService { protected seasonalEventConfig: ISeasonalEventConfig; protected questConfig: IQuestConfig; protected httpConfig: IHttpConfig; @@ -43,8 +42,7 @@ export class SeasonalEventService @inject("BotHelper") protected botHelper: BotHelper, @inject("ProfileHelper") protected profileHelper: ProfileHelper, @inject("ConfigServer") protected configServer: ConfigServer, - ) - { + ) { this.seasonalEventConfig = this.configServer.getConfig(ConfigTypes.SEASONAL_EVENT); this.questConfig = this.configServer.getConfig(ConfigTypes.QUEST); this.httpConfig = this.configServer.getConfig(ConfigTypes.HTTP); @@ -53,8 +51,7 @@ export class SeasonalEventService this.cacheActiveEvents(); } - protected get christmasEventItems(): string[] - { + protected get christmasEventItems(): string[] { return [ ItemTpl.FACECOVER_FAKE_WHITE_BEARD, ItemTpl.BARTER_CHRISTMAS_TREE_ORNAMENT_RED, @@ -66,8 +63,7 @@ export class SeasonalEventService ]; } - protected get halloweenEventItems(): string[] - { + protected get halloweenEventItems(): string[] { return [ ItemTpl.FACECOVER_SPOOKY_SKULL_MASK, ItemTpl.RANDOMLOOTCONTAINER_PUMPKIN_RAND_LOOT_CONTAINER, @@ -87,8 +83,7 @@ export class SeasonalEventService * Get an array of christmas items found in bots inventories as loot * @returns array */ - public getChristmasEventItems(): string[] - { + public getChristmasEventItems(): string[] { return this.christmasEventItems; } @@ -96,18 +91,15 @@ export class SeasonalEventService * Get an array of halloween items found in bots inventories as loot * @returns array */ - public getHalloweenEventItems(): string[] - { + public getHalloweenEventItems(): string[] { return this.halloweenEventItems; } - public itemIsChristmasRelated(itemTpl: string): boolean - { + public itemIsChristmasRelated(itemTpl: string): boolean { return this.christmasEventItems.includes(itemTpl); } - public itemIsHalloweenRelated(itemTpl: string): boolean - { + public itemIsHalloweenRelated(itemTpl: string): boolean { return this.halloweenEventItems.includes(itemTpl); } @@ -116,8 +108,7 @@ export class SeasonalEventService * @param itemTpl item tpl to check for * @returns */ - public itemIsSeasonalRelated(itemTpl: string): boolean - { + public itemIsSeasonalRelated(itemTpl: string): boolean { return this.christmasEventItems.includes(itemTpl) || this.halloweenEventItems.includes(itemTpl); } @@ -127,16 +118,13 @@ export class SeasonalEventService * or, if halloween and christmas are inactive, return both sets of items * @returns array of tpl strings */ - public getInactiveSeasonalEventItems(): string[] - { + public getInactiveSeasonalEventItems(): string[] { const items: string[] = []; - if (!this.christmasEventEnabled()) - { + if (!this.christmasEventEnabled()) { items.push(...this.christmasEventItems); } - if (!this.halloweenEventEnabled()) - { + if (!this.halloweenEventEnabled()) { items.push(...this.halloweenEventItems); } @@ -147,8 +135,7 @@ export class SeasonalEventService * Is a seasonal event currently active * @returns true if event is active */ - public seasonalEventEnabled(): boolean - { + public seasonalEventEnabled(): boolean { return this.christmasEventEnabled() || this.halloweenEventEnabled(); } @@ -156,8 +143,7 @@ export class SeasonalEventService * Is christmas event active * @returns true if active */ - public christmasEventEnabled(): boolean - { + public christmasEventEnabled(): boolean { return this.christmasEventActive ?? false; } @@ -165,8 +151,7 @@ export class SeasonalEventService * is halloween event active * @returns true if active */ - public halloweenEventEnabled(): boolean - { + public halloweenEventEnabled(): boolean { return this.halloweenEventActive ?? false; } @@ -174,8 +159,7 @@ export class SeasonalEventService * Is detection of seasonal events enabled (halloween / christmas) * @returns true if seasonal events should be checked for */ - public isAutomaticEventDetectionEnabled(): boolean - { + public isAutomaticEventDetectionEnabled(): boolean { return this.seasonalEventConfig.enableSeasonalEventDetection; } @@ -184,8 +168,7 @@ export class SeasonalEventService * @param eventName Name of event to get gear changes for * @returns bots with equipment changes */ - protected getEventBotGear(eventType: SeasonalEventType): Record>> - { + protected getEventBotGear(eventType: SeasonalEventType): Record>> { return this.seasonalEventConfig.eventGear[eventType.toLowerCase()]; } @@ -193,8 +176,7 @@ export class SeasonalEventService * Get the dates each seasonal event starts and ends at * @returns Record with event name + start/end date */ - public getEventDetails(): ISeasonalEvent[] - { + public getEventDetails(): ISeasonalEvent[] { return this.seasonalEventConfig.events; } @@ -204,11 +186,9 @@ export class SeasonalEventService * @param event event type (Christmas/Halloween/None) * @returns true if related */ - public isQuestRelatedToEvent(questId: string, event: SeasonalEventType): boolean - { + public isQuestRelatedToEvent(questId: string, event: SeasonalEventType): boolean { const eventQuestData = this.questConfig.eventQuests[questId]; - if (eventQuestData?.season.toLowerCase() === event.toLowerCase()) - { + if (eventQuestData?.season.toLowerCase() === event.toLowerCase()) { return true; } @@ -219,51 +199,41 @@ export class SeasonalEventService * Handle seasonal events * @param sessionId Players id */ - public enableSeasonalEvents(sessionId: string): void - { - if (this.currentlyActiveEvents) - { + public enableSeasonalEvents(sessionId: string): void { + if (this.currentlyActiveEvents) { const globalConfig = this.databaseService.getGlobals().config; - for (const event of this.currentlyActiveEvents) - { + for (const event of this.currentlyActiveEvents) { this.updateGlobalEvents(sessionId, globalConfig, event); } } } - protected cacheActiveEvents(): void - { + protected cacheActiveEvents(): void { const currentDate = new Date(); const seasonalEvents = this.getEventDetails(); - for (const event of seasonalEvents) - { + for (const event of seasonalEvents) { const eventStartDate = new Date(currentDate.getFullYear(), event.startMonth - 1, event.startDay); const eventEndDate = new Date(currentDate.getFullYear(), event.endMonth - 1, event.endDay); // Current date is between start/end dates - if (currentDate >= eventStartDate && currentDate <= eventEndDate) - { + if (currentDate >= eventStartDate && currentDate <= eventEndDate) { this.currentlyActiveEvents.push(SeasonalEventType[event.type]); - if (SeasonalEventType[event.type] === SeasonalEventType.CHRISTMAS) - { + if (SeasonalEventType[event.type] === SeasonalEventType.CHRISTMAS) { this.christmasEventActive = true; } - if (SeasonalEventType[event.type] === SeasonalEventType.HALLOWEEN) - { + if (SeasonalEventType[event.type] === SeasonalEventType.HALLOWEEN) { this.halloweenEventActive = true; } } } } - public getActiveWeatherSeason(): Season - { + public getActiveWeatherSeason(): Season { const currentDate = new Date(); - for (const seasonRange of this.weatherConfig.seasonDates) - { + for (const seasonRange of this.weatherConfig.seasonDates) { // Figure out start and end dates to get range of season const eventStartDate = new Date( currentDate.getFullYear(), @@ -273,8 +243,7 @@ export class SeasonalEventService const eventEndDate = new Date(currentDate.getFullYear(), seasonRange.endMonth - 1, seasonRange.endDay); // Does todays date fit inside the above range - if (currentDate >= eventStartDate && currentDate <= eventEndDate) - { + if (currentDate >= eventStartDate && currentDate <= eventEndDate) { return seasonRange.seasonType; } } @@ -289,17 +258,14 @@ export class SeasonalEventService * @param botInventory Bots inventory to iterate over * @param botRole the role of the bot being processed */ - public removeChristmasItemsFromBotInventory(botInventory: Inventory, botRole: string): void - { + public removeChristmasItemsFromBotInventory(botInventory: Inventory, botRole: string): void { const christmasItems = this.getChristmasEventItems(); const equipmentSlotsToFilter = ["FaceCover", "Headwear", "Backpack", "TacticalVest"]; const lootContainersToFilter = ["Backpack", "Pockets", "TacticalVest"]; // Remove christmas related equipment - for (const equipmentSlotKey of equipmentSlotsToFilter) - { - if (!botInventory.equipment[equipmentSlotKey]) - { + for (const equipmentSlotKey of equipmentSlotsToFilter) { + if (!botInventory.equipment[equipmentSlotKey]) { this.logger.warning( this.localisationService.getText("seasonal-missing_equipment_slot_on_bot", { equipmentSlot: equipmentSlotKey, @@ -315,10 +281,8 @@ export class SeasonalEventService } // Remove christmas related loot from loot containers - for (const lootContainerKey of lootContainersToFilter) - { - if (!botInventory.items[lootContainerKey]) - { + for (const lootContainerKey of lootContainersToFilter) { + if (!botInventory.items[lootContainerKey]) { this.logger.warning( this.localisationService.getText("seasonal-missing_loot_container_slot_on_bot", { lootContainer: lootContainerKey, @@ -329,29 +293,24 @@ export class SeasonalEventService const tplsToRemove: string[] = []; const containerItems = botInventory.items[lootContainerKey]; - for (const tplKey of Object.keys(containerItems)) - { - if (christmasItems.includes(tplKey)) - { + for (const tplKey of Object.keys(containerItems)) { + if (christmasItems.includes(tplKey)) { tplsToRemove.push(tplKey); } } - for (const tplToRemove of tplsToRemove) - { + for (const tplToRemove of tplsToRemove) { delete containerItems[tplToRemove]; } // Get non-christmas items const nonChristmasTpls = Object.keys(containerItems).filter((tpl) => !christmasItems.includes(tpl)); - if (nonChristmasTpls.length === 0) - { + if (nonChristmasTpls.length === 0) { continue; } const intermediaryDict = {}; - for (const tpl of nonChristmasTpls) - { + for (const tpl of nonChristmasTpls) { intermediaryDict[tpl] = containerItems[tpl]; } @@ -366,12 +325,10 @@ export class SeasonalEventService * @param globalConfig globals.json * @param eventName Name of the event to enable. e.g. Christmas */ - protected updateGlobalEvents(sessionId: string, globalConfig: IConfig, eventType: SeasonalEventType): void - { + protected updateGlobalEvents(sessionId: string, globalConfig: IConfig, eventType: SeasonalEventType): void { this.logger.success(`${eventType} event is active`); - switch (eventType.toLowerCase()) - { + switch (eventType.toLowerCase()) { case SeasonalEventType.HALLOWEEN.toLowerCase(): globalConfig.EventType = globalConfig.EventType.filter((x) => x !== "None"); globalConfig.EventType.push("Halloween"); @@ -408,41 +365,33 @@ export class SeasonalEventService } } - protected adjustZryachiyMeleeChance(): void - { + protected adjustZryachiyMeleeChance(): void { this.databaseService.getBots().types.bosszryachiy.chances.equipment.Scabbard = 100; } - protected enableHalloweenSummonEvent(): void - { + protected enableHalloweenSummonEvent(): void { this.databaseService.getGlobals().config.EventSettings.EventActive = true; } - protected addEventBossesToMaps(eventType: SeasonalEventType): void - { + protected addEventBossesToMaps(eventType: SeasonalEventType): void { const botsToAddPerMap = this.seasonalEventConfig.eventBossSpawns[eventType.toLowerCase()]; - if (!botsToAddPerMap) - { + if (!botsToAddPerMap) { this.logger.warning(`Unable to add: ${eventType} bosses, eventBossSpawns is missing`); return; } const mapKeys = Object.keys(botsToAddPerMap) ?? []; - for (const mapKey of mapKeys) - { + for (const mapKey of mapKeys) { const bossesToAdd = botsToAddPerMap[mapKey]; - if (!bossesToAdd) - { + if (!bossesToAdd) { this.logger.warning(`Unable to add: ${eventType} bosses to: ${mapKey}`); continue; } - for (const boss of bossesToAdd) - { + for (const boss of bossesToAdd) { const locations = this.databaseService.getLocations(); const mapBosses: BossLocationSpawn[] = locations[mapKey].base.BossLocationSpawn; - if (!mapBosses.some((bossSpawn) => bossSpawn.BossName === boss.BossName)) - { + if (!mapBosses.some((bossSpawn) => bossSpawn.BossName === boss.BossName)) { locations[mapKey].base.BossLocationSpawn.push(...bossesToAdd); } } @@ -453,27 +402,25 @@ export class SeasonalEventService * Change trader icons to be more event themed (Halloween only so far) * @param eventType What event is active */ - protected adjustTraderIcons(eventType: SeasonalEventType): void - { - switch (eventType.toLowerCase()) - { + protected adjustTraderIcons(eventType: SeasonalEventType): void { + switch (eventType.toLowerCase()) { case SeasonalEventType.HALLOWEEN.toLowerCase(): - this.httpConfig.serverImagePathOverride["./assets/images/traders/5a7c2ebb86f7746e324a06ab.png"] - = "./assets/images/traders/halloween/5a7c2ebb86f7746e324a06ab.png"; - this.httpConfig.serverImagePathOverride["./assets/images/traders/5ac3b86a86f77461491d1ad8.png"] - = "./assets/images/traders/halloween/5ac3b86a86f77461491d1ad8.png"; - this.httpConfig.serverImagePathOverride["./assets/images/traders/5c06531a86f7746319710e1b.png"] - = "./assets/images/traders/halloween/5c06531a86f7746319710e1b.png"; - this.httpConfig.serverImagePathOverride["./assets/images/traders/59b91ca086f77469a81232e4.png"] - = "./assets/images/traders/halloween/59b91ca086f77469a81232e4.png"; - this.httpConfig.serverImagePathOverride["./assets/images/traders/59b91cab86f77469aa5343ca.png"] - = "./assets/images/traders/halloween/59b91cab86f77469aa5343ca.png"; - this.httpConfig.serverImagePathOverride["./assets/images/traders/59b91cb486f77469a81232e5.png"] - = "./assets/images/traders/halloween/59b91cb486f77469a81232e5.png"; - this.httpConfig.serverImagePathOverride["./assets/images/traders/59b91cbd86f77469aa5343cb.png"] - = "./assets/images/traders/halloween/59b91cbd86f77469aa5343cb.png"; - this.httpConfig.serverImagePathOverride["./assets/images/traders/579dc571d53a0658a154fbec.png"] - = "./assets/images/traders/halloween/579dc571d53a0658a154fbec.png"; + this.httpConfig.serverImagePathOverride["./assets/images/traders/5a7c2ebb86f7746e324a06ab.png"] = + "./assets/images/traders/halloween/5a7c2ebb86f7746e324a06ab.png"; + this.httpConfig.serverImagePathOverride["./assets/images/traders/5ac3b86a86f77461491d1ad8.png"] = + "./assets/images/traders/halloween/5ac3b86a86f77461491d1ad8.png"; + this.httpConfig.serverImagePathOverride["./assets/images/traders/5c06531a86f7746319710e1b.png"] = + "./assets/images/traders/halloween/5c06531a86f7746319710e1b.png"; + this.httpConfig.serverImagePathOverride["./assets/images/traders/59b91ca086f77469a81232e4.png"] = + "./assets/images/traders/halloween/59b91ca086f77469a81232e4.png"; + this.httpConfig.serverImagePathOverride["./assets/images/traders/59b91cab86f77469aa5343ca.png"] = + "./assets/images/traders/halloween/59b91cab86f77469aa5343ca.png"; + this.httpConfig.serverImagePathOverride["./assets/images/traders/59b91cb486f77469a81232e5.png"] = + "./assets/images/traders/halloween/59b91cb486f77469a81232e5.png"; + this.httpConfig.serverImagePathOverride["./assets/images/traders/59b91cbd86f77469aa5343cb.png"] = + "./assets/images/traders/halloween/59b91cbd86f77469aa5343cb.png"; + this.httpConfig.serverImagePathOverride["./assets/images/traders/579dc571d53a0658a154fbec.png"] = + "./assets/images/traders/halloween/579dc571d53a0658a154fbec.png"; break; case SeasonalEventType.CHRISTMAS.toLowerCase(): // TODO: find christmas trader icons @@ -490,11 +437,9 @@ export class SeasonalEventService /** * Add lootble items from backpack into patrol.ITEMS_TO_DROP difficulty property */ - protected addLootItemsToGifterDropItemsList(): void - { + protected addLootItemsToGifterDropItemsList(): void { const gifterBot = this.databaseService.getBots().types.gifter; - for (const difficulty in gifterBot.difficulty) - { + for (const difficulty in gifterBot.difficulty) { gifterBot.difficulty[difficulty].Patrol.ITEMS_TO_DROP = Object.keys( gifterBot.inventory.items.Backpack, ).join(", "); @@ -505,30 +450,25 @@ export class SeasonalEventService * Read in data from seasonalEvents.json and add found equipment items to bots * @param eventName Name of the event to read equipment in from config */ - protected addEventGearToBots(eventType: SeasonalEventType): void - { + protected addEventGearToBots(eventType: SeasonalEventType): void { const botGearChanges = this.getEventBotGear(eventType); - if (!botGearChanges) - { + if (!botGearChanges) { this.logger.warning(this.localisationService.getText("gameevent-no_gear_data", eventType)); return; } // Iterate over bots with changes to apply - for (const bot in botGearChanges) - { + for (const bot in botGearChanges) { const botToUpdate = this.databaseService.getBots().types[bot.toLowerCase()]; - if (!botToUpdate) - { + if (!botToUpdate) { this.logger.warning(this.localisationService.getText("gameevent-bot_not_found", bot)); continue; } // Iterate over each equipment slot change const gearAmendments = botGearChanges[bot]; - for (const equipmentSlot in gearAmendments) - { + for (const equipmentSlot in gearAmendments) { // Adjust slots spawn chance to be at least 75% botToUpdate.chances.equipment[equipmentSlot] = Math.max( botToUpdate.chances.equipment[equipmentSlot], @@ -537,36 +477,32 @@ export class SeasonalEventService // Grab gear to add and loop over it const itemsToAdd = gearAmendments[equipmentSlot]; - for (const itemTplIdToAdd in itemsToAdd) - { + for (const itemTplIdToAdd in itemsToAdd) { botToUpdate.inventory.equipment[equipmentSlot][itemTplIdToAdd] = itemsToAdd[itemTplIdToAdd]; } } } } - protected addPumpkinsToScavBackpacks(): void - { - this.databaseService.getBots().types.assault.inventory.items.Backpack[ItemTpl.RANDOMLOOTCONTAINER_PUMPKIN_RAND_LOOT_CONTAINER] = 400; + protected addPumpkinsToScavBackpacks(): void { + this.databaseService.getBots().types.assault.inventory.items.Backpack[ + ItemTpl.RANDOMLOOTCONTAINER_PUMPKIN_RAND_LOOT_CONTAINER + ] = 400; } /** * Set Khorovod(dancing tree) chance to 100% on all maps that support it */ - protected enableDancingTree(): void - { + protected enableDancingTree(): void { const maps = this.databaseService.getLocations(); - for (const mapName in maps) - { + for (const mapName in maps) { // Skip maps that have no tree - if (["hideout", "base", "privatearea"].includes(mapName)) - { + if (["hideout", "base", "privatearea"].includes(mapName)) { continue; } const mapData: ILocation = maps[mapName]; - if (mapData?.base?.BotLocationModifier && "KhorovodChance" in mapData.base.BotLocationModifier) - { + if (mapData?.base?.BotLocationModifier && "KhorovodChance" in mapData.base.BotLocationModifier) { mapData.base.BotLocationModifier.KhorovodChance = 100; } } @@ -575,16 +511,13 @@ export class SeasonalEventService /** * Add santa to maps */ - protected addGifterBotToMaps(): void - { + protected addGifterBotToMaps(): void { const gifterSettings = this.seasonalEventConfig.gifterSettings; const maps = this.databaseService.getLocations(); - for (const gifterMapSettings of gifterSettings) - { + for (const gifterMapSettings of gifterSettings) { const mapData: ILocation = maps[gifterMapSettings.map]; // Dont add gifter to map twice - if (mapData.base.BossLocationSpawn.some((boss) => boss.BossName === "gifter")) - { + if (mapData.base.BossLocationSpawn.some((boss) => boss.BossName === "gifter")) { continue; } @@ -613,11 +546,9 @@ export class SeasonalEventService * @param playerId Player to send gift to * @param giftKey Key of gift to give */ - protected giveGift(playerId: string, giftKey: string): void - { + protected giveGift(playerId: string, giftKey: string): void { const gitftData = this.giftService.getGiftById(giftKey); - if (!this.profileHelper.playerHasRecievedMaxNumberOfGift(playerId, giftKey, gitftData.maxToSendPlayer ?? 5)) - { + if (!this.profileHelper.playerHasRecievedMaxNumberOfGift(playerId, giftKey, gitftData.maxToSendPlayer ?? 5)) { this.giftService.sendGiftToPlayer(playerId, giftKey); } } @@ -627,13 +558,11 @@ export class SeasonalEventService * @param eventBotRole Event bot role type * @returns Bot role as string */ - public getBaseRoleForEventBot(eventBotRole: string): string - { + public getBaseRoleForEventBot(eventBotRole: string): string { return this.seasonalEventConfig.eventBotMapping[eventBotRole]; } - public enableSnow(): void - { + public enableSnow(): void { this.weatherConfig.overrideSeason = Season.WINTER; } } diff --git a/project/src/services/TraderAssortService.ts b/project/src/services/TraderAssortService.ts index ec7b9835..93622344 100644 --- a/project/src/services/TraderAssortService.ts +++ b/project/src/services/TraderAssortService.ts @@ -1,11 +1,9 @@ import { ITraderAssort } from "@spt/models/eft/common/tables/ITrader"; -export class TraderAssortService -{ +export class TraderAssortService { protected pristineTraderAssorts: Record = {}; - public getPristineTraderAssort(traderId: string): ITraderAssort - { + public getPristineTraderAssort(traderId: string): ITraderAssort { return this.pristineTraderAssorts[traderId]; } @@ -14,8 +12,7 @@ export class TraderAssortService * @param traderId Traderid to store assorts against * @param assort Assorts to store */ - public setPristineTraderAssort(traderId: string, assort: ITraderAssort): void - { + public setPristineTraderAssort(traderId: string, assort: ITraderAssort): void { this.pristineTraderAssorts[traderId] = assort; } } diff --git a/project/src/services/TraderPurchasePersisterService.ts b/project/src/services/TraderPurchasePersisterService.ts index 1ef96ab3..e843d29d 100644 --- a/project/src/services/TraderPurchasePersisterService.ts +++ b/project/src/services/TraderPurchasePersisterService.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { ProfileHelper } from "@spt/helpers/ProfileHelper"; import { TraderPurchaseData } from "@spt/models/eft/profile/ISptProfile"; import { ConfigTypes } from "@spt/models/enums/ConfigTypes"; @@ -8,13 +7,13 @@ import { ConfigServer } from "@spt/servers/ConfigServer"; import { LocalisationService } from "@spt/services/LocalisationService"; import { RandomUtil } from "@spt/utils/RandomUtil"; import { TimeUtil } from "@spt/utils/TimeUtil"; +import { inject, injectable } from "tsyringe"; /** * Help with storing limited item purchases from traders in profile to persist them over server restarts */ @injectable() -export class TraderPurchasePersisterService -{ +export class TraderPurchasePersisterService { protected traderConfig: ITraderConfig; constructor( @@ -24,8 +23,7 @@ export class TraderPurchasePersisterService @inject("ProfileHelper") protected profileHelper: ProfileHelper, @inject("LocalisationService") protected localisationService: LocalisationService, @inject("ConfigServer") protected configServer: ConfigServer, - ) - { + ) { this.traderConfig = this.configServer.getConfig(ConfigTypes.TRADER); } @@ -35,12 +33,13 @@ export class TraderPurchasePersisterService * @param traderId Trader to loop up purchases for * @returns Dict of assort id and count purchased */ - public getProfileTraderPurchases(sessionId: string, traderId: string): Record | undefined - { + public getProfileTraderPurchases( + sessionId: string, + traderId: string, + ): Record | undefined { const profile = this.profileHelper.getFullProfile(sessionId); - if (!profile.traderPurchases) - { + if (!profile.traderPurchases) { return undefined; } @@ -54,19 +53,19 @@ export class TraderPurchasePersisterService * @param assortId Id of assort to get data for * @returns TraderPurchaseData */ - public getProfileTraderPurchase(sessionId: string, traderId: string, assortId: string): - TraderPurchaseData | undefined - { + public getProfileTraderPurchase( + sessionId: string, + traderId: string, + assortId: string, + ): TraderPurchaseData | undefined { const profile = this.profileHelper.getFullProfile(sessionId); - if (!profile.traderPurchases) - { + if (!profile.traderPurchases) { return undefined; } const traderPurchases = profile.traderPurchases[traderId]; - if (!traderPurchases) - { + if (!traderPurchases) { return undefined; } @@ -77,21 +76,17 @@ export class TraderPurchasePersisterService * Remove all trader purchase records from all profiles that exist * @param traderId Traders id */ - public resetTraderPurchasesStoredInProfile(traderId: string): void - { + public resetTraderPurchasesStoredInProfile(traderId: string): void { // Reset all profiles purchase dictionaries now a trader update has occured; const profiles = this.profileHelper.getProfiles(); - for (const profile of Object.values(profiles)) - { + for (const profile of Object.values(profiles)) { // Skip if no purchases - if (!profile.traderPurchases) - { + if (!profile.traderPurchases) { continue; } // Skip if no trader-speicifc purchases - if (!profile.traderPurchases[traderId]) - { + if (!profile.traderPurchases[traderId]) { continue; } @@ -103,28 +98,22 @@ export class TraderPurchasePersisterService * Iterate over all server profiles and remove specific trader purchase data that has passed the trader refesh time * @param traderId Trader id */ - public removeStalePurchasesFromProfiles(traderId: string): void - { + public removeStalePurchasesFromProfiles(traderId: string): void { const profiles = this.profileHelper.getProfiles(); - for (const profile of Object.values(profiles)) - { + for (const profile of Object.values(profiles)) { // Skip if no purchases - if (!profile.traderPurchases) - { + if (!profile.traderPurchases) { continue; } // Skip if no trader-specifc purchases - if (!profile.traderPurchases[traderId]) - { + if (!profile.traderPurchases[traderId]) { continue; } - for (const purchaseKey in profile.traderPurchases[traderId]) - { + for (const purchaseKey in profile.traderPurchases[traderId]) { const traderUpdateDetails = this.traderConfig.updateTime.find((x) => x.traderId === traderId); - if (!traderUpdateDetails) - { + if (!traderUpdateDetails) { this.logger.error( this.localisationService.getText("trader-unable_to_delete_stale_purchases", { profileId: profile.info.id, @@ -136,11 +125,10 @@ export class TraderPurchasePersisterService } const purchaseDetails = profile.traderPurchases[traderId][purchaseKey]; - const resetTimeForItem - = purchaseDetails.purchaseTimestamp - + this.randomUtil.getInt(traderUpdateDetails.seconds.min, traderUpdateDetails.seconds.max); - if (resetTimeForItem < this.timeUtil.getTimestamp()) - { + const resetTimeForItem = + purchaseDetails.purchaseTimestamp + + this.randomUtil.getInt(traderUpdateDetails.seconds.min, traderUpdateDetails.seconds.max); + if (resetTimeForItem < this.timeUtil.getTimestamp()) { // Item was purchased far enough in past a trader refresh would have occured, remove purchase record from profile this.logger.debug( `Removed trader: ${traderId} purchase: ${purchaseKey} from profile: ${profile.info.id}`, diff --git a/project/src/services/cache/BundleHashCacheService.ts b/project/src/services/cache/BundleHashCacheService.ts index b33e3b42..9be47f2d 100644 --- a/project/src/services/cache/BundleHashCacheService.ts +++ b/project/src/services/cache/BundleHashCacheService.ts @@ -1,12 +1,11 @@ -import { inject, injectable } from "tsyringe"; import { ILogger } from "@spt/models/spt/utils/ILogger"; import { HashUtil } from "@spt/utils/HashUtil"; import { JsonUtil } from "@spt/utils/JsonUtil"; import { VFS } from "@spt/utils/VFS"; +import { inject, injectable } from "tsyringe"; @injectable() -export class BundleHashCacheService -{ +export class BundleHashCacheService { protected bundleHashes: Record; protected readonly bundleHashCachePath = "./user/cache/bundleHashCache.json"; @@ -15,10 +14,8 @@ export class BundleHashCacheService @inject("HashUtil") protected hashUtil: HashUtil, @inject("JsonUtil") protected jsonUtil: JsonUtil, @inject("PrimaryLogger") protected logger: ILogger, - ) - { - if (!this.vfs.exists(this.bundleHashCachePath)) - { + ) { + if (!this.vfs.exists(this.bundleHashCachePath)) { this.vfs.writeFile(this.bundleHashCachePath, "{}"); } @@ -28,13 +25,11 @@ export class BundleHashCacheService ); } - public getStoredValue(key: string): number - { + public getStoredValue(key: string): number { return this.bundleHashes[key]; } - public storeValue(key: string, value: number): void - { + public storeValue(key: string, value: number): void { this.bundleHashes[key] = value; this.vfs.writeFile(this.bundleHashCachePath, this.jsonUtil.serialize(this.bundleHashes)); @@ -42,20 +37,17 @@ export class BundleHashCacheService this.logger.debug(`Bundle ${key} hash stored in ${this.bundleHashCachePath}`); } - public matchWithStoredHash(bundlePath: string, hash: number): boolean - { + public matchWithStoredHash(bundlePath: string, hash: number): boolean { return this.getStoredValue(bundlePath) === hash; } - public calculateAndMatchHash(bundlePath: string): boolean - { + public calculateAndMatchHash(bundlePath: string): boolean { const generatedHash = this.hashUtil.generateCRC32ForFile(bundlePath); return this.matchWithStoredHash(bundlePath, generatedHash); } - public calculateAndStoreHash(bundlePath: string): void - { + public calculateAndStoreHash(bundlePath: string): void { const generatedHash = this.hashUtil.generateCRC32ForFile(bundlePath); this.storeValue(bundlePath, generatedHash); diff --git a/project/src/services/cache/ModHashCacheService.ts b/project/src/services/cache/ModHashCacheService.ts index 12b57530..e63d2cc9 100644 --- a/project/src/services/cache/ModHashCacheService.ts +++ b/project/src/services/cache/ModHashCacheService.ts @@ -1,12 +1,11 @@ -import { inject, injectable } from "tsyringe"; import { ILogger } from "@spt/models/spt/utils/ILogger"; import { HashUtil } from "@spt/utils/HashUtil"; import { JsonUtil } from "@spt/utils/JsonUtil"; import { VFS } from "@spt/utils/VFS"; +import { inject, injectable } from "tsyringe"; @injectable() -export class ModHashCacheService -{ +export class ModHashCacheService { protected modHashes: Record; protected readonly modCachePath = "./user/cache/modCache.json"; @@ -15,23 +14,19 @@ export class ModHashCacheService @inject("HashUtil") protected hashUtil: HashUtil, @inject("JsonUtil") protected jsonUtil: JsonUtil, @inject("PrimaryLogger") protected logger: ILogger, - ) - { - if (!this.vfs.exists(this.modCachePath)) - { + ) { + if (!this.vfs.exists(this.modCachePath)) { this.vfs.writeFile(this.modCachePath, "{}"); } this.modHashes = this.jsonUtil.deserialize(this.vfs.readFile(this.modCachePath), this.modCachePath); } - public getStoredValue(key: string): string - { + public getStoredValue(key: string): string { return this.modHashes[key]; } - public storeValue(key: string, value: string): void - { + public storeValue(key: string, value: string): void { this.modHashes[key] = value; this.vfs.writeFile(this.modCachePath, this.jsonUtil.serialize(this.modHashes)); @@ -39,20 +34,17 @@ export class ModHashCacheService this.logger.debug(`Mod ${key} hash stored in ${this.modCachePath}`); } - public matchWithStoredHash(modName: string, hash: string): boolean - { + public matchWithStoredHash(modName: string, hash: string): boolean { return this.getStoredValue(modName) === hash; } - public calculateAndCompareHash(modName: string, modContent: string): boolean - { + public calculateAndCompareHash(modName: string, modContent: string): boolean { const generatedHash = this.hashUtil.generateSha1ForData(modContent); return this.matchWithStoredHash(modName, generatedHash); } - public calculateAndStoreHash(modName: string, modContent: string): void - { + public calculateAndStoreHash(modName: string, modContent: string): void { const generatedHash = this.hashUtil.generateSha1ForData(modContent); this.storeValue(modName, generatedHash); diff --git a/project/src/services/mod/CustomItemService.ts b/project/src/services/mod/CustomItemService.ts index 12aed0cc..92f2a36d 100644 --- a/project/src/services/mod/CustomItemService.ts +++ b/project/src/services/mod/CustomItemService.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { ItemHelper } from "@spt/helpers/ItemHelper"; import { ITemplateItem, Props } from "@spt/models/eft/common/tables/ITemplateItem"; import { BaseClasses } from "@spt/models/enums/BaseClasses"; @@ -12,12 +11,12 @@ import { import { ILogger } from "@spt/models/spt/utils/ILogger"; import { DatabaseService } from "@spt/services/DatabaseService"; import { ItemBaseClassService } from "@spt/services/ItemBaseClassService"; -import { ICloner } from "@spt/utils/cloners/ICloner"; import { HashUtil } from "@spt/utils/HashUtil"; +import { ICloner } from "@spt/utils/cloners/ICloner"; +import { inject, injectable } from "tsyringe"; @injectable() -export class CustomItemService -{ +export class CustomItemService { constructor( @inject("PrimaryLogger") protected logger: ILogger, @inject("HashUtil") protected hashUtil: HashUtil, @@ -25,9 +24,7 @@ export class CustomItemService @inject("ItemHelper") protected itemHelper: ItemHelper, @inject("ItemBaseClassService") protected itemBaseClassService: ItemBaseClassService, @inject("PrimaryCloner") protected cloner: ICloner, - ) - { - } + ) {} /** * Create a new item from a cloned item base @@ -39,8 +36,7 @@ export class CustomItemService * @param newItemDetails Item details for the new item to be created * @returns tplId of the new item created */ - public createItemFromClone(newItemDetails: NewItemFromCloneDetails): CreateItemResult - { + public createItemFromClone(newItemDetails: NewItemFromCloneDetails): CreateItemResult { const result = new CreateItemResult(); const tables = this.databaseService.getTables(); @@ -48,8 +44,7 @@ export class CustomItemService const newItemId = this.getOrGenerateIdForItem(newItemDetails.newId); // Fail if itemId already exists - if (tables.templates.items[newItemId]) - { + if (tables.templates.items[newItemId]) { result.errors.push(`ItemId already exists. ${tables.templates.items[newItemId]._name}`); result.success = false; result.itemId = newItemId; @@ -76,8 +71,7 @@ export class CustomItemService this.itemBaseClassService.hydrateItemBaseClassCache(); - if (this.itemHelper.isOfBaseclass(itemClone._id, BaseClasses.WEAPON)) - { + if (this.itemHelper.isOfBaseclass(itemClone._id, BaseClasses.WEAPON)) { this.addToWeaponShelf(newItemId); } @@ -96,16 +90,14 @@ export class CustomItemService * @param newItemDetails Details on what the item to be created * @returns CreateItemResult containing the completed items Id */ - public createItem(newItemDetails: NewItemDetails): CreateItemResult - { + public createItem(newItemDetails: NewItemDetails): CreateItemResult { const result = new CreateItemResult(); const tables = this.databaseService.getTables(); const newItem = newItemDetails.newItem; // Fail if itemId already exists - if (tables.templates.items[newItem._id]) - { + if (tables.templates.items[newItem._id]) { result.errors.push(`ItemId already exists. ${tables.templates.items[newItem._id]._name}`); return result; } @@ -120,8 +112,7 @@ export class CustomItemService this.itemBaseClassService.hydrateItemBaseClassCache(); - if (this.itemHelper.isOfBaseclass(newItem._id, BaseClasses.WEAPON)) - { + if (this.itemHelper.isOfBaseclass(newItem._id, BaseClasses.WEAPON)) { this.addToWeaponShelf(newItem._id); } @@ -136,8 +127,7 @@ export class CustomItemService * @param newId id supplied to code * @returns item id */ - protected getOrGenerateIdForItem(newId: string): string - { + protected getOrGenerateIdForItem(newId: string): string { return newId === "" ? this.hashUtil.generate() : newId; } @@ -147,10 +137,8 @@ export class CustomItemService * @param overrideProperties new properties to apply * @param itemClone item to update */ - protected updateBaseItemPropertiesWithOverrides(overrideProperties: Props, itemClone: ITemplateItem): void - { - for (const propKey in overrideProperties) - { + protected updateBaseItemPropertiesWithOverrides(overrideProperties: Props, itemClone: ITemplateItem): void { + for (const propKey in overrideProperties) { itemClone._props[propKey] = overrideProperties[propKey]; } } @@ -160,8 +148,7 @@ export class CustomItemService * @param newItemId id of the item to add to items.json * @param itemToAdd Item to add against the new id */ - protected addToItemsDb(newItemId: string, itemToAdd: ITemplateItem): void - { + protected addToItemsDb(newItemId: string, itemToAdd: ITemplateItem): void { this.databaseService.getItems()[newItemId] = itemToAdd; } @@ -171,9 +158,10 @@ export class CustomItemService * @param parentId parent id of the item being added * @param priceRoubles price of the item being added */ - protected addToHandbookDb(newItemId: string, parentId: string, priceRoubles: number): void - { - this.databaseService.getTemplates().handbook.Items.push({ Id: newItemId, ParentId: parentId, Price: priceRoubles }); + protected addToHandbookDb(newItemId: string, parentId: string, priceRoubles: number): void { + this.databaseService + .getTemplates() + .handbook.Items.push({ Id: newItemId, ParentId: parentId, Price: priceRoubles }); } /** @@ -187,15 +175,12 @@ export class CustomItemService * @param localeDetails key is language, value are the new locale details * @param newItemId id of the item being created */ - protected addToLocaleDbs(localeDetails: Record, newItemId: string): void - { + protected addToLocaleDbs(localeDetails: Record, newItemId: string): void { const languages = this.databaseService.getLocales().languages; - for (const shortNameKey in languages) - { + for (const shortNameKey in languages) { // Get locale details passed in, if not provided by caller use first record in newItemDetails.locales let newLocaleDetails = localeDetails[shortNameKey]; - if (!newLocaleDetails) - { + if (!newLocaleDetails) { newLocaleDetails = localeDetails[Object.keys(localeDetails)[0]]; } @@ -212,8 +197,7 @@ export class CustomItemService * @param newItemId id of the new item * @param fleaPriceRoubles Price of the new item */ - protected addToFleaPriceDb(newItemId: string, fleaPriceRoubles: number): void - { + protected addToFleaPriceDb(newItemId: string, fleaPriceRoubles: number): void { this.databaseService.getTemplates().prices[newItemId] = fleaPriceRoubles; } @@ -221,15 +205,16 @@ export class CustomItemService * Add a weapon to the hideout weapon shelf whitelist * @param newItemId Weapon id to add */ - protected addToWeaponShelf(newItemId: string): void - { + protected addToWeaponShelf(newItemId: string): void { // Ids for wall stashes in db - const wallStashIds = [ItemTpl.HIDEOUTAREACONTAINER_WEAPONSTAND_STASH_1, ItemTpl.HIDEOUTAREACONTAINER_WEAPONSTAND_STASH_2, ItemTpl.HIDEOUTAREACONTAINER_WEAPONSTAND_STASH_3]; - for (const wallId of wallStashIds) - { + const wallStashIds = [ + ItemTpl.HIDEOUTAREACONTAINER_WEAPONSTAND_STASH_1, + ItemTpl.HIDEOUTAREACONTAINER_WEAPONSTAND_STASH_2, + ItemTpl.HIDEOUTAREACONTAINER_WEAPONSTAND_STASH_3, + ]; + for (const wallId of wallStashIds) { const wall = this.itemHelper.getItem(wallId); - if (wall[0]) - { + if (wall[0]) { wall[1]._props.Grids[0]._props.filters[0].Filter.push(newItemId); } } @@ -241,11 +226,9 @@ export class CustomItemService * @param weaponWeight The weighting for the weapon to be picked vs other weapons * @param weaponSlot The slot the weapon should be added to (e.g. FirstPrimaryWeapon/SecondPrimaryWeapon/Holster) */ - public addCustomWeaponToPMCs(weaponTpl: string, weaponWeight: number, weaponSlot: string): void - { + public addCustomWeaponToPMCs(weaponTpl: string, weaponWeight: number, weaponSlot: string): void { const weapon = this.itemHelper.getItem(weaponTpl); - if (!weapon[0]) - { + if (!weapon[0]) { this.logger.warning( `Unable to add custom weapon ${weaponTpl} to PMCs as it cannot be found in the Item db`, ); @@ -256,8 +239,7 @@ export class CustomItemService // Get all slots weapon has and create a dictionary of them with possible mods that slot into each const weaponSlots = weapon[1]._props.Slots; - for (const slot of weaponSlots) - { + for (const slot of weaponSlots) { baseWeaponModObject[slot._name] = slot._props.filters[0].Filter; } diff --git a/project/src/services/mod/dynamicRouter/DynamicRouterMod.ts b/project/src/services/mod/dynamicRouter/DynamicRouterMod.ts index 65b9e928..770726f6 100644 --- a/project/src/services/mod/dynamicRouter/DynamicRouterMod.ts +++ b/project/src/services/mod/dynamicRouter/DynamicRouterMod.ts @@ -1,17 +1,14 @@ import { DynamicRouter, RouteAction } from "@spt/di/Router"; -export class DynamicRouterMod extends DynamicRouter -{ +export class DynamicRouterMod extends DynamicRouter { public constructor( routes: RouteAction[], private topLevelRoute: string, - ) - { + ) { super(routes); } - public override getTopLevelRoute(): string - { + public override getTopLevelRoute(): string { return this.topLevelRoute; } } diff --git a/project/src/services/mod/dynamicRouter/DynamicRouterModService.ts b/project/src/services/mod/dynamicRouter/DynamicRouterModService.ts index e300bb4e..778ff122 100644 --- a/project/src/services/mod/dynamicRouter/DynamicRouterModService.ts +++ b/project/src/services/mod/dynamicRouter/DynamicRouterModService.ts @@ -1,15 +1,12 @@ -import { DependencyContainer, injectable } from "tsyringe"; import { RouteAction } from "@spt/di/Router"; import { DynamicRouterMod } from "@spt/services/mod/dynamicRouter/DynamicRouterMod"; +import { DependencyContainer, injectable } from "tsyringe"; @injectable() -export class DynamicRouterModService -{ - constructor(private container: DependencyContainer) - {} +export class DynamicRouterModService { + constructor(private container: DependencyContainer) {} - public registerDynamicRouter(name: string, routes: RouteAction[], topLevelRoute: string): void - { + public registerDynamicRouter(name: string, routes: RouteAction[], topLevelRoute: string): void { this.container.register(name, { useValue: new DynamicRouterMod(routes, topLevelRoute) }); this.container.registerType("DynamicRoutes", name); } diff --git a/project/src/services/mod/httpListener/HttpListenerMod.ts b/project/src/services/mod/httpListener/HttpListenerMod.ts index bf563e19..648708bf 100644 --- a/project/src/services/mod/httpListener/HttpListenerMod.ts +++ b/project/src/services/mod/httpListener/HttpListenerMod.ts @@ -1,21 +1,17 @@ import { IncomingMessage, ServerResponse } from "node:http"; import { IHttpListener } from "@spt/servers/http/IHttpListener"; -export class HttpListenerMod implements IHttpListener -{ +export class HttpListenerMod implements IHttpListener { public constructor( private canHandleOverride: (sessionId: string, req: IncomingMessage) => boolean, private handleOverride: (sessionId: string, req: IncomingMessage, resp: ServerResponse) => void, - ) - {} + ) {} - public canHandle(sessionId: string, req: IncomingMessage): boolean - { + public canHandle(sessionId: string, req: IncomingMessage): boolean { return this.canHandleOverride(sessionId, req); } - public async handle(sessionId: string, req: IncomingMessage, resp: ServerResponse): Promise - { + public async handle(sessionId: string, req: IncomingMessage, resp: ServerResponse): Promise { this.handleOverride(sessionId, req, resp); } } diff --git a/project/src/services/mod/httpListener/HttpListenerModService.ts b/project/src/services/mod/httpListener/HttpListenerModService.ts index a7086b7b..4d93edc7 100644 --- a/project/src/services/mod/httpListener/HttpListenerModService.ts +++ b/project/src/services/mod/httpListener/HttpListenerModService.ts @@ -1,20 +1,17 @@ import { IncomingMessage, ServerResponse } from "node:http"; -import { DependencyContainer, injectable } from "tsyringe"; import { IHttpListener } from "@spt/servers/http/IHttpListener"; import { HttpListenerMod } from "@spt/services/mod/httpListener/HttpListenerMod"; +import { DependencyContainer, injectable } from "tsyringe"; @injectable() -export class HttpListenerModService -{ - constructor(protected container: DependencyContainer) - {} +export class HttpListenerModService { + constructor(protected container: DependencyContainer) {} public registerHttpListener( name: string, canHandleOverride: (sessionId: string, req: IncomingMessage) => boolean, handleOverride: (sessionId: string, req: IncomingMessage, resp: ServerResponse) => void, - ): void - { + ): void { this.container.register(name, { useValue: new HttpListenerMod(canHandleOverride, handleOverride), }); diff --git a/project/src/services/mod/image/ImageRouteService.ts b/project/src/services/mod/image/ImageRouteService.ts index b5886b77..70c3c259 100644 --- a/project/src/services/mod/image/ImageRouteService.ts +++ b/project/src/services/mod/image/ImageRouteService.ts @@ -1,19 +1,15 @@ -export class ImageRouteService -{ +export class ImageRouteService { protected routes: Record = {}; - public addRoute(urlKey: string, route: string): void - { + public addRoute(urlKey: string, route: string): void { this.routes[urlKey] = route; } - public getByKey(urlKey: string): string - { + public getByKey(urlKey: string): string { return this.routes[urlKey]; } - public existsByKey(urlKey: string): boolean - { + public existsByKey(urlKey: string): boolean { return this.routes[urlKey] !== undefined; } } diff --git a/project/src/services/mod/onLoad/OnLoadMod.ts b/project/src/services/mod/onLoad/OnLoadMod.ts index 5cb2fbeb..c649d0f1 100644 --- a/project/src/services/mod/onLoad/OnLoadMod.ts +++ b/project/src/services/mod/onLoad/OnLoadMod.ts @@ -1,22 +1,18 @@ import { OnLoad } from "@spt/di/OnLoad"; -export class OnLoadMod implements OnLoad -{ +export class OnLoadMod implements OnLoad { public constructor( private onLoadOverride: () => void, private getRouteOverride: () => string, - ) - { + ) { // super(); } - public async onLoad(): Promise - { + public async onLoad(): Promise { return this.onLoadOverride(); } - public getRoute(): string - { + public getRoute(): string { return this.getRouteOverride(); } } diff --git a/project/src/services/mod/onLoad/OnLoadModService.ts b/project/src/services/mod/onLoad/OnLoadModService.ts index 03bbb267..8b4215d9 100644 --- a/project/src/services/mod/onLoad/OnLoadModService.ts +++ b/project/src/services/mod/onLoad/OnLoadModService.ts @@ -1,14 +1,11 @@ -import { DependencyContainer, injectable } from "tsyringe"; import { OnLoadMod } from "@spt/services/mod/onLoad/OnLoadMod"; +import { DependencyContainer, injectable } from "tsyringe"; @injectable() -export class OnLoadModService -{ - constructor(protected container: DependencyContainer) - {} +export class OnLoadModService { + constructor(protected container: DependencyContainer) {} - public registerOnLoad(name: string, onLoad: () => void, getRoute: () => string): void - { + public registerOnLoad(name: string, onLoad: () => void, getRoute: () => string): void { this.container.register(name, { useValue: new OnLoadMod(onLoad, getRoute) }); this.container.registerType("OnLoad", name); } diff --git a/project/src/services/mod/onUpdate/OnUpdateMod.ts b/project/src/services/mod/onUpdate/OnUpdateMod.ts index 50b7b3a8..4a44727a 100644 --- a/project/src/services/mod/onUpdate/OnUpdateMod.ts +++ b/project/src/services/mod/onUpdate/OnUpdateMod.ts @@ -1,20 +1,16 @@ import { OnUpdate } from "@spt/di/OnUpdate"; -export class OnUpdateMod implements OnUpdate -{ +export class OnUpdateMod implements OnUpdate { public constructor( private onUpdateOverride: (timeSinceLastRun: number) => boolean, private getRouteOverride: () => string, - ) - {} + ) {} - public async onUpdate(timeSinceLastRun: number): Promise - { + public async onUpdate(timeSinceLastRun: number): Promise { return this.onUpdateOverride(timeSinceLastRun); } - public getRoute(): string - { + public getRoute(): string { return this.getRouteOverride(); } } diff --git a/project/src/services/mod/onUpdate/OnUpdateModService.ts b/project/src/services/mod/onUpdate/OnUpdateModService.ts index d8ce2e1e..031b733d 100644 --- a/project/src/services/mod/onUpdate/OnUpdateModService.ts +++ b/project/src/services/mod/onUpdate/OnUpdateModService.ts @@ -1,18 +1,15 @@ -import { DependencyContainer, injectable } from "tsyringe"; import { OnUpdateMod } from "@spt/services/mod/onUpdate/OnUpdateMod"; +import { DependencyContainer, injectable } from "tsyringe"; @injectable() -export class OnUpdateModService -{ - constructor(protected container: DependencyContainer) - {} +export class OnUpdateModService { + constructor(protected container: DependencyContainer) {} public registerOnUpdate( name: string, onUpdate: (timeSinceLastRun: number) => boolean, getRoute: () => string, - ): void - { + ): void { this.container.register(name, { useValue: new OnUpdateMod(onUpdate, getRoute) }); this.container.registerType("OnUpdate", name); } diff --git a/project/src/services/mod/staticRouter/StaticRouterMod.ts b/project/src/services/mod/staticRouter/StaticRouterMod.ts index b9002bff..94bb747c 100644 --- a/project/src/services/mod/staticRouter/StaticRouterMod.ts +++ b/project/src/services/mod/staticRouter/StaticRouterMod.ts @@ -1,17 +1,14 @@ import { RouteAction, StaticRouter } from "@spt/di/Router"; -export class StaticRouterMod extends StaticRouter -{ +export class StaticRouterMod extends StaticRouter { public constructor( routes: RouteAction[], private topLevelRoute: string, - ) - { + ) { super(routes); } - public override getTopLevelRoute(): string - { + public override getTopLevelRoute(): string { return this.topLevelRoute; } } diff --git a/project/src/services/mod/staticRouter/StaticRouterModService.ts b/project/src/services/mod/staticRouter/StaticRouterModService.ts index 9afd6afe..f57d2e37 100644 --- a/project/src/services/mod/staticRouter/StaticRouterModService.ts +++ b/project/src/services/mod/staticRouter/StaticRouterModService.ts @@ -1,15 +1,12 @@ -import { DependencyContainer, injectable } from "tsyringe"; import { RouteAction } from "@spt/di/Router"; import { StaticRouterMod } from "@spt/services/mod/staticRouter/StaticRouterMod"; +import { DependencyContainer, injectable } from "tsyringe"; @injectable() -export class StaticRouterModService -{ - constructor(protected container: DependencyContainer) - {} +export class StaticRouterModService { + constructor(protected container: DependencyContainer) {} - public registerStaticRouter(name: string, routes: RouteAction[], topLevelRoute: string): void - { + public registerStaticRouter(name: string, routes: RouteAction[], topLevelRoute: string): void { this.container.register(name, { useValue: new StaticRouterMod(routes, topLevelRoute) }); this.container.registerType("StaticRoutes", name); } diff --git a/project/src/tools/ItemTplGenerator/ItemTplGenerator.ts b/project/src/tools/ItemTplGenerator/ItemTplGenerator.ts index 14d4b6d6..700a9b8d 100644 --- a/project/src/tools/ItemTplGenerator/ItemTplGenerator.ts +++ b/project/src/tools/ItemTplGenerator/ItemTplGenerator.ts @@ -25,7 +25,6 @@ import * as fs from "fs"; import * as path from "path"; -import { inject, injectAll, injectable } from "tsyringe"; import { OnLoad } from "@spt/di/OnLoad"; import { ItemHelper } from "@spt/helpers/ItemHelper"; import { ITemplateItem } from "@spt/models/eft/common/tables/ITemplateItem"; @@ -36,10 +35,10 @@ import { ILogger } from "@spt/models/spt/utils/ILogger"; import { DatabaseServer } from "@spt/servers/DatabaseServer"; import { LocaleService } from "@spt/services/LocaleService"; import * as itemTplOverrides from "@spt/tools/ItemTplGenerator/itemOverrides"; +import { inject, injectAll, injectable } from "tsyringe"; @injectable() -export class ItemTplGenerator -{ +export class ItemTplGenerator { private enumDir: string; private items: Record; private itemOverrides: Record; @@ -51,14 +50,11 @@ export class ItemTplGenerator @inject("PrimaryLogger") protected logger: ILogger, @inject("ItemHelper") protected itemHelper: ItemHelper, @injectAll("OnLoad") protected onLoadComponents: OnLoad[], - ) - {} + ) {} - async run(): Promise - { + async run(): Promise { // Load all of the onload components, this gives us access to most of SPTs injections - for (const onLoad of this.onLoadComponents) - { + for (const onLoad of this.onLoadComponents) { await onLoad.onLoad(); } @@ -90,11 +86,9 @@ export class ItemTplGenerator * Return an object containing all items in the game with a generated name * @returns An object containing a generated item name to item ID association */ - private generateItemsObject(): Record - { + private generateItemsObject(): Record { const itemsObject = {}; - for (const item of Object.values(this.items)) - { + for (const item of Object.values(this.items)) { // Skip invalid items (Non-Item types, and shrapnel) if (!this.isValidItem(item)) continue; @@ -104,22 +98,18 @@ export class ItemTplGenerator const itemSuffix = this.getItemSuffix(item); // Handle the case where the item starts with the parent category name. Avoids things like 'POCKETS_POCKETS' - if (itemParentName == itemName.substring(1, itemParentName.length + 1) && itemPrefix == "") - { + if (itemParentName == itemName.substring(1, itemParentName.length + 1) && itemPrefix == "") { itemName = itemName.substring(itemParentName.length + 1); - if (itemName.length > 0 && itemName.at(0) != "_") - { + if (itemName.length > 0 && itemName.at(0) != "_") { itemName = `_${itemName}`; } } // Handle the case where the item ends with the parent category name. Avoids things like 'KEY_DORM_ROOM_103_KEY' - if (itemParentName === itemName.substring(itemName.length - itemParentName.length)) - { + if (itemParentName === itemName.substring(itemName.length - itemParentName.length)) { itemName = itemName.substring(0, itemName.length - itemParentName.length); - if (itemName.substring(itemName.length - 1) === "_") - { + if (itemName.substring(itemName.length - 1) === "_") { itemName = itemName.substring(0, itemName.length - 1); } } @@ -130,21 +120,17 @@ export class ItemTplGenerator itemKey = this.sanitizeEnumKey(itemKey); // If the key already exists, see if we can add a suffix to both this, and the existing conflicting item - if (Object.keys(itemsObject).includes(itemKey) || this.collidedEnumKeys.includes(itemKey)) - { + if (Object.keys(itemsObject).includes(itemKey) || this.collidedEnumKeys.includes(itemKey)) { // Keep track, so we can handle 3+ conflicts this.collidedEnumKeys.push(itemKey); const itemNameSuffix = this.getItemNameSuffix(item); - if (itemNameSuffix) - { + if (itemNameSuffix) { // Try to update the old key reference if we haven't already - if (itemsObject[itemKey]) - { + if (itemsObject[itemKey]) { const oldItemId = itemsObject[itemKey]; const oldItemNameSuffix = this.getItemNameSuffix(this.items[oldItemId]); - if (oldItemNameSuffix) - { + if (oldItemNameSuffix) { const oldItemNewKey = this.sanitizeEnumKey(`${itemKey}_${oldItemNameSuffix}`); delete itemsObject[itemKey]; itemsObject[oldItemNewKey] = oldItemId; @@ -154,15 +140,12 @@ export class ItemTplGenerator itemKey = this.sanitizeEnumKey(`${itemKey}_${itemNameSuffix}`); // If we still collide, log an error - if (Object.keys(itemsObject).includes(itemKey)) - { + if (Object.keys(itemsObject).includes(itemKey)) { this.logger.error( `After rename, itemsObject already contains ${itemKey} ${itemsObject[itemKey]} => ${item._id}`, ); } - } - else - { + } else { this.logger.error( `New itemOverride entry required: itemsObject already contains ${itemKey} ${itemsObject[itemKey]} => ${item._id}`, ); @@ -176,8 +159,7 @@ export class ItemTplGenerator // Sort the items object const orderedItemsObject = Object.keys(itemsObject) .sort() - .reduce((obj, key) => - { + .reduce((obj, key) => { obj[key] = itemsObject[key]; return obj; }, {}); @@ -190,13 +172,10 @@ export class ItemTplGenerator * @param orderedItemsObject The previously generated object of item name to item ID associations * @returns */ - private generateWeaponsObject(): Record - { + private generateWeaponsObject(): Record { const weaponsObject = {}; - for (const [itemId, item] of Object.entries(this.items)) - { - if (!this.itemHelper.isOfBaseclass(itemId, BaseClasses.WEAPON)) - { + for (const [itemId, item] of Object.entries(this.items)) { + if (!this.itemHelper.isOfBaseclass(itemId, BaseClasses.WEAPON)) { continue; } @@ -204,16 +183,14 @@ export class ItemTplGenerator let weaponShortName = this.localeService.getLocaleDb()[`${itemId} ShortName`]?.toUpperCase(); // Special case for the weird duplicated grenade launcher - if (itemId === "639c3fbbd0446708ee622ee9") - { + if (itemId === "639c3fbbd0446708ee622ee9") { weaponShortName = "FN40GL_2"; } // Include any bracketed suffixes that exist, handles the case of colored gun variants const weaponFullName = this.localeService.getLocaleDb()[`${itemId} Name`]?.toUpperCase(); const itemNameBracketSuffix = weaponFullName.match(/\((.+?)\)$/); - if (itemNameBracketSuffix && !weaponShortName.endsWith(itemNameBracketSuffix[1])) - { + if (itemNameBracketSuffix && !weaponShortName.endsWith(itemNameBracketSuffix[1])) { weaponShortName += `_${itemNameBracketSuffix[1]}`; } @@ -225,8 +202,7 @@ export class ItemTplGenerator .replace(/[^a-zA-Z0-9_]/g, "") .toUpperCase(); - if (weaponsObject[weaponName]) - { + if (weaponsObject[weaponName]) { this.logger.error(`Error, weapon ${weaponName} already exists`); continue; } @@ -237,8 +213,7 @@ export class ItemTplGenerator // Sort the weapons object const orderedWeaponsObject = Object.keys(weaponsObject) .sort() - .reduce((obj, key) => - { + .reduce((obj, key) => { obj[key] = weaponsObject[key]; return obj; }, {}); @@ -251,60 +226,39 @@ export class ItemTplGenerator * @param enumKey The enum key to sanitize * @returns The sanitized enum key */ - private sanitizeEnumKey(enumKey: string): string - { + private sanitizeEnumKey(enumKey: string): string { return enumKey .toUpperCase() .replace(/[^A-Z0-9_]/g, "") .replace(/_+/g, "_"); } - private getParentName(item: ITemplateItem): string - { - if (item._props.QuestItem) - { + private getParentName(item: ITemplateItem): string { + if (item._props.QuestItem) { return "QUEST"; - } - else if (this.itemHelper.isOfBaseclass(item._id, BaseClasses.BARTER_ITEM)) - { + } else if (this.itemHelper.isOfBaseclass(item._id, BaseClasses.BARTER_ITEM)) { return "BARTER"; - } - else if (this.itemHelper.isOfBaseclass(item._id, BaseClasses.THROW_WEAPON)) - { + } else if (this.itemHelper.isOfBaseclass(item._id, BaseClasses.THROW_WEAPON)) { return "GRENADE"; - } - else if (this.itemHelper.isOfBaseclass(item._id, BaseClasses.STIMULATOR)) - { + } else if (this.itemHelper.isOfBaseclass(item._id, BaseClasses.STIMULATOR)) { return "STIM"; - } - else if (this.itemHelper.isOfBaseclass(item._id, BaseClasses.MAGAZINE)) - { + } else if (this.itemHelper.isOfBaseclass(item._id, BaseClasses.MAGAZINE)) { return "MAGAZINE"; - } - else if (this.itemHelper.isOfBaseclass(item._id, BaseClasses.KEY_MECHANICAL)) - { + } else if (this.itemHelper.isOfBaseclass(item._id, BaseClasses.KEY_MECHANICAL)) { return "KEY"; - } - else if (this.itemHelper.isOfBaseclass(item._id, BaseClasses.MOB_CONTAINER)) - { + } else if (this.itemHelper.isOfBaseclass(item._id, BaseClasses.MOB_CONTAINER)) { return "SECURE"; - } - else if (this.itemHelper.isOfBaseclass(item._id, BaseClasses.SIMPLE_CONTAINER)) - { + } else if (this.itemHelper.isOfBaseclass(item._id, BaseClasses.SIMPLE_CONTAINER)) { return "CONTAINER"; - } - else if (this.itemHelper.isOfBaseclass(item._id, BaseClasses.PORTABLE_RANGE_FINDER)) - { + } else if (this.itemHelper.isOfBaseclass(item._id, BaseClasses.PORTABLE_RANGE_FINDER)) { return "RANGEFINDER"; } // Why are flares grenade launcher...? - else if (item._name.startsWith("weapon_rsp30")) - { + else if (item._name.startsWith("weapon_rsp30")) { return "FLARE"; } // This is a special case for the signal pistol, I'm not adding it as a Grenade Launcher - else if (item._id == "620109578d82e67e7911abf2") - { + else if (item._id == "620109578d82e67e7911abf2") { return "SIGNALPISTOL"; } @@ -312,17 +266,14 @@ export class ItemTplGenerator return this.items[parentId]._name.toUpperCase(); } - private isValidItem(item: ITemplateItem): boolean - { + private isValidItem(item: ITemplateItem): boolean { const shrapnelId = "5943d9c186f7745a13413ac9"; - if (item._type !== "Item") - { + if (item._type !== "Item") { return false; } - if (item._proto === shrapnelId) - { + if (item._proto === shrapnelId) { return false; } @@ -334,74 +285,62 @@ export class ItemTplGenerator * @param item The item to generate the prefix for * @returns The prefix of the given item */ - private getItemPrefix(item: ITemplateItem): string - { + private getItemPrefix(item: ITemplateItem): string { let prefix = ""; // Prefix ammo with its caliber - if (this.itemHelper.isOfBaseclass(item._id, BaseClasses.AMMO)) - { + if (this.itemHelper.isOfBaseclass(item._id, BaseClasses.AMMO)) { prefix = this.getAmmoPrefix(item); } // Prefix ammo boxes with their caliber - else if (this.itemHelper.isOfBaseclass(item._id, BaseClasses.AMMO_BOX)) - { + else if (this.itemHelper.isOfBaseclass(item._id, BaseClasses.AMMO_BOX)) { prefix = this.getAmmoBoxPrefix(item); } // Prefix magazines with their caliber - else if (this.itemHelper.isOfBaseclass(item._id, BaseClasses.MAGAZINE)) - { + else if (this.itemHelper.isOfBaseclass(item._id, BaseClasses.MAGAZINE)) { prefix = this.getMagazinePrefix(item); } // Make sure there's an underscore separator - if (prefix.length > 0 && prefix.at(0) != "_") - { + if (prefix.length > 0 && prefix.at(0) != "_") { prefix = `_${prefix}`; } return prefix; } - private getItemSuffix(item: ITemplateItem): string - { + private getItemSuffix(item: ITemplateItem): string { let suffix = ""; // Add mag size for magazines - if (this.itemHelper.isOfBaseclass(item._id, BaseClasses.MAGAZINE)) - { + if (this.itemHelper.isOfBaseclass(item._id, BaseClasses.MAGAZINE)) { suffix = item._props.Cartridges![0]?._max_count?.toString() + "RND"; } // Add pack size for ammo boxes - else if (this.itemHelper.isOfBaseclass(item._id, BaseClasses.AMMO_BOX)) - { + else if (this.itemHelper.isOfBaseclass(item._id, BaseClasses.AMMO_BOX)) { suffix = item._props.StackSlots![0]?._max_count.toString() + "RND"; } // Add "DAMAGED" for damaged items - if (item._name.toLowerCase().includes("damaged")) - { + if (item._name.toLowerCase().includes("damaged")) { suffix += "_DAMAGED"; } // Make sure there's an underscore separator - if (suffix.length > 0 && suffix.at(0) != "_") - { + if (suffix.length > 0 && suffix.at(0) != "_") { suffix = `_${suffix}`; } return suffix; } - private getAmmoPrefix(item: ITemplateItem): string - { + private getAmmoPrefix(item: ITemplateItem): string { const prefix = item._props.Caliber!.toUpperCase(); return this.cleanCaliber(prefix); } - private cleanCaliber(ammoCaliber: string): string - { + private cleanCaliber(ammoCaliber: string): string { ammoCaliber = ammoCaliber.replace("CALIBER", ""); ammoCaliber = ammoCaliber.replace("PARA", ""); ammoCaliber = ammoCaliber.replace("NATO", ""); @@ -412,15 +351,13 @@ export class ItemTplGenerator return ammoCaliber; } - private getAmmoBoxPrefix(item: ITemplateItem): string - { + private getAmmoBoxPrefix(item: ITemplateItem): string { const ammoItem = item._props.StackSlots![0]?._props.filters[0].Filter[0]; return this.getAmmoPrefix(this.items[ammoItem]); } - private getMagazinePrefix(item: ITemplateItem): string - { + private getMagazinePrefix(item: ITemplateItem): string { const ammoItem = item._props.Cartridges![0]?._props.filters[0].Filter[0]; return this.getAmmoPrefix(this.items[ammoItem]); @@ -431,13 +368,11 @@ export class ItemTplGenerator * @param item The item to generate the name for * @returns The name of the given item */ - private getItemName(item) - { + private getItemName(item) { let itemName; // Manual item name overrides - if (this.itemOverrides[item._id]) - { + if (this.itemOverrides[item._id]) { itemName = this.itemOverrides[item._id].toUpperCase(); } // For the listed types, user the item's _name property @@ -447,35 +382,29 @@ export class ItemTplGenerator BaseClasses.BUILT_IN_INSERTS, BaseClasses.STASH, ]) - ) - { + ) { itemName = item._name.toUpperCase(); } // For the listed types, use the short name else if ( this.itemHelper.isOfBaseclasses(item._id, [BaseClasses.AMMO, BaseClasses.AMMO_BOX, BaseClasses.MAGAZINE]) - ) - { + ) { itemName = this.localeService.getLocaleDb()[`${item._id} ShortName`]?.toUpperCase(); } // For everything else, use the full name - else - { + else { itemName = this.localeService.getLocaleDb()[`${item._id} Name`]?.toUpperCase(); } // Fall back in the event we couldn't find a name - if (!itemName) - { + if (!itemName) { itemName = this.localeService.getLocaleDb()[`${item._id} Name`]?.toUpperCase(); } - if (!itemName) - { + if (!itemName) { itemName = item._name.toUpperCase(); } - if (!itemName) - { + if (!itemName) { console.log(`Unable to get shortname for ${item._id}`); return ""; } @@ -486,25 +415,21 @@ export class ItemTplGenerator return `_${itemName}`; } - private getItemNameSuffix(item: ITemplateItem): string - { + private getItemNameSuffix(item: ITemplateItem): string { const itemName = this.localeService.getLocaleDb()[`${item._id} Name`]; // Add grid size for lootable containers - if (this.itemHelper.isOfBaseclass(item._id, BaseClasses.LOOT_CONTAINER)) - { + if (this.itemHelper.isOfBaseclass(item._id, BaseClasses.LOOT_CONTAINER)) { return `${item._props.Grids![0]?._props.cellsH}X${item._props.Grids![0]?._props.cellsV}`; } // Add ammo caliber to conflicting weapons - if (this.itemHelper.isOfBaseclass(item._id, BaseClasses.WEAPON)) - { + if (this.itemHelper.isOfBaseclass(item._id, BaseClasses.WEAPON)) { const caliber = this.cleanCaliber(item._props.ammoCaliber!.toUpperCase()); // If the item has a bracketed section at the end of its name, include that const itemNameBracketSuffix = itemName?.match(/\((.+?)\)$/); - if (itemNameBracketSuffix) - { + if (itemNameBracketSuffix) { return `${caliber}_${itemNameBracketSuffix[1]}`; } @@ -512,42 +437,35 @@ export class ItemTplGenerator } // Make sure we have a full name - if (!itemName) - { + if (!itemName) { return ""; } // If the item has a bracketed section at the end of its name, use that const itemNameBracketSuffix = itemName.match(/\((.+?)\)$/); - if (itemNameBracketSuffix) - { + if (itemNameBracketSuffix) { return itemNameBracketSuffix[1]; } // If the item has a number at the end of its name, use that const itemNameNumberSuffix = itemName.match(/#([0-9]+)$/); - if (itemNameNumberSuffix) - { + if (itemNameNumberSuffix) { return itemNameNumberSuffix[1]; } return ""; } - private logEnumValueChanges(data: Record, enumName: string, originalEnum: Record) - { + private logEnumValueChanges(data: Record, enumName: string, originalEnum: Record) { // First generate a mapping of the original enum values to names const originalEnumValues = {}; - for (const [key, value] of Object.entries(originalEnum)) - { + for (const [key, value] of Object.entries(originalEnum)) { originalEnumValues[value as string] = key; } // Loop through our new data, and find any where the given ID's name doesn't match the original enum - for (const [dataKey, dataValue] of Object.entries(data)) - { - if (originalEnumValues[dataValue] && originalEnumValues[dataValue] !== dataKey) - { + for (const [dataKey, dataValue] of Object.entries(data)) { + if (originalEnumValues[dataValue] && originalEnumValues[dataValue] !== dataKey) { this.logger.warning( `Enum ${enumName} key has changed for ${dataValue}, ${originalEnumValues[dataValue]} => ${dataKey}`, ); @@ -555,16 +473,13 @@ export class ItemTplGenerator } } - private writeEnumsToFile(outputPath: string, enumEntries: Record>): void - { + private writeEnumsToFile(outputPath: string, enumEntries: Record>): void { let enumFileData = "// This is an auto generated file, do not modify. Re-generate with `npm run gen:items`"; - for (const [enumName, data] of Object.entries(enumEntries)) - { + for (const [enumName, data] of Object.entries(enumEntries)) { enumFileData += `\nexport enum ${enumName}\n{\n`; - for (const [key, value] of Object.entries(data)) - { + for (const [key, value] of Object.entries(data)) { enumFileData += ` ${key} = "${value}",\n`; } diff --git a/project/src/tools/ItemTplGenerator/ItemTplGeneratorProgram.ts b/project/src/tools/ItemTplGenerator/ItemTplGeneratorProgram.ts index b2c67426..06f57e06 100644 --- a/project/src/tools/ItemTplGenerator/ItemTplGeneratorProgram.ts +++ b/project/src/tools/ItemTplGenerator/ItemTplGeneratorProgram.ts @@ -1,26 +1,22 @@ import "reflect-metadata"; import "source-map-support/register"; -import { Lifecycle, container } from "tsyringe"; -import { Container } from "@spt/di/Container"; import { ErrorHandler } from "@spt/ErrorHandler"; +import { Container } from "@spt/di/Container"; import { ItemTplGenerator } from "@spt/tools/ItemTplGenerator/ItemTplGenerator"; +import { Lifecycle, container } from "tsyringe"; -export class ItemTplGeneratorProgram -{ +export class ItemTplGeneratorProgram { private errorHandler: ErrorHandler; - constructor() - { + constructor() { // set window properties process.stdout.setEncoding("utf8"); process.title = "SPT ItemTplGenerator"; this.errorHandler = new ErrorHandler(); } - public async start(): Promise - { - try - { + public async start(): Promise { + try { Container.registerTypes(container); const childContainer = container.createChildContainer(); childContainer.register("ItemTplGenerator", ItemTplGenerator, { @@ -29,9 +25,7 @@ export class ItemTplGeneratorProgram Container.registerListTypes(childContainer); Container.registerPostLoadTypes(container, childContainer); await childContainer.resolve("ItemTplGenerator").run(); - } - catch (err: any) - { + } catch (err: any) { this.errorHandler.handleCriticalError(err instanceof Error ? err : new Error(err)); } diff --git a/project/src/tools/ItemTplGenerator/itemOverrides.ts b/project/src/tools/ItemTplGenerator/itemOverrides.ts index 12ddbebf..f3eba6c3 100644 --- a/project/src/tools/ItemTplGenerator/itemOverrides.ts +++ b/project/src/tools/ItemTplGenerator/itemOverrides.ts @@ -1,4 +1,3 @@ - /** * An object containing item name overrides for use with ItemTplGenerator */ diff --git a/project/src/utils/App.ts b/project/src/utils/App.ts index 5248d058..27f563e4 100644 --- a/project/src/utils/App.ts +++ b/project/src/utils/App.ts @@ -1,5 +1,4 @@ import os from "node:os"; -import { inject, injectAll, injectable } from "tsyringe"; import { OnLoad } from "@spt/di/OnLoad"; import { OnUpdate } from "@spt/di/OnUpdate"; import { ConfigTypes } from "@spt/models/enums/ConfigTypes"; @@ -10,10 +9,10 @@ import { HttpServer } from "@spt/servers/HttpServer"; import { LocalisationService } from "@spt/services/LocalisationService"; import { EncodingUtil } from "@spt/utils/EncodingUtil"; import { TimeUtil } from "@spt/utils/TimeUtil"; +import { inject, injectAll, injectable } from "tsyringe"; @injectable() -export class App -{ +export class App { protected onUpdateLastRun = {}; protected coreConfig: ICoreConfig; @@ -26,13 +25,11 @@ export class App @inject("HttpServer") protected httpServer: HttpServer, @injectAll("OnLoad") protected onLoadComponents: OnLoad[], @injectAll("OnUpdate") protected onUpdateComponents: OnUpdate[], - ) - { + ) { this.coreConfig = this.configServer.getConfig(ConfigTypes.CORE); } - public async load(): Promise - { + public async load(): Promise { // execute onLoad callbacks this.logger.info(this.localisationService.getText("executing_startup_callbacks")); @@ -42,61 +39,47 @@ export class App this.logger.debug(`PATH: ${this.encodingUtil.toBase64(process.argv[0])}`); this.logger.debug(`PATH: ${this.encodingUtil.toBase64(process.execPath)}`); this.logger.debug(`Server: ${globalThis.G_SPTVERSION || this.coreConfig.sptVersion}`); - if (globalThis.G_BUILDTIME) - { + if (globalThis.G_BUILDTIME) { this.logger.debug(`Date: ${globalThis.G_BUILDTIME}`); } - if (globalThis.G_COMMIT) - { + if (globalThis.G_COMMIT) { this.logger.debug(`Commit: ${globalThis.G_COMMIT}`); } - for (const onLoad of this.onLoadComponents) - { + for (const onLoad of this.onLoadComponents) { await onLoad.onLoad(); } - setInterval(() => - { + setInterval(() => { this.update(this.onUpdateComponents); }, 5000); } - protected async update(onUpdateComponents: OnUpdate[]): Promise - { + protected async update(onUpdateComponents: OnUpdate[]): Promise { // If the server has failed to start, skip any update calls - if (!this.httpServer.isStarted()) - { + if (!this.httpServer.isStarted()) { return; } - for (const updateable of onUpdateComponents) - { + for (const updateable of onUpdateComponents) { let success = false; const lastRunTimeTimestamp = this.onUpdateLastRun[updateable.getRoute()] || 0; // 0 on first load so all update() calls occur on first load const secondsSinceLastRun = this.timeUtil.getTimestamp() - lastRunTimeTimestamp; - try - { + try { success = await updateable.onUpdate(secondsSinceLastRun); - } - catch (err) - { + } catch (err) { this.logUpdateException(err, updateable); } - if (success) - { + if (success) { this.onUpdateLastRun[updateable.getRoute()] = this.timeUtil.getTimestamp(); - } - else - { + } else { /* temporary for debug */ const warnTime = 20 * 60; - if (success === void 0 && !(secondsSinceLastRun % warnTime)) - { + if (success === void 0 && !(secondsSinceLastRun % warnTime)) { this.logger.debug( this.localisationService.getText("route_onupdate_no_response", updateable.getRoute()), ); @@ -105,15 +88,12 @@ export class App } } - protected logUpdateException(err: any, updateable: OnUpdate): void - { + protected logUpdateException(err: any, updateable: OnUpdate): void { this.logger.error(this.localisationService.getText("scheduled_event_failed_to_run", updateable.getRoute())); - if (err.message) - { + if (err.message) { this.logger.error(err.message); } - if (err.stack) - { + if (err.stack) { this.logger.error(err.stack); } } diff --git a/project/src/utils/AsyncQueue.ts b/project/src/utils/AsyncQueue.ts index 31b82631..c1549d74 100644 --- a/project/src/utils/AsyncQueue.ts +++ b/project/src/utils/AsyncQueue.ts @@ -1,26 +1,21 @@ import { IAsyncQueue } from "@spt/models/spt/utils/IAsyncQueue"; import { ICommand } from "@spt/models/spt/utils/ICommand"; -export class AsyncQueue implements IAsyncQueue -{ +export class AsyncQueue implements IAsyncQueue { protected commandsQueue: ICommand[]; - constructor() - { + constructor() { this.commandsQueue = []; } // Wait for the right command to execute // This ensures that the commands execute in the right order, thus no data corruption - public async waitFor(command: ICommand): Promise - { + public async waitFor(command: ICommand): Promise { // Add to the queue this.commandsQueue.push(command); - while (this.commandsQueue[0].uuid !== command.uuid) - { - await new Promise((resolve) => - { + while (this.commandsQueue[0].uuid !== command.uuid) { + await new Promise((resolve) => { setTimeout(resolve, 100); }); } diff --git a/project/src/utils/CompareUtil.ts b/project/src/utils/CompareUtil.ts index 2bd62e74..f3797242 100644 --- a/project/src/utils/CompareUtil.ts +++ b/project/src/utils/CompareUtil.ts @@ -1,8 +1,7 @@ import { injectable } from "tsyringe"; @injectable() -export class CompareUtil -{ +export class CompareUtil { private static typesToCheckAgainst = new Set([ "string", "number", @@ -20,41 +19,32 @@ export class CompareUtil * @param v2 value 2 to compare * @returns true if equal, false if not */ - public recursiveCompare(v1: any, v2: any): boolean - { + public recursiveCompare(v1: any, v2: any): boolean { const typeOfv1 = typeof v1; const typeOfv2 = typeof v2; - if (CompareUtil.typesToCheckAgainst.has(typeOfv1)) - { + if (CompareUtil.typesToCheckAgainst.has(typeOfv1)) { return v1 === v2; } - if (typeOfv1 === "object" && typeOfv2 === "object") - { - if (Array.isArray(v1)) - { - if (!Array.isArray(v2)) - { + if (typeOfv1 === "object" && typeOfv2 === "object") { + if (Array.isArray(v1)) { + if (!Array.isArray(v2)) { return false; } const arr1 = v1 as Array; const arr2 = v2 as Array; - if (arr1.length !== arr2.length) - { + if (arr1.length !== arr2.length) { return false; } return arr1.every((vOf1) => arr2.find((vOf2) => this.recursiveCompare(vOf1, vOf2))); } - for (const propOf1 in v1) - { - if (v2[propOf1] === undefined) - { + for (const propOf1 in v1) { + if (v2[propOf1] === undefined) { return false; } return this.recursiveCompare(v1[propOf1], v2[propOf1]); } } - if (typeOfv1 === typeOfv2) - { + if (typeOfv1 === typeOfv2) { return v1 === v2; } diff --git a/project/src/utils/DatabaseImporter.ts b/project/src/utils/DatabaseImporter.ts index 2c1e154c..8ec58c3d 100644 --- a/project/src/utils/DatabaseImporter.ts +++ b/project/src/utils/DatabaseImporter.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from "tsyringe"; import { OnLoad } from "@spt/di/OnLoad"; import { ConfigTypes } from "@spt/models/enums/ConfigTypes"; import { IHttpConfig } from "@spt/models/spt/config/IHttpConfig"; @@ -13,10 +12,10 @@ import { HashUtil } from "@spt/utils/HashUtil"; import { ImporterUtil } from "@spt/utils/ImporterUtil"; import { JsonUtil } from "@spt/utils/JsonUtil"; import { VFS } from "@spt/utils/VFS"; +import { inject, injectable } from "tsyringe"; @injectable() -export class DatabaseImporter implements OnLoad -{ +export class DatabaseImporter implements OnLoad { private hashedFile: any; private valid = VaildationResult.UNDEFINED; private filepath: string; @@ -33,8 +32,7 @@ export class DatabaseImporter implements OnLoad @inject("HashUtil") protected hashUtil: HashUtil, @inject("ImporterUtil") protected importerUtil: ImporterUtil, @inject("ConfigServer") protected configServer: ConfigServer, - ) - { + ) { this.httpConfig = this.configServer.getConfig(ConfigTypes.HTTP); } @@ -42,37 +40,28 @@ export class DatabaseImporter implements OnLoad * Get path to spt data * @returns path to data */ - public getSptDataPath(): string - { + public getSptDataPath(): string { return globalThis.G_RELEASE_CONFIGURATION ? "SPT_Data/Server/" : "./assets/"; } - public async onLoad(): Promise - { + public async onLoad(): Promise { this.filepath = this.getSptDataPath(); - if (globalThis.G_RELEASE_CONFIGURATION) - { - try - { + if (globalThis.G_RELEASE_CONFIGURATION) { + try { // Reading the dynamic SHA1 file const file = "checks.dat"; const fileWithPath = `${this.filepath}${file}`; - if (this.vfs.exists(fileWithPath)) - { + if (this.vfs.exists(fileWithPath)) { this.hashedFile = this.jsonUtil.deserialize( this.encodingUtil.fromBase64(this.vfs.readFile(fileWithPath)), file, ); - } - else - { + } else { this.valid = VaildationResult.NOT_FOUND; this.logger.debug(this.localisationService.getText("validation_not_found")); } - } - catch (e) - { + } catch (e) { this.valid = VaildationResult.FAILED; this.logger.warning(this.localisationService.getText("validation_error_decode")); } @@ -97,8 +86,7 @@ export class DatabaseImporter implements OnLoad * Read all json files in database folder and map into a json object * @param filepath path to database folder */ - protected async hydrateDatabase(filepath: string): Promise - { + protected async hydrateDatabase(filepath: string): Promise { this.logger.info(this.localisationService.getText("importing_database")); const dataToImport = await this.importerUtil.loadAsync( @@ -107,52 +95,40 @@ export class DatabaseImporter implements OnLoad (fileWithPath: string, data: string) => this.onReadValidate(fileWithPath, data), ); - const validation - = this.valid === VaildationResult.FAILED || this.valid === VaildationResult.NOT_FOUND ? "." : ""; + const validation = + this.valid === VaildationResult.FAILED || this.valid === VaildationResult.NOT_FOUND ? "." : ""; this.logger.info(`${this.localisationService.getText("importing_database_finish")}${validation}`); this.databaseServer.setTables(dataToImport); } - protected onReadValidate(fileWithPath: string, data: string): void - { + protected onReadValidate(fileWithPath: string, data: string): void { // Validate files - if (globalThis.G_RELEASE_CONFIGURATION && this.hashedFile && !this.validateFile(fileWithPath, data)) - { + if (globalThis.G_RELEASE_CONFIGURATION && this.hashedFile && !this.validateFile(fileWithPath, data)) { this.valid = VaildationResult.FAILED; } } - public getRoute(): string - { + public getRoute(): string { return "spt-database"; } - protected validateFile(filePathAndName: string, fileData: any): boolean - { - try - { + protected validateFile(filePathAndName: string, fileData: any): boolean { + try { const finalPath = filePathAndName.replace(this.filepath, "").replace(".json", ""); let tempObject: any; - for (const prop of finalPath.split("/")) - { - if (!tempObject) - { + for (const prop of finalPath.split("/")) { + if (!tempObject) { tempObject = this.hashedFile[prop]; - } - else - { + } else { tempObject = tempObject[prop]; } } - if (tempObject !== this.hashUtil.generateSha1ForData(fileData)) - { + if (tempObject !== this.hashUtil.generateSha1ForData(fileData)) { this.logger.debug(this.localisationService.getText("validation_error_file", filePathAndName)); return false; } - } - catch (e) - { + } catch (e) { this.logger.warning(this.localisationService.getText("validation_error_exception", filePathAndName)); this.logger.warning(e); return false; @@ -164,22 +140,18 @@ export class DatabaseImporter implements OnLoad * Find and map files with image router inside a designated path * @param filepath Path to find files in */ - public loadImages(filepath: string, directories: string[], routes: string[]): void - { - for (const directoryIndex in directories) - { + public loadImages(filepath: string, directories: string[], routes: string[]): void { + for (const directoryIndex in directories) { // Get all files in directory const filesInDirectory = this.vfs.getFiles(`${filepath}${directories[directoryIndex]}`); - for (const file of filesInDirectory) - { + for (const file of filesInDirectory) { // Register each file in image router const filename = this.vfs.stripExtension(file); const routeKey = `${routes[directoryIndex]}${filename}`; let imagePath = `${filepath}${directories[directoryIndex]}/${file}`; const pathOverride = this.getImagePathOverride(imagePath); - if (pathOverride) - { + if (pathOverride) { this.logger.debug(`overrode route: ${routeKey} endpoint: ${imagePath} with ${pathOverride}`); imagePath = pathOverride; } @@ -197,14 +169,12 @@ export class DatabaseImporter implements OnLoad * @param imagePath Key * @returns override for key */ - protected getImagePathOverride(imagePath: string): string - { + protected getImagePathOverride(imagePath: string): string { return this.httpConfig.serverImagePathOverride[imagePath]; } } -enum VaildationResult -{ +enum VaildationResult { SUCCESS = 0, FAILED = 1, NOT_FOUND = 2, diff --git a/project/src/utils/EncodingUtil.ts b/project/src/utils/EncodingUtil.ts index 6ab124ef..77b51024 100644 --- a/project/src/utils/EncodingUtil.ts +++ b/project/src/utils/EncodingUtil.ts @@ -1,41 +1,33 @@ import { injectable } from "tsyringe"; @injectable() -export class EncodingUtil -{ - public encode(value: string, encode: EncodeType): string - { +export class EncodingUtil { + public encode(value: string, encode: EncodeType): string { return Buffer.from(value).toString(encode); } - public decode(value: string, encode: EncodeType): string - { + public decode(value: string, encode: EncodeType): string { return Buffer.from(value, encode).toString(EncodeType.UTF8); } - public fromBase64(value: string): string - { + public fromBase64(value: string): string { return this.decode(value, EncodeType.BASE64); } - public toBase64(value: string): string - { + public toBase64(value: string): string { return this.encode(value, EncodeType.BASE64); } - public fromHex(value: string): string - { + public fromHex(value: string): string { return this.decode(value, EncodeType.HEX); } - public toHex(value: string): string - { + public toHex(value: string): string { return this.encode(value, EncodeType.HEX); } } -export enum EncodeType -{ +export enum EncodeType { BASE64 = "base64", HEX = "hex", ASCII = "ascii", diff --git a/project/src/utils/HashUtil.ts b/project/src/utils/HashUtil.ts index 70ef6b08..174f819d 100644 --- a/project/src/utils/HashUtil.ts +++ b/project/src/utils/HashUtil.ts @@ -1,37 +1,31 @@ import crypto from "node:crypto"; import fs from "node:fs"; +import { TimeUtil } from "@spt/utils/TimeUtil"; import crc32 from "buffer-crc32"; import { mongoid } from "mongoid-js"; import { inject, injectable } from "tsyringe"; -import { TimeUtil } from "@spt/utils/TimeUtil"; @injectable() -export class HashUtil -{ - constructor(@inject("TimeUtil") protected timeUtil: TimeUtil) - {} +export class HashUtil { + constructor(@inject("TimeUtil") protected timeUtil: TimeUtil) {} /** * Create a 24 character id using the sha256 algorithm + current timestamp * @returns 24 character hash */ - public generate(): string - { + public generate(): string { return mongoid(); } - public generateMd5ForData(data: string): string - { + public generateMd5ForData(data: string): string { return this.generateHashForData("md5", data); } - public generateSha1ForData(data: string): string - { + public generateSha1ForData(data: string): string { return this.generateHashForData("sha1", data); } - public generateCRC32ForFile(filePath: fs.PathLike): number - { + public generateCRC32ForFile(filePath: fs.PathLike): number { return crc32.unsigned(fs.readFileSync(filePath)); } @@ -41,15 +35,13 @@ export class HashUtil * @param data data to be hashed * @returns hash value */ - public generateHashForData(algorithm: string, data: crypto.BinaryLike): string - { + public generateHashForData(algorithm: string, data: crypto.BinaryLike): string { const hashSum = crypto.createHash(algorithm); hashSum.update(data); return hashSum.digest("hex"); } - public generateAccountId(): number - { + public generateAccountId(): number { const min = 1000000; const max = 1999999; return max > min ? Math.floor(Math.random() * (max - min + 1) + min) : min; diff --git a/project/src/utils/HttpFileUtil.ts b/project/src/utils/HttpFileUtil.ts index 5acc27cc..980cb442 100644 --- a/project/src/utils/HttpFileUtil.ts +++ b/project/src/utils/HttpFileUtil.ts @@ -1,24 +1,20 @@ import fs from "node:fs"; import { ServerResponse } from "node:http"; -import { inject, injectable } from "tsyringe"; import { HttpServerHelper } from "@spt/helpers/HttpServerHelper"; +import { inject, injectable } from "tsyringe"; @injectable() -export class HttpFileUtil -{ - constructor(@inject("HttpServerHelper") protected httpServerHelper: HttpServerHelper) - {} +export class HttpFileUtil { + constructor(@inject("HttpServerHelper") protected httpServerHelper: HttpServerHelper) {} - public sendFile(resp: ServerResponse, filePath: string): void - { + public sendFile(resp: ServerResponse, filePath: string): void { const pathSlic = filePath.split("/"); - const type - = this.httpServerHelper.getMimeText(pathSlic[pathSlic.length - 1].split(".").at(-1) ?? "") - || this.httpServerHelper.getMimeText("txt"); + const type = + this.httpServerHelper.getMimeText(pathSlic[pathSlic.length - 1].split(".").at(-1) ?? "") || + this.httpServerHelper.getMimeText("txt"); const fileStream = fs.createReadStream(filePath); - fileStream.on("open", () => - { + fileStream.on("open", () => { resp.setHeader("Content-Type", type); fileStream.pipe(resp); }); diff --git a/project/src/utils/HttpResponseUtil.ts b/project/src/utils/HttpResponseUtil.ts index 628110f1..ef766dd0 100644 --- a/project/src/utils/HttpResponseUtil.ts +++ b/project/src/utils/HttpResponseUtil.ts @@ -1,22 +1,19 @@ -import { inject, injectable } from "tsyringe"; import { IGetBodyResponseData } from "@spt/models/eft/httpResponse/IGetBodyResponseData"; import { INullResponseData } from "@spt/models/eft/httpResponse/INullResponseData"; import { IItemEventRouterResponse } from "@spt/models/eft/itemEvent/IItemEventRouterResponse"; import { BackendErrorCodes } from "@spt/models/enums/BackendErrorCodes"; import { LocalisationService } from "@spt/services/LocalisationService"; import { JsonUtil } from "@spt/utils/JsonUtil"; +import { inject, injectable } from "tsyringe"; @injectable() -export class HttpResponseUtil -{ +export class HttpResponseUtil { constructor( @inject("JsonUtil") protected jsonUtil: JsonUtil, @inject("LocalisationService") protected localisationService: LocalisationService, - ) - {} + ) {} - protected clearString(s: string): any - { + protected clearString(s: string): any { return s .replace(/[\b]/g, "") .replace(/[\f]/g, "") @@ -30,8 +27,7 @@ export class HttpResponseUtil * @param data * @returns */ - public noBody(data: any): any - { + public noBody(data: any): any { return this.clearString(this.jsonUtil.serialize(data)); } @@ -42,30 +38,25 @@ export class HttpResponseUtil * @param errmsg * @returns */ - public getBody(data: T, err: number = 0, errmsg?: string, sanitize = true): IGetBodyResponseData - { + public getBody(data: T, err = 0, errmsg?: string, sanitize = true): IGetBodyResponseData { return sanitize ? this.clearString(this.getUnclearedBody(data, err, errmsg)) : (this.getUnclearedBody(data, err, errmsg) as any); } - public getUnclearedBody(data: any, err: number = 0, errmsg?: string): string - { + public getUnclearedBody(data: any, err = 0, errmsg?: string): string { return this.jsonUtil.serialize({ err: err, errmsg: errmsg, data: data }); } - public emptyResponse(): IGetBodyResponseData - { + public emptyResponse(): IGetBodyResponseData { return this.getBody("", 0, ""); } - public nullResponse(): INullResponseData - { + public nullResponse(): INullResponseData { return this.clearString(this.getUnclearedBody(undefined, 0, undefined)); } - public emptyArrayResponse(): IGetBodyResponseData - { + public emptyArrayResponse(): IGetBodyResponseData { return this.getBody([]); } @@ -80,14 +71,10 @@ export class HttpResponseUtil output: IItemEventRouterResponse, message = this.localisationService.getText("http-unknown_error"), errorCode = BackendErrorCodes.NONE, - ): IItemEventRouterResponse - { - if (output.warnings?.length > 0) - { + ): IItemEventRouterResponse { + if (output.warnings?.length > 0) { output.warnings.push({ index: output.warnings?.length - 1, errmsg: message, code: errorCode.toString() }); - } - else - { + } else { output.warnings = [{ index: 0, errmsg: message, code: errorCode.toString() }]; } diff --git a/project/src/utils/ImporterUtil.ts b/project/src/utils/ImporterUtil.ts index 52e14492..d5fa2e83 100644 --- a/project/src/utils/ImporterUtil.ts +++ b/project/src/utils/ImporterUtil.ts @@ -1,16 +1,14 @@ -import { inject, injectable } from "tsyringe"; -import { Queue } from "@spt/utils/collections/queue/Queue"; import { JsonUtil } from "@spt/utils/JsonUtil"; import { VFS } from "@spt/utils/VFS"; +import { Queue } from "@spt/utils/collections/queue/Queue"; +import { inject, injectable } from "tsyringe"; @injectable() -export class ImporterUtil -{ +export class ImporterUtil { constructor( @inject("VFS") protected vfs: VFS, @inject("JsonUtil") protected jsonUtil: JsonUtil, - ) - {} + ) {} /** * Load files into js objects recursively (asynchronous) @@ -19,12 +17,9 @@ export class ImporterUtil */ public async loadRecursiveAsync( filepath: string, - onReadCallback: (fileWithPath: string, data: string) => void = () => - {}, - onObjectDeserialized: (fileWithPath: string, object: any) => void = () => - {}, - ): Promise - { + onReadCallback: (fileWithPath: string, data: string) => void = () => {}, + onObjectDeserialized: (fileWithPath: string, object: any) => void = () => {}, + ): Promise { const result = {} as T; // get all filepaths @@ -32,14 +27,11 @@ export class ImporterUtil const directories = this.vfs.getDirs(filepath); // add file content to result - for (const file of files) - { - if (this.vfs.getFileExtension(file) === "json") - { + for (const file of files) { + if (this.vfs.getFileExtension(file) === "json") { const filename = this.vfs.stripExtension(file); const filePathAndName = `${filepath}${file}`; - await this.vfs.readFileAsync(filePathAndName).then((fileData) => - { + await this.vfs.readFileAsync(filePathAndName).then((fileData) => { onReadCallback(filePathAndName, fileData); const fileDeserialized = this.jsonUtil.deserializeWithCacheCheck(fileData, filePathAndName); onObjectDeserialized(filePathAndName, fileDeserialized); @@ -49,16 +41,14 @@ export class ImporterUtil } // deep tree search - for (const dir of directories) - { + for (const dir of directories) { result[dir] = this.loadRecursiveAsync(`${filepath}${dir}/`); } // set all loadRecursive to be executed asynchronously const resEntries = Object.entries(result!); const resResolved = await Promise.all(resEntries.map((ent) => ent[1])); - for (let resIdx = 0; resIdx < resResolved.length; resIdx++) - { + for (let resIdx = 0; resIdx < resResolved.length; resIdx++) { resEntries[resIdx][1] = resResolved[resIdx]; } @@ -73,12 +63,9 @@ export class ImporterUtil */ public loadRecursive( filepath: string, - onReadCallback: (fileWithPath: string, data: string) => void = () => - {}, - onObjectDeserialized: (fileWithPath: string, object: any) => void = () => - {}, - ): T - { + onReadCallback: (fileWithPath: string, data: string) => void = () => {}, + onObjectDeserialized: (fileWithPath: string, object: any) => void = () => {}, + ): T { const result = {} as T; // get all filepaths @@ -86,10 +73,8 @@ export class ImporterUtil const directories = this.vfs.getDirs(filepath); // add file content to result - for (const file of files) - { - if (this.vfs.getFileExtension(file) === "json") - { + for (const file of files) { + if (this.vfs.getFileExtension(file) === "json") { const filename = this.vfs.stripExtension(file); const filePathAndName = `${filepath}${file}`; const fileData = this.vfs.readFile(filePathAndName); @@ -101,8 +86,7 @@ export class ImporterUtil } // deep tree search - for (const dir of directories) - { + for (const dir of directories) { result[dir] = this.loadRecursive(`${filepath}${dir}/`); } @@ -112,12 +96,9 @@ export class ImporterUtil public async loadAsync( filepath: string, strippablePath = "", - onReadCallback: (fileWithPath: string, data: string) => void = () => - {}, - onObjectDeserialized: (fileWithPath: string, object: any) => void = () => - {}, - ): Promise - { + onReadCallback: (fileWithPath: string, data: string) => void = () => {}, + onObjectDeserialized: (fileWithPath: string, object: any) => void = () => {}, + ): Promise { const directoriesToRead = new Queue(); const filesToProcess = new Queue(); @@ -131,33 +112,26 @@ export class ImporterUtil directoriesToRead.enqueueAll(directories.map((d) => `${filepath}${d}`)); filesToProcess.enqueueAll(files.map((f) => new VisitNode(filepath, f))); - while (directoriesToRead.length !== 0) - { + while (directoriesToRead.length !== 0) { const directory = directoriesToRead.dequeue(); - if (!directory) - continue; + if (!directory) continue; filesToProcess.enqueueAll(this.vfs.getFiles(directory).map((f) => new VisitNode(`${directory}/`, f))); directoriesToRead.enqueueAll(this.vfs.getDirs(directory).map((d) => `${directory}/${d}`)); } - while (filesToProcess.length !== 0) - { + while (filesToProcess.length !== 0) { const fileNode = filesToProcess.dequeue(); - if (!fileNode) - continue; - if (this.vfs.getFileExtension(fileNode.fileName) === "json") - { + if (!fileNode) continue; + if (this.vfs.getFileExtension(fileNode.fileName) === "json") { const filePathAndName = `${fileNode.filePath}${fileNode.fileName}`; promises.push( this.vfs .readFileAsync(filePathAndName) - .then(async (fileData) => - { + .then(async (fileData) => { onReadCallback(filePathAndName, fileData); return this.jsonUtil.deserializeWithCacheCheckAsync(fileData, filePathAndName); }) - .then(async (fileDeserialized) => - { + .then(async (fileDeserialized) => { onObjectDeserialized(filePathAndName, fileDeserialized); const strippedFilePath = this.vfs.stripExtension(filePathAndName).replace(filepath, ""); this.placeObject(fileDeserialized, strippedFilePath, result, strippablePath); @@ -171,23 +145,17 @@ export class ImporterUtil return result; } - protected placeObject(fileDeserialized: any, strippedFilePath: string, result: T, strippablePath: string): void - { + protected placeObject(fileDeserialized: any, strippedFilePath: string, result: T, strippablePath: string): void { const strippedFinalPath = strippedFilePath.replace(strippablePath, ""); let temp = result; const propertiesToVisit = strippedFinalPath.split("/"); - for (let i = 0; i < propertiesToVisit.length; i++) - { + for (let i = 0; i < propertiesToVisit.length; i++) { const property = propertiesToVisit[i]; - if (i === propertiesToVisit.length - 1) - { + if (i === propertiesToVisit.length - 1) { temp[property] = fileDeserialized; - } - else - { - if (!temp[property]) - { + } else { + if (!temp[property]) { temp[property] = {}; } temp = temp[property]; @@ -196,11 +164,9 @@ export class ImporterUtil } } -class VisitNode -{ +class VisitNode { constructor( public filePath: string, public fileName: string, - ) - {} + ) {} } diff --git a/project/src/utils/JsonUtil.ts b/project/src/utils/JsonUtil.ts index cd7f81b2..9d22f33d 100644 --- a/project/src/utils/JsonUtil.ts +++ b/project/src/utils/JsonUtil.ts @@ -1,15 +1,14 @@ -import fixJson from "json-fixer"; -import { stringify, parse } from "json5"; -import { jsonc } from "jsonc"; -import { IParseOptions, IStringifyOptions, Reviver } from "jsonc/lib/interfaces"; -import { inject, injectable } from "tsyringe"; import { ILogger } from "@spt/models/spt/utils/ILogger"; import { HashUtil } from "@spt/utils/HashUtil"; import { VFS } from "@spt/utils/VFS"; +import fixJson from "json-fixer"; +import { parse, stringify } from "json5"; +import { jsonc } from "jsonc"; +import { IParseOptions, IStringifyOptions, Reviver } from "jsonc/lib/interfaces"; +import { inject, injectable } from "tsyringe"; @injectable() -export class JsonUtil -{ +export class JsonUtil { protected fileHashes?: Map = undefined; protected jsonCacheExists = false; protected jsonCachePath = "./user/cache/jsonCache.json"; @@ -18,8 +17,7 @@ export class JsonUtil @inject("VFS") protected vfs: VFS, @inject("HashUtil") protected hashUtil: HashUtil, @inject("PrimaryLogger") protected logger: ILogger, - ) - {} + ) {} /** * From object to string @@ -27,10 +25,8 @@ export class JsonUtil * @param prettify Should output be prettified * @returns string */ - public serialize(data: any, prettify = false): string - { - if (prettify) - { + public serialize(data: any, prettify = false): string { + if (prettify) { return JSON.stringify(data, undefined, "\t"); } @@ -48,8 +44,7 @@ export class JsonUtil data: any, replacer?: (this: any, key: string, value: any) => any, space?: string | number, - ): string - { + ): string { return JSON.stringify(data, replacer, space); } @@ -64,33 +59,24 @@ export class JsonUtil data: any, filename?: string | undefined, options?: IStringifyOptions | Reviver, - ): string | undefined - { - try - { + ): string | undefined { + try { return jsonc.stringify(data, options); - } - catch (error) - { + } catch (error) { this.logger.error( `unable to stringify jsonC file: ${filename} message: ${error.message}, stack: ${error.stack}`, ); } } - public serializeJson5(data: any, filename?: string | undefined, prettify = false): string | undefined - { - try - { - if (prettify) - { + public serializeJson5(data: any, filename?: string | undefined, prettify = false): string | undefined { + try { + if (prettify) { return stringify(data, undefined, "\t"); } return stringify(data); - } - catch (error) - { + } catch (error) { this.logger.error( `unable to stringify json5 file: ${filename} message: ${error.message}, stack: ${error.stack}`, ); @@ -103,14 +89,10 @@ export class JsonUtil * @param filename Name of file being deserialized * @returns object */ - public deserialize(jsonString: string, filename = ""): T | undefined - { - try - { + public deserialize(jsonString: string, filename = ""): T | undefined { + try { return JSON.parse(jsonString); - } - catch (error) - { + } catch (error) { this.logger.error( `unable to parse json file: ${filename} message: ${error.message}, stack: ${error.stack}`, ); @@ -124,38 +106,28 @@ export class JsonUtil * @param options Parsing options * @returns object */ - public deserializeJsonC(jsonString: string, filename = "", options?: IParseOptions): T | undefined - { - try - { + public deserializeJsonC(jsonString: string, filename = "", options?: IParseOptions): T | undefined { + try { return jsonc.parse(jsonString, options); - } - catch (error) - { + } catch (error) { this.logger.error( `unable to parse jsonC file: ${filename} message: ${error.message}, stack: ${error.stack}`, ); } } - public deserializeJson5(jsonString: string, filename = ""): T | undefined - { - try - { + public deserializeJson5(jsonString: string, filename = ""): T | undefined { + try { return parse(jsonString); - } - catch (error) - { + } catch (error) { this.logger.error( `unable to parse json file: ${filename} message: ${error.message}, stack: ${error.stack}`, ); } } - public async deserializeWithCacheCheckAsync(jsonString: string, filePath: string): Promise - { - return new Promise((resolve) => - { + public async deserializeWithCacheCheckAsync(jsonString: string, filePath: string): Promise { + return new Promise((resolve) => { resolve(this.deserializeWithCacheCheck(jsonString, filePath)); }); } @@ -167,41 +139,32 @@ export class JsonUtil * @param filePath Path to json file being processed * @returns Object */ - public deserializeWithCacheCheck(jsonString: string, filePath: string): T | undefined - { + public deserializeWithCacheCheck(jsonString: string, filePath: string): T | undefined { this.ensureJsonCacheExists(this.jsonCachePath); this.hydrateJsonCache(this.jsonCachePath); // Generate hash of string const generatedHash = this.hashUtil.generateSha1ForData(jsonString); - if (!this.fileHashes) - { + if (!this.fileHashes) { throw new Error("Unable to deserialize with Cache, file hashes have not been hydrated yet"); } // Get hash of file and check if missing or hash mismatch let savedHash = this.fileHashes[filePath]; - if (!savedHash || savedHash !== generatedHash) - { - try - { + if (!savedHash || savedHash !== generatedHash) { + try { const { data, changed } = fixJson(jsonString); - if (changed) - { + if (changed) { // data invalid, return it this.logger.error(`${filePath} - Detected faulty json, please fix your json file using VSCodium`); - } - else - { + } else { // data valid, save hash and call function again this.fileHashes[filePath] = generatedHash; this.vfs.writeFile(this.jsonCachePath, this.serialize(this.fileHashes, true)); savedHash = generatedHash; } return data as T; - } - catch (error) - { + } catch (error) { const errorMessage = `Attempted to parse file: ${filePath}. Error: ${error.message}`; this.logger.error(errorMessage); throw new Error(errorMessage); @@ -209,8 +172,7 @@ export class JsonUtil } // Doesn't match - if (savedHash !== generatedHash) - { + if (savedHash !== generatedHash) { throw new Error(`Catastrophic failure processing file ${filePath}`); } @@ -222,12 +184,9 @@ export class JsonUtil * Create file if nothing found * @param jsonCachePath path to cache */ - protected ensureJsonCacheExists(jsonCachePath: string): void - { - if (!this.jsonCacheExists) - { - if (!this.vfs.exists(jsonCachePath)) - { + protected ensureJsonCacheExists(jsonCachePath: string): void { + if (!this.jsonCacheExists) { + if (!this.vfs.exists(jsonCachePath)) { // Create empty object at path this.vfs.writeFile(jsonCachePath, "{}"); } @@ -239,11 +198,9 @@ export class JsonUtil * Read contents of json cache and add to class field * @param jsonCachePath Path to cache */ - protected hydrateJsonCache(jsonCachePath: string): void - { + protected hydrateJsonCache(jsonCachePath: string): void { // Get all file hashes - if (!this.fileHashes) - { + if (!this.fileHashes) { this.fileHashes = this.deserialize(this.vfs.readFile(`${jsonCachePath}`)); } } @@ -254,8 +211,7 @@ export class JsonUtil * @returns Cloned parameter * @deprecated Use ICloner implementations, such as RecursiveCloner or StructuredCloner */ - public clone(objectToClone: T): T - { + public clone(objectToClone: T): T { return structuredClone(objectToClone); } } diff --git a/project/src/utils/MathUtil.ts b/project/src/utils/MathUtil.ts index efd560e5..abbc3d4a 100644 --- a/project/src/utils/MathUtil.ts +++ b/project/src/utils/MathUtil.ts @@ -1,15 +1,13 @@ import { injectable } from "tsyringe"; @injectable() -export class MathUtil -{ +export class MathUtil { /** * Helper to create the sum of all array elements * @param {array} values The array with numbers of which to calculate the sum * @return {number} sum(values) */ - public arraySum(values: number[]): number - { + public arraySum(values: number[]): number { // sum with initial value being 0 return values.reduce((sum, x) => sum + x, 0); } @@ -20,12 +18,10 @@ export class MathUtil * @param {array} values The array with numbers of which to calculate the cumulative sum * @return {array} cumsum(values) */ - public arrayCumsum(values: number[]): number[] - { + public arrayCumsum(values: number[]): number[] { const cumsumArray: number[] = []; let sum = 0; - for (let i = 0; i < values.length; i++) - { + for (let i = 0; i < values.length; i++) { sum += values[i]; cumsumArray[i] = sum; } @@ -37,8 +33,7 @@ export class MathUtil * @param {array} values The array of numbers which shall be multiplied by the factor * @return {array} array times factor */ - public arrayProd(values: number[], factor: number): number[] - { + public arrayProd(values: number[], factor: number): number[] { return values.map((x) => x * factor); } @@ -47,8 +42,7 @@ export class MathUtil * @param {array} values The array of numbers to which the summand should be added * @return {array} array plus summand */ - public arrayAdd(values: number[], summand: number): number[] - { + public arrayAdd(values: number[], summand: number): number[] { return values.map((x) => x + summand); } @@ -67,8 +61,7 @@ export class MathUtil * @param {number} maxOut max of outout range * @return {number} the result of the mapping */ - public mapToRange(x: number, minIn: number, maxIn: number, minOut: number, maxOut: number): number - { + public mapToRange(x: number, minIn: number, maxIn: number, minOut: number, maxOut: number): number { const deltaIn = maxIn - minIn; const deltaOut = maxOut - minOut; @@ -85,22 +78,17 @@ export class MathUtil * @param {array} y support points in y (of same length as x) * @return {number} y(xp) */ - public interp1(xp: number, x: number[], y: number[]): number | undefined - { - if (xp > x[x.length - 1]) - { + public interp1(xp: number, x: number[], y: number[]): number | undefined { + if (xp > x[x.length - 1]) { return y[y.length - 1]; } - if (xp < x[0]) - { + if (xp < x[0]) { return y[0]; } - for (let i = 0; i < x.length - 1; i++) - { - if (xp >= x[i] && xp <= x[i + 1]) - { + for (let i = 0; i < x.length - 1; i++) { + if (xp >= x[i] && xp <= x[i + 1]) { return y[i] + ((xp - x[i]) * (y[i + 1] - y[i])) / (x[i + 1] - x[i]); } } diff --git a/project/src/utils/ObjectId.ts b/project/src/utils/ObjectId.ts index 7489bbfc..5a87d952 100644 --- a/project/src/utils/ObjectId.ts +++ b/project/src/utils/ObjectId.ts @@ -1,12 +1,10 @@ import crypto from "node:crypto"; -import { inject, injectable } from "tsyringe"; import { TimeUtil } from "@spt/utils/TimeUtil"; +import { inject, injectable } from "tsyringe"; @injectable() -export class ObjectId -{ - constructor(@inject("TimeUtil") protected timeUtil: TimeUtil) - {} +export class ObjectId { + constructor(@inject("TimeUtil") protected timeUtil: TimeUtil) {} protected randomBytes = crypto.randomBytes(5); protected constglobalCounter = 0; @@ -14,27 +12,22 @@ export class ObjectId protected globalCounter: number; protected time: number; - public incGlobalCounter(): number - { + public incGlobalCounter(): number { this.globalCounter = (this.globalCounter + 1) % 0xffffff; return this.globalCounter; } - public toHexString(byteArray: string | any[] | Buffer): string - { + public toHexString(byteArray: string | any[] | Buffer): string { let hexString = ""; - for (let i = 0; i < byteArray.length; i++) - { + for (let i = 0; i < byteArray.length; i++) { hexString += `0${(byteArray[i] & 0xff).toString(16)}`.slice(-2); } return hexString; } - public generate(): string - { + public generate(): string { const time = this.timeUtil.getTimestamp(); - if (this.time !== time) - { + if (this.time !== time) { this.globalCounter = 0; this.time = time; } diff --git a/project/src/utils/RagfairOfferHolder.ts b/project/src/utils/RagfairOfferHolder.ts index d730b78a..476d920a 100644 --- a/project/src/utils/RagfairOfferHolder.ts +++ b/project/src/utils/RagfairOfferHolder.ts @@ -2,8 +2,7 @@ import { ProfileHelper } from "@spt/helpers/ProfileHelper"; import { RagfairServerHelper } from "@spt/helpers/RagfairServerHelper"; import { IRagfairOffer } from "@spt/models/eft/ragfair/IRagfairOffer"; -export class RagfairOfferHolder -{ +export class RagfairOfferHolder { protected offersById: Map; protected offersByTemplate: Map>; protected offersByTrader: Map>; @@ -12,69 +11,56 @@ export class RagfairOfferHolder protected maxOffersPerTemplate: number, protected ragfairServerHelper: RagfairServerHelper, protected profileHelper: ProfileHelper, - ) - { + ) { this.offersById = new Map(); this.offersByTemplate = new Map(); this.offersByTrader = new Map(); } - public getOfferById(id: string): IRagfairOffer | undefined - { - if (this.offersById.has(id)) - { + public getOfferById(id: string): IRagfairOffer | undefined { + if (this.offersById.has(id)) { return this.offersById.get(id)!; } return undefined; } - public getOffersByTemplate(templateId: string): Array | undefined - { - if (this.offersByTemplate.has(templateId)) - { + public getOffersByTemplate(templateId: string): Array | undefined { + if (this.offersByTemplate.has(templateId)) { return [...this.offersByTemplate.get(templateId)!.values()]; } return undefined; } - public getOffersByTrader(traderId: string): Array | undefined - { - if (this.offersByTrader.has(traderId)) - { + public getOffersByTrader(traderId: string): Array | undefined { + if (this.offersByTrader.has(traderId)) { return [...this.offersByTrader.get(traderId)!.values()]; } return undefined; } - public getOffers(): Array - { - if (this.offersById.size > 0) - { + public getOffers(): Array { + if (this.offersById.size > 0) { return [...this.offersById.values()]; } return []; } - public addOffers(offers: Array): void - { - for (const offer of offers) - { + public addOffers(offers: Array): void { + for (const offer of offers) { this.addOffer(offer); } } - public addOffer(offer: IRagfairOffer): void - { + public addOffer(offer: IRagfairOffer): void { const trader = offer.user.id; const offerId = offer._id; const itemTpl = offer.items[0]._tpl; // If its an NPC PMC offer AND we have already reached the maximum amount of possible offers // for this template, just dont add in more if ( - !(this.ragfairServerHelper.isTrader(trader) || this.profileHelper.isPlayer(trader)) - && (this.getOffersByTemplate(itemTpl)?.length ?? 0) >= this.maxOffersPerTemplate - ) - { + !(this.ragfairServerHelper.isTrader(trader) || this.profileHelper.isPlayer(trader)) && + (this.getOffersByTemplate(itemTpl)?.length ?? 0) >= this.maxOffersPerTemplate + ) { return; } this.offersById.set(offerId, offer); @@ -86,43 +72,34 @@ export class RagfairOfferHolder * Purge offer from offer cache * @param offer Offer to remove */ - public removeOffer(offer: IRagfairOffer): void - { - if (this.offersById.has(offer._id)) - { + public removeOffer(offer: IRagfairOffer): void { + if (this.offersById.has(offer._id)) { this.offersById.delete(offer._id); - if (this.offersByTrader.has(offer.user.id)) - { + if (this.offersByTrader.has(offer.user.id)) { this.offersByTrader.get(offer.user.id)!.delete(offer._id); // This was causing a memory leak, we need to make sure that we remove // the user ID from the cached offers after they dont have anything else // on the flea placed. We regenerate the ID for the NPC users, making it // continously grow otherwise - if (this.offersByTrader.get(offer.user.id)!.size === 0) - { + if (this.offersByTrader.get(offer.user.id)!.size === 0) { this.offersByTrader.delete(offer.user.id); } } - if (this.offersByTemplate.has(offer.items[0]._tpl)) - { + if (this.offersByTemplate.has(offer.items[0]._tpl)) { this.offersByTemplate.get(offer.items[0]._tpl)!.delete(offer._id); } } } - public removeOffers(offers: Array): void - { - for (const offer of offers) - { + public removeOffers(offers: Array): void { + for (const offer of offers) { this.removeOffer(offer); } } - public removeAllOffersByTrader(traderId: string): void - { - if (this.offersByTrader.has(traderId)) - { + public removeAllOffersByTrader(traderId: string): void { + if (this.offersByTrader.has(traderId)) { this.removeOffers([...this.offersByTrader.get(traderId)!.values()]); } } @@ -131,41 +108,31 @@ export class RagfairOfferHolder * Get an array of stale offers that are still shown to player * @returns IRagfairOffer array */ - public getStaleOffers(time: number): Array - { + public getStaleOffers(time: number): Array { return this.getOffers().filter((o) => this.isStale(o, time)); } - protected addOfferByTemplates(template: string, offer: IRagfairOffer): void - { - if (this.offersByTemplate.has(template)) - { + protected addOfferByTemplates(template: string, offer: IRagfairOffer): void { + if (this.offersByTemplate.has(template)) { this.offersByTemplate.get(template)!.set(offer._id, offer); - } - else - { + } else { const valueMapped = new Map(); valueMapped.set(offer._id, offer); this.offersByTemplate.set(template, valueMapped); } } - protected addOfferByTrader(trader: string, offer: IRagfairOffer): void - { - if (this.offersByTrader.has(trader)) - { + protected addOfferByTrader(trader: string, offer: IRagfairOffer): void { + if (this.offersByTrader.has(trader)) { this.offersByTrader.get(trader)!.set(offer._id, offer); - } - else - { + } else { const valueMapped = new Map(); valueMapped.set(offer._id, offer); this.offersByTrader.set(trader, valueMapped); } } - protected isStale(offer: IRagfairOffer, time: number): boolean - { + protected isStale(offer: IRagfairOffer, time: number): boolean { return offer.endTime < time || (offer.items[0].upd?.StackObjectsCount ?? 0) < 1; } } diff --git a/project/src/utils/RandomUtil.ts b/project/src/utils/RandomUtil.ts index b26ba032..0019ab5e 100644 --- a/project/src/utils/RandomUtil.ts +++ b/project/src/utils/RandomUtil.ts @@ -1,7 +1,7 @@ -import { inject, injectable } from "tsyringe"; import { ILogger } from "@spt/models/spt/utils/ILogger"; -import { ICloner } from "@spt/utils/cloners/ICloner"; import { MathUtil } from "@spt/utils/MathUtil"; +import { ICloner } from "@spt/utils/cloners/ICloner"; +import { inject, injectable } from "tsyringe"; /** * Array of ProbabilityObjectArray which allow to randomly draw of the contained objects @@ -18,22 +18,19 @@ import { MathUtil } from "@spt/utils/MathUtil"; * // count the elements which should be distributed according to the relative probabilities * res.filter(x => x==="b").reduce((sum, x) => sum + 1 , 0) */ -export class ProbabilityObjectArray extends Array> -{ +export class ProbabilityObjectArray extends Array> { constructor( private mathUtil: MathUtil, private cloner: ICloner, ...items: ProbabilityObject[] - ) - { + ) { super(); this.push(...items); } filter( callbackfn: (value: ProbabilityObject, index: number, array: ProbabilityObject[]) => any, - ): ProbabilityObjectArray - { + ): ProbabilityObjectArray { return new ProbabilityObjectArray(this.mathUtil, this.cloner, ...super.filter(callbackfn)); } @@ -42,8 +39,7 @@ export class ProbabilityObjectArray extends Array extends Array - { + clone(): ProbabilityObjectArray { const clone = this.cloner.clone(this); const probabliltyObjects = new ProbabilityObjectArray(this.mathUtil, this.cloner); - for (const ci of clone) - { + for (const ci of clone) { probabliltyObjects.push(new ProbabilityObject(ci.key, ci.relativeProbability, ci.data)); } return probabliltyObjects; @@ -71,8 +65,7 @@ export class ProbabilityObjectArray extends Array - { + drop(key: K): ProbabilityObjectArray { return this.filter((r) => r.key !== key); } @@ -81,8 +74,7 @@ export class ProbabilityObjectArray extends Array r.key === key)[0]?.data; } @@ -96,8 +88,7 @@ export class ProbabilityObjectArray extends Array r.key === key)[0].relativeProbability; } @@ -110,8 +101,7 @@ export class ProbabilityObjectArray extends Array x.relativeProbability)); } @@ -124,8 +114,7 @@ export class ProbabilityObjectArray extends Array x.relativeProbability)); } @@ -137,16 +126,13 @@ export class ProbabilityObjectArray extends Array = []): K[] - { - if (this.length === 0) - { + public draw(count = 1, replacement = true, locklist: Array = []): K[] { + if (this.length === 0) { return []; } const { probArray, keyArray } = this.reduce( - (acc, x) => - { + (acc, x) => { acc.probArray.push(x.relativeProbability); acc.keyArray.push(x.key); return acc; @@ -156,26 +142,21 @@ export class ProbabilityObjectArray extends Array x > rand); // We cannot put Math.random() directly in the findIndex because then it draws anew for each of its iteration - if (replacement || locklist.includes(keyArray[randomIndex])) - { + if (replacement || locklist.includes(keyArray[randomIndex])) { // Add random item from possible value into return array drawnKeys.push(keyArray[randomIndex]); - } - else - { + } else { // We draw without replacement -> remove the key and its probability from array const key = keyArray.splice(randomIndex, 1)[0]; probArray.splice(randomIndex, 1); drawnKeys.push(key); probCumsum = this.cumulativeProbability(probArray); // If we draw without replacement and the ProbabilityObjectArray is exhausted we need to break - if (keyArray.length < 1) - { + if (keyArray.length < 1) { break; } } @@ -189,8 +170,7 @@ export class ProbabilityObjectArray extends Array -{ +export class ProbabilityObject { key: K; relativeProbability: number; data?: V; @@ -200,8 +180,7 @@ export class ProbabilityObject * @param {number} relativeProbability The relative probability of this element * @param {any} data Optional data attached to the element */ - constructor(key: K, relativeProbability: number, data?: V) - { + constructor(key: K, relativeProbability: number, data?: V) { this.key = key; this.relativeProbability = relativeProbability; this.data = data; @@ -209,38 +188,31 @@ export class ProbabilityObject } @injectable() -export class RandomUtil -{ +export class RandomUtil { constructor( @inject("PrimaryCloner") protected cloner: ICloner, @inject("PrimaryLogger") protected logger: ILogger, - ) - {} + ) {} - public getInt(min: number, max: number): number - { + public getInt(min: number, max: number): number { const minimum = Math.ceil(min); const maximum = Math.floor(max); return maximum > minimum ? Math.floor(Math.random() * (maximum - minimum + 1) + minimum) : minimum; } - public getIntEx(max: number): number - { + public getIntEx(max: number): number { return max > 1 ? Math.floor(Math.random() * (max - 2) + 1) : 1; } - public getFloat(min: number, max: number): number - { + public getFloat(min: number, max: number): number { return Math.random() * (max - min) + min; } - public getBool(): boolean - { + public getBool(): boolean { return Math.random() < 0.5; } - public getPercentOfValue(percent: number, number: number, toFixed = 2): number - { + public getPercentOfValue(percent: number, number: number, toFixed = 2): number { return Number.parseFloat(((percent * number) / 100).toFixed(toFixed)); } @@ -250,8 +222,7 @@ export class RandomUtil * @param percentage Percentage to reduce value by * @returns Reduced value */ - public reduceValueByPercent(number: number, percentage: number): number - { + public reduceValueByPercent(number: number, percentage: number): number { const reductionAmount = number * (percentage / 100); return number - reductionAmount; } @@ -261,29 +232,24 @@ export class RandomUtil * @param chancePercent value check needs to be above * @returns true if value passes check */ - public getChance100(chancePercent: number): boolean - { + public getChance100(chancePercent: number): boolean { return this.getIntEx(100) <= chancePercent; } // Its better to keep this method separated from getArrayValue so we can use generic inferance on getArrayValue - public getStringArrayValue(arr: string[]): string - { + public getStringArrayValue(arr: string[]): string { return arr[this.getInt(0, arr.length - 1)]; } - public getArrayValue(arr: T[]): T - { + public getArrayValue(arr: T[]): T { return arr[this.getInt(0, arr.length - 1)]; } - public getKey(node: any): string - { + public getKey(node: any): string { return this.getArrayValue(Object.keys(node)); } - public getKeyValue(node: { [x: string]: any }): any - { + public getKeyValue(node: { [x: string]: any }): any { return node[this.getKey(node)]; } @@ -294,24 +260,19 @@ export class RandomUtil * @param {number} sigma Standard deviation of the normal distribution * @returns {number} The value drawn */ - public getNormallyDistributedRandomNumber(mean: number, sigma: number, attempt = 0): number - { + public getNormallyDistributedRandomNumber(mean: number, sigma: number, attempt = 0): number { let u = 0; let v = 0; - while (u === 0) - { + while (u === 0) { u = Math.random(); // Converting [0,1) to (0,1) } - while (v === 0) - { + while (v === 0) { v = Math.random(); } const w = Math.sqrt(-2.0 * Math.log(u)) * Math.cos(2.0 * Math.PI * v); const valueDrawn = mean + w * sigma; - if (valueDrawn < 0) - { - if (attempt > 100) - { + if (valueDrawn < 0) { + if (attempt > 100) { return this.getFloat(0.01, mean * 2); } @@ -328,10 +289,8 @@ export class RandomUtil * @param {integer} high Higher bound exclusive * @returns {integer} The random integer in [low, high) */ - public randInt(low: number, high?: number): number - { - if (high) - { + public randInt(low: number, high?: number): number { + if (high) { return low + Math.floor(Math.random() * (high - low)); } @@ -346,24 +305,18 @@ export class RandomUtil * @param {boolean} replacement Draw with or without replacement from the input array(default true) * @return {array} Array consisting of N random elements */ - public drawRandomFromList(originalList: Array, count = 1, replacement = true): Array - { + public drawRandomFromList(originalList: Array, count = 1, replacement = true): Array { let list = originalList; - if (!replacement) - { + if (!replacement) { list = this.cloner.clone(originalList); } const results: T[] = []; - for (let i = 0; i < count; i++) - { + for (let i = 0; i < count; i++) { const randomIndex = this.randInt(list.length); - if (replacement) - { + if (replacement) { results.push(list[randomIndex]); - } - else - { + } else { results.push(list.splice(randomIndex, 1)[0]); } } @@ -378,15 +331,13 @@ export class RandomUtil * @param {boolean} replacement Draw with ot without replacement from the input dict * @return {array} Array consisting of N random keys of the dictionary */ - public drawRandomFromDict(dict: any, count = 1, replacement = true): any[] - { + public drawRandomFromDict(dict: any, count = 1, replacement = true): any[] { const keys = Object.keys(dict); const randomKeys = this.drawRandomFromList(keys, count, replacement); return randomKeys; } - public getBiasedRandomNumber(min: number, max: number, shift: number, n: number): number - { + public getBiasedRandomNumber(min: number, max: number, shift: number, n: number): number { /* To whoever tries to make sense of this, please forgive me - I tried my best at explaining what goes on here. * This function generates a random number based on a gaussian distribution with an option to add a bias via shifting. * @@ -400,26 +351,22 @@ export class RandomUtil * Here's a place where you can play around with the 'n' and 'shift' values to see how the distribution changes: * http://jsfiddle.net/e08cumyx/ */ - if (max < min) - { + if (max < min) { throw { name: "Invalid arguments", message: `Bounded random number generation max is smaller than min (${max} < ${min})`, }; } - if (n < 1) - { + if (n < 1) { throw { name: "Invalid argument", message: `'n' must be 1 or greater (received ${n})` }; } - if (min === max) - { + if (min === max) { return min; } - if (shift > max - min) - { + if (shift > max - min) { /* If a rolled number is out of bounds (due to bias being applied), we simply roll it again. * As the shifting increases, the chance of rolling a number within bounds decreases. * A shift that is equal to the available range only has a 50% chance of rolling correctly, theoretically halving performance. @@ -431,20 +378,17 @@ export class RandomUtil this.logger.info(`min -> ${min}; max -> ${max}; shift -> ${shift}`); } - const gaussianRandom = (n: number) => - { + const gaussianRandom = (n: number) => { let rand = 0; - for (let i = 0; i < n; i += 1) - { + for (let i = 0; i < n; i += 1) { rand += Math.random(); } return rand / n; }; - const boundedGaussian = (start: number, end: number, n: number) => - { + const boundedGaussian = (start: number, end: number, n: number) => { return Math.round(start + gaussianRandom(n) * (end - start + 1)); }; @@ -452,8 +396,7 @@ export class RandomUtil const biasedMax = shift < 0 ? max + shift : max; let num: number; - do - { + do { num = boundedGaussian(biasedMin, biasedMax, n); } while (num < min || num > max); @@ -465,14 +408,12 @@ export class RandomUtil * @param array Array to shuffle * @returns Shuffled array */ - public shuffle(array: Array): Array - { + public shuffle(array: Array): Array { let currentIndex = array.length; let randomIndex: number; // While there remain elements to shuffle. - while (currentIndex !== 0) - { + while (currentIndex !== 0) { // Pick a remaining element. randomIndex = Math.floor(Math.random() * currentIndex); currentIndex--; @@ -491,8 +432,7 @@ export class RandomUtil * @example * rollForChanceProbability(0.25); // returns true 25% probability */ - public rollForChanceProbability(probabilityChance: number): boolean - { + public rollForChanceProbability(probabilityChance: number): boolean { const maxRoll = 9999; // Roll a number between 0 and 1 diff --git a/project/src/utils/TimeUtil.ts b/project/src/utils/TimeUtil.ts index d1887ca8..7982f95b 100644 --- a/project/src/utils/TimeUtil.ts +++ b/project/src/utils/TimeUtil.ts @@ -5,8 +5,7 @@ import { injectable } from "tsyringe"; * Utility class to handle time related operations. */ @injectable() -export class TimeUtil -{ +export class TimeUtil { public static readonly ONE_HOUR_AS_SECONDS = 3600; // Number of seconds in one hour. /** @@ -15,8 +14,7 @@ export class TimeUtil * @param {number} number - The number to pad. * @returns {string} The padded number as a string. */ - protected pad(number: number): string - { + protected pad(number: number): string { return String(number).padStart(2, "0"); } @@ -26,8 +24,7 @@ export class TimeUtil * @param {Date} date - The date to format in UTC. * @returns {string} The formatted time as 'HH-MM-SS'. */ - public formatTime(date: Date): string - { + public formatTime(date: Date): string { const hours = this.pad(date.getUTCHours()); const minutes = this.pad(date.getUTCMinutes()); const seconds = this.pad(date.getUTCSeconds()); @@ -40,8 +37,7 @@ export class TimeUtil * @param {Date} date - The date to format in UTC. * @returns {string} The formatted date as 'YYYY-MM-DD'. */ - public formatDate(date: Date): string - { + public formatDate(date: Date): string { const day = this.pad(date.getUTCDate()); const month = this.pad(date.getUTCMonth() + 1); // getUTCMonth returns 0-11 const year = date.getUTCFullYear(); @@ -53,8 +49,7 @@ export class TimeUtil * * @returns {string} The current date as 'YYYY-MM-DD'. */ - public getDate(): string - { + public getDate(): string { return this.formatDate(new Date()); } @@ -63,8 +58,7 @@ export class TimeUtil * * @returns {string} The current time as 'HH-MM-SS'. */ - public getTime(): string - { + public getTime(): string { return this.formatTime(new Date()); } @@ -73,8 +67,7 @@ export class TimeUtil * * @returns {number} The current timestamp in seconds since the Unix epoch in UTC. */ - public getTimestamp(): number - { + public getTimestamp(): number { return Math.floor(new Date().getTime() / 1000); } @@ -82,8 +75,7 @@ export class TimeUtil * Get timestamp of today + passed in day count * @param daysFromNow Days from now */ - public getTimeStampFromNowDays(daysFromNow: number): number - { + public getTimeStampFromNowDays(daysFromNow: number): number { const currentTimeStamp = this.getTimestamp(); const desiredDaysAsSeconds = this.getHoursAsSeconds(daysFromNow * 24); @@ -95,8 +87,7 @@ export class TimeUtil * * @returns {string} The current time as 'HH:MM' in UTC. */ - public getTimeMailFormat(): string - { + public getTimeMailFormat(): string { return formatInTimeZone(new Date(), "UTC", "HH:mm"); } @@ -105,8 +96,7 @@ export class TimeUtil * * @returns {string} The current date as 'DD.MM.YYYY' in UTC. */ - public getDateMailFormat(): string - { + public getDateMailFormat(): string { return formatInTimeZone(new Date(), "UTC", "dd.MM.yyyy"); } @@ -116,16 +106,14 @@ export class TimeUtil * @param {number} hours - The number of hours to convert. * @returns {number} The equivalent number of seconds. */ - public getHoursAsSeconds(hours: number): number - { + public getHoursAsSeconds(hours: number): number { return hours * TimeUtil.ONE_HOUR_AS_SECONDS; } - public getTimestampOfNextHour(): number - { + public getTimestampOfNextHour(): number { const now = new Date(); - const millisecondsUntilNextHour - = (60 - now.getMinutes()) * 60 * 1000 - now.getSeconds() * 1000 - now.getMilliseconds(); + const millisecondsUntilNextHour = + (60 - now.getMinutes()) * 60 * 1000 - now.getSeconds() * 1000 - now.getMilliseconds(); return (now.getTime() + millisecondsUntilNextHour) / 1000; } } diff --git a/project/src/utils/VFS.ts b/project/src/utils/VFS.ts index 95d2eb9c..41e95501 100644 --- a/project/src/utils/VFS.ts +++ b/project/src/utils/VFS.ts @@ -4,26 +4,25 @@ import crypto from "node:crypto"; import fs from "node:fs"; import path, { resolve } from "node:path"; import { promisify } from "node:util"; -import { writeFileSync } from "atomically"; -import { lockSync, checkSync, unlockSync } from "proper-lockfile"; -import { inject, injectable } from "tsyringe"; import { IAsyncQueue } from "@spt/models/spt/utils/IAsyncQueue"; +import { writeFileSync } from "atomically"; +import { checkSync, lockSync, unlockSync } from "proper-lockfile"; +import { inject, injectable } from "tsyringe"; @injectable() -export class VFS -{ +export class VFS { accessFilePromisify: (path: fs.PathLike, mode?: number) => Promise; copyFilePromisify: (src: fs.PathLike, dst: fs.PathLike, flags?: number) => Promise; mkdirPromisify: ( path: fs.PathLike, - options: fs.MakeDirectoryOptions & { recursive: true } + options: fs.MakeDirectoryOptions & { recursive: true }, ) => Promise; readFilePromisify: (path: fs.PathLike) => Promise; writeFilePromisify: (path: fs.PathLike, data: string, options?: any) => Promise; readdirPromisify: ( path: fs.PathLike, - options?: BufferEncoding | { encoding: BufferEncoding, withFileTypes?: false }, + options?: BufferEncoding | { encoding: BufferEncoding; withFileTypes?: false }, ) => Promise; statPromisify: (path: fs.PathLike, options?: fs.StatOptions & { bigint?: false }) => Promise; @@ -31,8 +30,7 @@ export class VFS rmdirPromisify: (path: fs.PathLike) => Promise; renamePromisify: (oldPath: fs.PathLike, newPath: fs.PathLike) => Promise; - constructor(@inject("AsyncQueue") protected asyncQueue: IAsyncQueue) - { + constructor(@inject("AsyncQueue") protected asyncQueue: IAsyncQueue) { this.accessFilePromisify = promisify(fs.access); this.copyFilePromisify = promisify(fs.copyFile); this.mkdirPromisify = promisify(fs.mkdir); @@ -45,15 +43,12 @@ export class VFS this.renamePromisify = promisify(fs.renameSync); } - public exists(filepath: fs.PathLike): boolean - { + public exists(filepath: fs.PathLike): boolean { return fs.existsSync(filepath); } - public async existsAsync(filepath: fs.PathLike): Promise - { - try - { + public async existsAsync(filepath: fs.PathLike): Promise { + try { // Create the command to add to the queue const command = { uuid: crypto.randomUUID(), cmd: async () => await this.accessFilePromisify(filepath) }; // Wait for the command completion @@ -61,32 +56,26 @@ export class VFS // If no Exception, the file exists return true; - } - catch - { + } catch { // If Exception, the file does not exist return false; } } - public copyFile(filepath: fs.PathLike, target: fs.PathLike): void - { + public copyFile(filepath: fs.PathLike, target: fs.PathLike): void { fs.copyFileSync(filepath, target); } - public async copyAsync(filepath: fs.PathLike, target: fs.PathLike): Promise - { + public async copyAsync(filepath: fs.PathLike, target: fs.PathLike): Promise { const command = { uuid: crypto.randomUUID(), cmd: async () => await this.copyFilePromisify(filepath, target) }; await this.asyncQueue.waitFor(command); } - public createDir(filepath: string): void - { + public createDir(filepath: string): void { fs.mkdirSync(filepath.substr(0, filepath.lastIndexOf("/")), { recursive: true }); } - public async createDirAsync(filepath: string): Promise - { + public async createDirAsync(filepath: string): Promise { const command = { uuid: crypto.randomUUID(), cmd: async () => @@ -95,203 +84,162 @@ export class VFS await this.asyncQueue.waitFor(command); } - public copyDir(filepath: string, target: string, fileExtensions?: string | string[]): void - { + public copyDir(filepath: string, target: string, fileExtensions?: string | string[]): void { const files = this.getFiles(filepath); const dirs = this.getDirs(filepath); - if (!this.exists(target)) - { + if (!this.exists(target)) { this.createDir(`${target}/`); } - for (const dir of dirs) - { + for (const dir of dirs) { this.copyDir(path.join(filepath, dir), path.join(target, dir), fileExtensions); } - for (const file of files) - { + for (const file of files) { // copy all if fileExtension is not set, copy only those with fileExtension if set - if (!fileExtensions || fileExtensions.includes(file.split(".").pop() ?? "")) - { + if (!fileExtensions || fileExtensions.includes(file.split(".").pop() ?? "")) { this.copyFile(path.join(filepath, file), path.join(target, file)); } } } - public async copyDirAsync(filepath: string, target: string, fileExtensions: string | string[]): Promise - { + public async copyDirAsync(filepath: string, target: string, fileExtensions: string | string[]): Promise { const files = this.getFiles(filepath); const dirs = this.getDirs(filepath); - if (!(await this.existsAsync(target))) - { + if (!(await this.existsAsync(target))) { await this.createDirAsync(`${target}/`); } - for (const dir of dirs) - { + for (const dir of dirs) { await this.copyDirAsync(path.join(filepath, dir), path.join(target, dir), fileExtensions); } - for (const file of files) - { + for (const file of files) { // copy all if fileExtension is not set, copy only those with fileExtension if set - if (!fileExtensions || fileExtensions.includes(file.split(".").pop() ?? "")) - { + if (!fileExtensions || fileExtensions.includes(file.split(".").pop() ?? "")) { await this.copyAsync(path.join(filepath, file), path.join(target, file)); } } } - public readFile(...args: Parameters): string - { + public readFile(...args: Parameters): string { const read = fs.readFileSync(...args); - if (this.isBuffer(read)) - { + if (this.isBuffer(read)) { return read.toString(); } return read; } - public async readFileAsync(path: fs.PathLike): Promise - { + public async readFileAsync(path: fs.PathLike): Promise { const read = await this.readFilePromisify(path); - if (this.isBuffer(read)) - { + if (this.isBuffer(read)) { return read.toString(); } return read; } - private isBuffer(value: any): value is Buffer - { + private isBuffer(value: any): value is Buffer { return value?.write && value.toString && value.toJSON && value.equals; } - public writeFile(filepath: any, data = "", append = false, atomic = true): void - { + public writeFile(filepath: any, data = "", append = false, atomic = true): void { const options = append ? { flag: "a" } : { flag: "w" }; - if (!this.exists(filepath)) - { + if (!this.exists(filepath)) { this.createDir(filepath); fs.writeFileSync(filepath, ""); } const releaseCallback = this.lockFileSync(filepath); - if (!append && atomic) - { + if (!append && atomic) { writeFileSync(filepath, data); - } - else - { + } else { fs.writeFileSync(filepath, data, options); } releaseCallback(); } - public async writeFileAsync(filepath: any, data = "", append = false, atomic = true): Promise - { + public async writeFileAsync(filepath: any, data = "", append = false, atomic = true): Promise { const options = append ? { flag: "a" } : { flag: "w" }; - if (!(await this.exists(filepath))) - { + if (!(await this.exists(filepath))) { await this.createDir(filepath); await this.writeFilePromisify(filepath, ""); } - if (!append && atomic) - { + if (!append && atomic) { await this.writeFilePromisify(filepath, data); - } - else - { + } else { await this.writeFilePromisify(filepath, data, options); } } - public getFiles(filepath: string): string[] - { - return fs.readdirSync(filepath).filter((item) => - { + public getFiles(filepath: string): string[] { + return fs.readdirSync(filepath).filter((item) => { return fs.statSync(path.join(filepath, item)).isFile(); }); } - public async getFilesAsync(filepath: string): Promise - { + public async getFilesAsync(filepath: string): Promise { const addr = await this.readdirPromisify(filepath); - return addr.filter(async (item) => - { + return addr.filter(async (item) => { const stat = await this.statPromisify(path.join(filepath, item)); return stat.isFile(); }); } - public getDirs(filepath: string): string[] - { - return fs.readdirSync(filepath).filter((item) => - { + public getDirs(filepath: string): string[] { + return fs.readdirSync(filepath).filter((item) => { return fs.statSync(path.join(filepath, item)).isDirectory(); }); } - public async getDirsAsync(filepath: string): Promise - { + public async getDirsAsync(filepath: string): Promise { const addr = await this.readdirPromisify(filepath); - return addr.filter(async (item) => - { + return addr.filter(async (item) => { const stat = await this.statPromisify(path.join(filepath, item)); return stat.isDirectory(); }); } - public removeFile(filepath: string): void - { + public removeFile(filepath: string): void { fs.unlinkSync(filepath); } - public async removeFileAsync(filepath: string): Promise - { + public async removeFileAsync(filepath: string): Promise { await this.unlinkPromisify(filepath); } - public removeDir(filepath: string): void - { + public removeDir(filepath: string): void { const files = this.getFiles(filepath); const dirs = this.getDirs(filepath); - for (const dir of dirs) - { + for (const dir of dirs) { this.removeDir(path.join(filepath, dir)); } - for (const file of files) - { + for (const file of files) { this.removeFile(path.join(filepath, file)); } fs.rmdirSync(filepath); } - public async removeDirAsync(filepath: string): Promise - { + public async removeDirAsync(filepath: string): Promise { const files = this.getFiles(filepath); const dirs = this.getDirs(filepath); const promises: Promise[] = []; - for (const dir of dirs) - { + for (const dir of dirs) { promises.push(this.removeDirAsync(path.join(filepath, dir))); } - for (const file of files) - { + for (const file of files) { promises.push(this.removeFileAsync(path.join(filepath, file))); } @@ -299,63 +247,51 @@ export class VFS await this.rmdirPromisify(filepath); } - public rename(oldPath: string, newPath: string): void - { + public rename(oldPath: string, newPath: string): void { fs.renameSync(oldPath, newPath); } - public async renameAsync(oldPath: string, newPath: string): Promise - { + public async renameAsync(oldPath: string, newPath: string): Promise { await this.renamePromisify(oldPath, newPath); } - protected lockFileSync(filepath: any): () => void - { + protected lockFileSync(filepath: any): () => void { return lockSync(filepath); } - protected checkFileSync(filepath: any): boolean - { + protected checkFileSync(filepath: any): boolean { return checkSync(filepath); } - protected unlockFileSync(filepath: any): void - { + protected unlockFileSync(filepath: any): void { unlockSync(filepath); } - public getFileExtension(filepath: string): string | undefined - { + public getFileExtension(filepath: string): string | undefined { return filepath.split(".").pop(); } - public stripExtension(filepath: string): string - { + public stripExtension(filepath: string): string { return filepath.split(".").slice(0, -1).join("."); } - public async minifyAllJsonInDirRecursive(filepath: string): Promise - { + public async minifyAllJsonInDirRecursive(filepath: string): Promise { const files = this.getFiles(filepath).filter((item) => this.getFileExtension(item) === "json"); - for (const file of files) - { + for (const file of files) { const filePathAndName = path.join(filepath, file); const minified = JSON.stringify(JSON.parse(this.readFile(filePathAndName))); this.writeFile(filePathAndName, minified); } const dirs = this.getDirs(filepath); - for (const dir of dirs) - { + for (const dir of dirs) { this.minifyAllJsonInDirRecursive(path.join(filepath, dir)); } } - public async minifyAllJsonInDirRecursiveAsync(filepath: string): Promise - { + public async minifyAllJsonInDirRecursiveAsync(filepath: string): Promise { const files = this.getFiles(filepath).filter((item) => this.getFileExtension(item) === "json"); - for (const file of files) - { + for (const file of files) { const filePathAndName = path.join(filepath, file); const minified = JSON.stringify(JSON.parse(await this.readFile(filePathAndName))); await this.writeFile(filePathAndName, minified); @@ -363,33 +299,25 @@ export class VFS const dirs = this.getDirs(filepath); const promises: Promise[] = []; - for (const dir of dirs) - { + for (const dir of dirs) { promises.push(this.minifyAllJsonInDirRecursive(path.join(filepath, dir))); } await Promise.all(promises); } - public getFilesOfType(directory: string, fileType: string, files: string[] = []): string[] - { + public getFilesOfType(directory: string, fileType: string, files: string[] = []): string[] { // no dir so exit early - if (!fs.existsSync(directory)) - { + if (!fs.existsSync(directory)) { return files; } const dirents = fs.readdirSync(directory, { encoding: "utf-8", withFileTypes: true }); - for (const dirent of dirents) - { + for (const dirent of dirents) { const res = resolve(directory, dirent.name); - if (dirent.isDirectory()) - { + if (dirent.isDirectory()) { this.getFilesOfType(res, fileType, files); - } - else - { - if (res.endsWith(fileType)) - { + } else { + if (res.endsWith(fileType)) { files.push(res); } } diff --git a/project/src/utils/Watermark.ts b/project/src/utils/Watermark.ts index cb8a02af..3773cd48 100644 --- a/project/src/utils/Watermark.ts +++ b/project/src/utils/Watermark.ts @@ -1,20 +1,18 @@ -import { inject, injectable } from "tsyringe"; import { ConfigTypes } from "@spt/models/enums/ConfigTypes"; import { ICoreConfig } from "@spt/models/spt/config/ICoreConfig"; import { LogTextColor } from "@spt/models/spt/logging/LogTextColor"; import { ILogger } from "@spt/models/spt/utils/ILogger"; import { ConfigServer } from "@spt/servers/ConfigServer"; import { LocalisationService } from "@spt/services/LocalisationService"; +import { inject, injectable } from "tsyringe"; @injectable() -export class WatermarkLocale -{ +export class WatermarkLocale { protected description: string[]; protected warning: string[]; protected modding: string[]; - constructor(@inject("LocalisationService") protected localisationService: LocalisationService) - { + constructor(@inject("LocalisationService") protected localisationService: LocalisationService) { this.description = [ this.localisationService.getText("watermark-discord_url"), "", @@ -41,25 +39,21 @@ export class WatermarkLocale ]; } - public getDescription(): string[] - { + public getDescription(): string[] { return this.description; } - public getWarning(): string[] - { + public getWarning(): string[] { return this.warning; } - public getModding(): string[] - { + public getModding(): string[] { return this.modding; } } @injectable() -export class Watermark -{ +export class Watermark { protected sptConfig: ICoreConfig; protected text: string[] = []; protected versionLabel = ""; @@ -69,13 +63,11 @@ export class Watermark @inject("ConfigServer") protected configServer: ConfigServer, @inject("LocalisationService") protected localisationService: LocalisationService, @inject("WatermarkLocale") protected watermarkLocale: WatermarkLocale, - ) - { + ) { this.sptConfig = this.configServer.getConfig(ConfigTypes.CORE); } - public initialize(): void - { + public initialize(): void { const description = this.watermarkLocale.getDescription(); const warning = this.watermarkLocale.getWarning(); const modding = this.watermarkLocale.getModding(); @@ -86,21 +78,16 @@ export class Watermark this.text = [this.versionLabel]; this.text = [...this.text, ...description]; - if (globalThis.G_DEBUG_CONFIGURATION) - { + if (globalThis.G_DEBUG_CONFIGURATION) { this.text = this.text.concat([...warning]); } - if (!globalThis.G_MODS_ENABLED) - { + if (!globalThis.G_MODS_ENABLED) { this.text = this.text.concat([...modding]); } - if (this.sptConfig.customWatermarkLocaleKeys) - { - if (this.sptConfig.customWatermarkLocaleKeys.length > 0) - { - for (const key of this.sptConfig.customWatermarkLocaleKeys) - { + if (this.sptConfig.customWatermarkLocaleKeys) { + if (this.sptConfig.customWatermarkLocaleKeys.length > 0) { + for (const key of this.sptConfig.customWatermarkLocaleKeys) { this.text.push(...["", this.localisationService.getText(key)]); } } @@ -116,15 +103,13 @@ export class Watermark * @param withEftVersion Include the eft version this spt version was made for * @returns string */ - public getVersionTag(withEftVersion = false): string - { + public getVersionTag(withEftVersion = false): string { const sptVersion = globalThis.G_SPTVERSION || this.sptConfig.sptVersion; const versionTag = globalThis.G_DEBUG_CONFIGURATION ? `${sptVersion} - ${this.localisationService.getText("bleeding_edge_build")}` : sptVersion; - if (withEftVersion) - { + if (withEftVersion) { const tarkovVersion = this.sptConfig.compatibleTarkovVersion.split(".").pop(); return `${versionTag} (${tarkovVersion})`; } @@ -137,8 +122,7 @@ export class Watermark * Get text shown in game on screen, can't be translated as it breaks bsgs client when certian characters are used * @returns string */ - public getInGameVersionLabel(): string - { + public getInGameVersionLabel(): string { const sptVersion = globalThis.G_SPTVERSION || this.sptConfig.sptVersion; const versionTag = globalThis.G_DEBUG_CONFIGURATION ? `${sptVersion} - BLEEDINGEDGE ${globalThis.G_COMMIT?.slice(0, 6) ?? ""}` @@ -148,33 +132,28 @@ export class Watermark } /** Set window title */ - protected setTitle(): void - { + protected setTitle(): void { process.title = this.versionLabel; } /** Reset console cursor to top */ - protected resetCursor(): void - { + protected resetCursor(): void { process.stdout.write("\u001B[2J\u001B[0;0f"); } /** Draw the watermark */ - protected draw(): void - { + protected draw(): void { const result: string[] = []; // Calculate size, add 10% for spacing to the right - const longestLength - = this.text.reduce((a, b) => - { + const longestLength = + this.text.reduce((a, b) => { return a.length > b.length ? a : b; }).length * 1.1; // Create line of - to add top/bottom of watermark let line = ""; - for (let i = 0; i < longestLength; ++i) - { + for (let i = 0; i < longestLength; ++i) { line += "─"; } @@ -182,13 +161,11 @@ export class Watermark result.push(`┌─${line}─┐`); // Add content of watermark to screen - for (const watermarkText of this.text) - { + for (const watermarkText of this.text) { const spacingSize = longestLength - watermarkText.length; let textWithRightPadding = watermarkText; - for (let i = 0; i < spacingSize; ++i) - { + for (let i = 0; i < spacingSize; ++i) { textWithRightPadding += " "; } @@ -199,8 +176,7 @@ export class Watermark result.push(`└─${line}─┘`); // Log watermark to screen - for (const text of result) - { + for (const text of result) { this.logger.logWithColor(text, LogTextColor.YELLOW); } } diff --git a/project/src/utils/cloners/ICloner.ts b/project/src/utils/cloners/ICloner.ts index 8c98799d..77c05418 100644 --- a/project/src/utils/cloners/ICloner.ts +++ b/project/src/utils/cloners/ICloner.ts @@ -1,4 +1,3 @@ -export interface ICloner -{ - clone(obj: T): T +export interface ICloner { + clone(obj: T): T; } diff --git a/project/src/utils/cloners/JsonCloner.ts b/project/src/utils/cloners/JsonCloner.ts index 619af8c1..7b37dca5 100644 --- a/project/src/utils/cloners/JsonCloner.ts +++ b/project/src/utils/cloners/JsonCloner.ts @@ -1,11 +1,9 @@ -import { injectable } from "tsyringe"; import type { ICloner } from "@spt/utils/cloners/ICloner"; +import { injectable } from "tsyringe"; @injectable() -export class JsonCloner implements ICloner -{ - public clone(obj: T): T - { +export class JsonCloner implements ICloner { + public clone(obj: T): T { return JSON.parse(JSON.stringify(obj)); } } diff --git a/project/src/utils/cloners/RecursiveCloner.ts b/project/src/utils/cloners/RecursiveCloner.ts index 8c586910..6dbf36fe 100644 --- a/project/src/utils/cloners/RecursiveCloner.ts +++ b/project/src/utils/cloners/RecursiveCloner.ts @@ -1,9 +1,8 @@ -import { injectable } from "tsyringe"; import type { ICloner } from "@spt/utils/cloners/ICloner"; +import { injectable } from "tsyringe"; @injectable() -export class RecursiveCloner implements ICloner -{ +export class RecursiveCloner implements ICloner { private static primitives = new Set([ "string", "number", @@ -14,34 +13,27 @@ export class RecursiveCloner implements ICloner "null", ]); - public clone(obj: T): T - { + public clone(obj: T): T { // if null or undefined return it as is - if (obj === null || obj === undefined) - return obj; + if (obj === null || obj === undefined) return obj; const typeOfObj = typeof obj; // no need to clone these types, they are primitives - if (RecursiveCloner.primitives.has(typeOfObj)) - { + if (RecursiveCloner.primitives.has(typeOfObj)) { return obj; } // clone the object types - if (typeOfObj === "object") - { - if (Array.isArray(obj)) - { + if (typeOfObj === "object") { + if (Array.isArray(obj)) { // biome-ignore lint/suspicious/noExplicitAny: used for clone const objArr = obj as Array; return objArr.map((v) => this.clone(v)) as T; } const newObj = {}; - for (const propOf1 in obj) - { + for (const propOf1 in obj) { // If the value of the original property is null, ensure the cloned value is also null // This fixes an issue where null arrays were incorrectly being converted to empty objects - if (obj[propOf1] === null || obj[propOf1] === undefined) - { + if (obj[propOf1] === null || obj[propOf1] === undefined) { newObj[propOf1.toString()] = obj[propOf1]; continue; } diff --git a/project/src/utils/cloners/StructuredCloner.ts b/project/src/utils/cloners/StructuredCloner.ts index 977cd2dd..267a7d63 100644 --- a/project/src/utils/cloners/StructuredCloner.ts +++ b/project/src/utils/cloners/StructuredCloner.ts @@ -1,11 +1,9 @@ -import { injectable } from "tsyringe"; import type { ICloner } from "@spt/utils/cloners/ICloner"; +import { injectable } from "tsyringe"; @injectable() -export class StructuredCloner implements ICloner -{ - public clone(obj: T): T - { +export class StructuredCloner implements ICloner { + public clone(obj: T): T { return structuredClone(obj); } } diff --git a/project/src/utils/collections/lists/LinkedList.ts b/project/src/utils/collections/lists/LinkedList.ts index 94ce1edd..08c94e72 100644 --- a/project/src/utils/collections/lists/LinkedList.ts +++ b/project/src/utils/collections/lists/LinkedList.ts @@ -1,23 +1,19 @@ import { LinkedListNode } from "@spt/utils/collections/lists/Nodes"; -export class LinkedList -{ +export class LinkedList { private head?: LinkedListNode; private tail?: LinkedListNode; private _length: number; - public get length(): number - { + public get length(): number { return this._length; } - private set length(value: number) - { + private set length(value: number) { this._length = value; } - constructor() - { + constructor() { this.length = 0; this.head = this.tail = undefined; } @@ -25,13 +21,11 @@ export class LinkedList /** * Adds an element to the start of the list. */ - public prepend(value: T): void - { + public prepend(value: T): void { const node = new LinkedListNode(value); this.length++; - if (!this.head) - { + if (!this.head) { this.head = this.tail = node; return; } @@ -44,28 +38,23 @@ export class LinkedList /** * Adds an element at the given index to the list. */ - public insertAt(value: T, idx: number): void - { - if (idx < 0 || idx > this.length) - { + public insertAt(value: T, idx: number): void { + if (idx < 0 || idx > this.length) { return; } - if (idx === 0) - { + if (idx === 0) { this.prepend(value); return; } - if (idx === this.length) - { + if (idx === this.length) { this.append(value); return; } let ref = this.head; - for (let i = 0; i <= idx; ++i) - { + for (let i = 0; i <= idx; ++i) { ref = ref?.next; } @@ -74,13 +63,11 @@ export class LinkedList node.next = ref; node.prev = ref?.prev; - if (ref) - { + if (ref) { ref.prev = node; } - if (node.prev) - { + if (node.prev) { node.prev.next = node; } } @@ -88,13 +75,11 @@ export class LinkedList /** * Adds an element to the end of the list. */ - public append(value: T): void - { + public append(value: T): void { const node = new LinkedListNode(value); this.length++; - if (!this.tail) - { + if (!this.tail) { this.head = this.tail = node; return; } @@ -107,35 +92,28 @@ export class LinkedList /** * Returns the first element's value. */ - public getHead(): T | undefined - { + public getHead(): T | undefined { return this.head?.value; } /** * Finds the element from the list at the given index and returns it's value. */ - public get(idx: number): T | undefined - { - if (idx < 0 || idx >= this.length) - { + public get(idx: number): T | undefined { + if (idx < 0 || idx >= this.length) { return; } - if (idx === 0) - { + if (idx === 0) { return this.getHead(); } - if (idx === this.length - 1) - { + if (idx === this.length - 1) { return this.getTail(); } - for (const [index, value] of this.entries()) - { - if (idx === index) - { + for (const [index, value] of this.entries()) { + if (idx === index) { return value; } } @@ -144,56 +122,46 @@ export class LinkedList /** * Returns the last element's value. */ - public getTail(): T | undefined - { + public getTail(): T | undefined { return this.tail?.value; } /** * Finds and removes the first element from a list that has a value equal to the given value, returns it's value if it successfully removed it. */ - public remove(value: T): T | undefined - { + public remove(value: T): T | undefined { let ref = this.head; - for (let i = 0; ref && i < this.length; ++i) - { - if (ref.value === value) - { + for (let i = 0; ref && i < this.length; ++i) { + if (ref.value === value) { break; } ref = ref.next; } - if (!ref) - { + if (!ref) { return; } this.length--; - if (this.length === 0) - { + if (this.length === 0) { const out = this.head?.value; this.head = this.tail = undefined; return out; } - if (ref.prev) - { + if (ref.prev) { ref.prev.next = ref.next; } - if (ref.next) - { + if (ref.next) { ref.next.prev = ref.prev; } - if (ref === this.head) - { + if (ref === this.head) { this.head = ref.next; } - if (ref === this.tail) - { + if (ref === this.tail) { this.tail = ref.prev; } @@ -205,10 +173,8 @@ export class LinkedList /** * Removes the first element from the list and returns it's value. If the list is empty, undefined is returned and the list is not modified. */ - public shift(): T | undefined - { - if (!this.head) - { + public shift(): T | undefined { + if (!this.head) { return; } @@ -219,8 +185,7 @@ export class LinkedList ref.next = undefined; - if (this.length === 0) - { + if (this.length === 0) { this.tail = undefined; } @@ -230,37 +195,30 @@ export class LinkedList /** * Removes the element from the list at the given index and returns it's value. */ - public removeAt(idx: number): T | undefined - { - if (idx < 0 || idx >= this.length) - { + public removeAt(idx: number): T | undefined { + if (idx < 0 || idx >= this.length) { return; } - if (idx === 0) - { + if (idx === 0) { return this.shift(); } - if (idx === this.length - 1) - { + if (idx === this.length - 1) { return this.pop(); } let ref = this.head; this.length--; - for (let i = 0; i < idx; ++i) - { + for (let i = 0; i < idx; ++i) { ref = ref?.next; } - if (ref?.prev) - { + if (ref?.prev) { ref.prev.next = ref.next; } - if (ref?.next) - { + if (ref?.next) { ref.next.prev = ref.prev; } @@ -270,10 +228,8 @@ export class LinkedList /** * Removes the last element from the list and returns it's value. If the list is empty, undefined is returned and the list is not modified. */ - public pop(): T | undefined - { - if (!this.tail) - { + public pop(): T | undefined { + if (!this.tail) { return; } @@ -284,8 +240,7 @@ export class LinkedList ref.prev = undefined; - if (this.length === 0) - { + if (this.length === 0) { this.head = undefined; } @@ -295,11 +250,9 @@ export class LinkedList /** * Returns an iterable of index, value pairs for every entry in the list. */ - public *entries(): IterableIterator<[number, T | undefined]> - { + public *entries(): IterableIterator<[number, T | undefined]> { let node = this.head; - for (let i = 0; i < this.length; ++i) - { + for (let i = 0; i < this.length; ++i) { yield [i, node?.value]; node = node?.next; } @@ -308,11 +261,9 @@ export class LinkedList /** * Returns an iterable of values in the list. */ - public *values(): IterableIterator - { + public *values(): IterableIterator { let node = this.head; - while (node) - { + while (node) { yield node.value; node = node.next; } diff --git a/project/src/utils/collections/lists/Nodes.ts b/project/src/utils/collections/lists/Nodes.ts index 8d518bdd..df7a71b1 100644 --- a/project/src/utils/collections/lists/Nodes.ts +++ b/project/src/utils/collections/lists/Nodes.ts @@ -1,9 +1,7 @@ -export class LinkedListNode -{ +export class LinkedListNode { constructor( public value: T, public prev?: LinkedListNode, public next?: LinkedListNode, - ) - {} + ) {} } diff --git a/project/src/utils/collections/queue/Queue.ts b/project/src/utils/collections/queue/Queue.ts index 7a765076..ca402953 100644 --- a/project/src/utils/collections/queue/Queue.ts +++ b/project/src/utils/collections/queue/Queue.ts @@ -1,34 +1,28 @@ import { LinkedList } from "@spt/utils/collections/lists/LinkedList"; -export class Queue -{ +export class Queue { private list: LinkedList; - public get length(): number - { + public get length(): number { return this.list.length; } - constructor() - { + constructor() { this.list = new LinkedList(); } /** * Adds an element to the end of the queue. */ - public enqueue(element: T): void - { + public enqueue(element: T): void { this.list.append(element); } /** * Iterates over the elements received and adds each one to the end of the queue. */ - public enqueueAll(elements: T[]): void - { - for (const element of elements) - { + public enqueueAll(elements: T[]): void { + for (const element of elements) { this.enqueue(element); } } @@ -36,16 +30,14 @@ export class Queue /** * Removes the first element from the queue and returns it's value. If the queue is empty, undefined is returned and the queue is not modified. */ - public dequeue(): T | undefined - { + public dequeue(): T | undefined { return this.list.shift(); } /** * Returns the first element's value. */ - public peek(): T | undefined - { + public peek(): T | undefined { return this.list.getHead(); } } diff --git a/project/src/utils/logging/AbstractWinstonLogger.ts b/project/src/utils/logging/AbstractWinstonLogger.ts index cac3e153..29969bf2 100644 --- a/project/src/utils/logging/AbstractWinstonLogger.ts +++ b/project/src/utils/logging/AbstractWinstonLogger.ts @@ -1,8 +1,6 @@ import crypto from "node:crypto"; import fs from "node:fs"; import { promisify } from "node:util"; -import winston, { createLogger, format, transports, addColors } from "winston"; -import DailyRotateFile from "winston-daily-rotate-file"; import { Daum } from "@spt/models/eft/itemEvent/IItemEventRouterRequest"; import { LogBackgroundColor } from "@spt/models/spt/logging/LogBackgroundColor"; import { LogTextColor } from "@spt/models/spt/logging/LogTextColor"; @@ -10,9 +8,10 @@ import { SptLogger } from "@spt/models/spt/logging/SptLogger"; import { IAsyncQueue } from "@spt/models/spt/utils/IAsyncQueue"; import { ICommand } from "@spt/models/spt/utils/ICommand"; import { ILogger } from "@spt/models/spt/utils/ILogger"; +import winston, { createLogger, format, transports, addColors } from "winston"; +import DailyRotateFile from "winston-daily-rotate-file"; -export abstract class AbstractWinstonLogger implements ILogger -{ +export abstract class AbstractWinstonLogger implements ILogger { protected showDebugInConsole = false; protected filePath: string; protected logLevels = { @@ -34,35 +33,30 @@ export abstract class AbstractWinstonLogger implements ILogger protected logger: winston.Logger & SptLogger; protected writeFilePromisify: (path: fs.PathLike, data: string, options?: any) => Promise; - constructor(protected asyncQueue: IAsyncQueue) - { + constructor(protected asyncQueue: IAsyncQueue) { this.filePath = `${this.getFilePath()}${this.getFileName()}`; this.writeFilePromisify = promisify(fs.writeFile); this.showDebugInConsole = globalThis.G_DEBUG_CONFIGURATION; - if (!fs.existsSync(this.getFilePath())) - { + if (!fs.existsSync(this.getFilePath())) { fs.mkdirSync(this.getFilePath(), { recursive: true }); } const transportsList: winston.transport[] = []; - if (this.isLogToConsole()) - { + if (this.isLogToConsole()) { transportsList.push( new transports.Console({ level: this.showDebugInConsole ? "debug" : "custom", format: format.combine( format.colorize({ all: true, colors: this.logLevels.colors }), - format.printf(({ message }) => - { + format.printf(({ message }) => { return `${message}`; }), ), }), ); } - if (this.isLogToFile()) - { + if (this.isLogToFile()) { transportsList.push( new DailyRotateFile({ level: "debug", @@ -76,8 +70,7 @@ export abstract class AbstractWinstonLogger implements ILogger format.timestamp(), format.align(), format.json(), - format.printf(({ timestamp, level, message }) => - { + format.printf(({ timestamp, level, message }) => { return `[${timestamp}] ${level}: ${message}`; }), ), @@ -88,10 +81,8 @@ export abstract class AbstractWinstonLogger implements ILogger addColors(this.logLevels.colors); this.logger = createLogger({ levels: this.logLevels.levels, transports: [...transportsList] }); - if (this.isLogExceptions()) - { - process.on("uncaughtException", (error) => - { + if (this.isLogExceptions()) { + process.on("uncaughtException", (error) => { this.error(`${error.name}: ${error.message}`); this.error(error.stack ?? "No stack"); }); @@ -108,23 +99,19 @@ export abstract class AbstractWinstonLogger implements ILogger protected abstract getFileName(): string; - protected getLogFrequency(): string - { + protected getLogFrequency(): string { return "3h"; } - protected getLogMaxSize(): string - { + protected getLogMaxSize(): string { return "5m"; } - protected getLogMaxFiles(): string - { + protected getLogMaxFiles(): string { return "14d"; } - public async writeToLogFile(data: string | Daum): Promise - { + public async writeToLogFile(data: string | Daum): Promise { const command: ICommand = { uuid: crypto.randomUUID(), cmd: async () => await this.writeFilePromisify(this.filePath, `${data}\n`, true), @@ -136,8 +123,7 @@ export abstract class AbstractWinstonLogger implements ILogger data: string | Error | Record, color: string, backgroundColor = "", - ): Promise - { + ): Promise { const textColor = `${color} ${backgroundColor}`.trimEnd(); const tmpLogger = createLogger({ levels: { custom: 0 }, @@ -154,12 +140,9 @@ export abstract class AbstractWinstonLogger implements ILogger let command: ICommand; - if (typeof data === "string") - { + if (typeof data === "string") { command = { uuid: crypto.randomUUID(), cmd: async () => await tmpLogger.log("custom", data) }; - } - else - { + } else { command = { uuid: crypto.randomUUID(), cmd: async () => await tmpLogger.log("custom", JSON.stringify(data, undefined, 4)), @@ -169,26 +152,22 @@ export abstract class AbstractWinstonLogger implements ILogger await this.asyncQueue.waitFor(command); } - public async error(data: string | Record): Promise - { + public async error(data: string | Record): Promise { const command: ICommand = { uuid: crypto.randomUUID(), cmd: async () => await this.logger.error(data) }; await this.asyncQueue.waitFor(command); } - public async warning(data: string | Record): Promise - { + public async warning(data: string | Record): Promise { const command: ICommand = { uuid: crypto.randomUUID(), cmd: async () => await this.logger.warn(data) }; await this.asyncQueue.waitFor(command); } - public async success(data: string | Record): Promise - { + public async success(data: string | Record): Promise { const command: ICommand = { uuid: crypto.randomUUID(), cmd: async () => await this.logger.succ!(data) }; await this.asyncQueue.waitFor(command); } - public async info(data: string | Record): Promise - { + public async info(data: string | Record): Promise { const command: ICommand = { uuid: crypto.randomUUID(), cmd: async () => await this.logger.info(data) }; await this.asyncQueue.waitFor(command); } @@ -203,8 +182,7 @@ export abstract class AbstractWinstonLogger implements ILogger data: string | Record, textColor: LogTextColor, backgroundColor = LogBackgroundColor.DEFAULT, - ): Promise - { + ): Promise { const command: ICommand = { uuid: crypto.randomUUID(), cmd: async () => await this.log(data, textColor.toString(), backgroundColor.toString()), @@ -213,16 +191,12 @@ export abstract class AbstractWinstonLogger implements ILogger await this.asyncQueue.waitFor(command); } - public async debug(data: string | Record, onlyShowInConsole = false): Promise - { + public async debug(data: string | Record, onlyShowInConsole = false): Promise { let command: ICommand; - if (onlyShowInConsole) - { + if (onlyShowInConsole) { command = { uuid: crypto.randomUUID(), cmd: async () => await this.log(data, this.logLevels.colors.debug) }; - } - else - { + } else { command = { uuid: crypto.randomUUID(), cmd: async () => await this.logger.debug(data) }; } diff --git a/project/src/utils/logging/WinstonMainLogger.ts b/project/src/utils/logging/WinstonMainLogger.ts index a2a4b304..091ac67d 100644 --- a/project/src/utils/logging/WinstonMainLogger.ts +++ b/project/src/utils/logging/WinstonMainLogger.ts @@ -1,37 +1,30 @@ -import { inject, injectable } from "tsyringe"; import { IAsyncQueue } from "@spt/models/spt/utils/IAsyncQueue"; import { AbstractWinstonLogger } from "@spt/utils/logging/AbstractWinstonLogger"; +import { inject, injectable } from "tsyringe"; @injectable() -export class WinstonMainLogger extends AbstractWinstonLogger -{ - constructor(@inject("AsyncQueue") protected asyncQueue: IAsyncQueue) - { +export class WinstonMainLogger extends AbstractWinstonLogger { + constructor(@inject("AsyncQueue") protected asyncQueue: IAsyncQueue) { super(asyncQueue); } - protected isLogExceptions(): boolean - { + protected isLogExceptions(): boolean { return true; } - protected isLogToFile(): boolean - { + protected isLogToFile(): boolean { return true; } - protected isLogToConsole(): boolean - { + protected isLogToConsole(): boolean { return true; } - protected getFilePath(): string - { + protected getFilePath(): string { return "./user/logs/"; } - protected getFileName(): string - { + protected getFileName(): string { return "server-%DATE%.log"; } } diff --git a/project/src/utils/logging/WinstonRequestLogger.ts b/project/src/utils/logging/WinstonRequestLogger.ts index 7e31c330..fa4472e4 100644 --- a/project/src/utils/logging/WinstonRequestLogger.ts +++ b/project/src/utils/logging/WinstonRequestLogger.ts @@ -1,42 +1,34 @@ -import { inject, injectable } from "tsyringe"; import { IAsyncQueue } from "@spt/models/spt/utils/IAsyncQueue"; import { AbstractWinstonLogger } from "@spt/utils/logging/AbstractWinstonLogger"; +import { inject, injectable } from "tsyringe"; @injectable() -export class WinstonRequestLogger extends AbstractWinstonLogger -{ - constructor(@inject("AsyncQueue") protected asyncQueue: IAsyncQueue) - { +export class WinstonRequestLogger extends AbstractWinstonLogger { + constructor(@inject("AsyncQueue") protected asyncQueue: IAsyncQueue) { super(asyncQueue); } - protected isLogExceptions(): boolean - { + protected isLogExceptions(): boolean { return false; } - protected isLogToFile(): boolean - { + protected isLogToFile(): boolean { return true; } - protected isLogToConsole(): boolean - { + protected isLogToConsole(): boolean { return false; } - protected getFilePath(): string - { + protected getFilePath(): string { return "./user/logs/requests/"; } - protected getFileName(): string - { + protected getFileName(): string { return "requests-%DATE%.log"; } - protected override getLogMaxSize(): string - { + protected override getLogMaxSize(): string { return "80mb"; } } diff --git a/project/tests/CustomEnvironment.ts b/project/tests/CustomEnvironment.ts index a813414c..c0ac99c4 100644 --- a/project/tests/CustomEnvironment.ts +++ b/project/tests/CustomEnvironment.ts @@ -1,21 +1,20 @@ import "reflect-metadata"; import path from "node:path"; -import { DependencyContainer, Lifecycle, container } from "tsyringe"; -import type { Environment } from "vitest"; import { Container } from "@spt/di/Container"; import { IDatabaseTables } from "@spt/models/spt/server/IDatabaseTables"; import { DatabaseServer } from "@spt/servers/DatabaseServer"; import { ImporterUtil } from "@spt/utils/ImporterUtil"; +import { DependencyContainer, Lifecycle, container } from "tsyringe"; +import type { Environment } from "vitest"; // Manually mock the logger. import { WinstonLogger } from "@tests/__mocks__/WinstonLogger.mock"; -export default { +export default ({ name: "spt-server", transformMode: "ssr", - async setup() - { + async setup() { // Register all of the dependencies in the container. Container.registerTypes(container); Container.registerListTypes(container); @@ -27,11 +26,10 @@ export default { await importDatabase(container); return { - async teardown() - {}, + async teardown() {}, }; }, -}; +}); /** * Reads the database JSON files and imports them into memory. @@ -39,8 +37,7 @@ export default { * @param container The dependency container. * @returns A void promise. */ -async function importDatabase(container: DependencyContainer): Promise -{ +async function importDatabase(container: DependencyContainer): Promise { const importerUtil = container.resolve("ImporterUtil"); const databaseServer = container.resolve("DatabaseServer"); diff --git a/project/tests/__factories__/ProfileInsurance.factory.ts b/project/tests/__factories__/ProfileInsurance.factory.ts index 1ff0366b..a1a83ec6 100644 --- a/project/tests/__factories__/ProfileInsurance.factory.ts +++ b/project/tests/__factories__/ProfileInsurance.factory.ts @@ -1,24 +1,21 @@ import "reflect-metadata"; -import { format } from "date-fns"; -import { container } from "tsyringe"; import { ItemHelper } from "@spt/helpers/ItemHelper"; import { Insurance } from "@spt/models/eft/profile/ISptProfile"; import { profileInsuranceFixture } from "@tests/__fixture__/profileInsurance.fixture"; +import { format } from "date-fns"; +import { container } from "tsyringe"; type DateInput = number | number[] | { [index: number]: number }; -export class ProfileInsuranceFactory -{ +export class ProfileInsuranceFactory { private profileInsuranceFixture: Insurance[]; - constructor() - { + constructor() { this.init(); } - public init(): this - { + public init(): this { this.profileInsuranceFixture = JSON.parse(JSON.stringify(profileInsuranceFixture)); // Deep clone. return this; } @@ -27,20 +24,15 @@ export class ProfileInsuranceFactory * Adjusts the scheduledTime, messageContent.systemData.date, and messageContent.systemData.time, otherwise the * dates in the original fixture will likely be expired. */ - public adjustPackageDates(dateInput?: DateInput): this - { - this.profileInsuranceFixture = this.profileInsuranceFixture.map((insurance, index) => - { + public adjustPackageDates(dateInput?: DateInput): this { + this.profileInsuranceFixture = this.profileInsuranceFixture.map((insurance, index) => { // Default to 1 hour ago. - const defaultDate = Math.floor((Date.now() / 1000) - (1 * 60 * 60)); + const defaultDate = Math.floor(Date.now() / 1000 - 1 * 60 * 60); let date: number; - if (Array.isArray(dateInput) || typeof dateInput === "object") - { + if (Array.isArray(dateInput) || typeof dateInput === "object") { date = dateInput[index] || defaultDate; - } - else - { + } else { date = dateInput || defaultDate; } @@ -56,12 +48,10 @@ export class ProfileInsuranceFactory /** * Removes all attachment items that are currently attached to their parent, leaving the "normal" base items. */ - public removeAttachmentItems(): this - { + public removeAttachmentItems(): this { const itemHelper = container.resolve("ItemHelper"); - this.profileInsuranceFixture = this.profileInsuranceFixture.map((insurance) => - { + this.profileInsuranceFixture = this.profileInsuranceFixture.map((insurance) => { insurance.items = insurance.items.filter((item) => !itemHelper.isAttachmentAttached(item)); return insurance; }); @@ -73,12 +63,10 @@ export class ProfileInsuranceFactory * Removes all normal base items leaving only attachment items that are currently attached to their parent. * This *will* cause orphaned attachments. */ - public removeRegularItems(): this - { + public removeRegularItems(): this { const itemHelper = container.resolve("ItemHelper"); - this.profileInsuranceFixture = this.profileInsuranceFixture.map((insurance) => - { + this.profileInsuranceFixture = this.profileInsuranceFixture.map((insurance) => { insurance.items = insurance.items.filter((item) => itemHelper.isAttachmentAttached(item)); return insurance; }); @@ -86,8 +74,7 @@ export class ProfileInsuranceFactory return this; } - public get(): Insurance[] - { + public get(): Insurance[] { return this.profileInsuranceFixture; } } diff --git a/project/tests/__fixture__/profileInsurance.fixture.ts b/project/tests/__fixture__/profileInsurance.fixture.ts index d67395b1..a361039d 100644 --- a/project/tests/__fixture__/profileInsurance.fixture.ts +++ b/project/tests/__fixture__/profileInsurance.fixture.ts @@ -1,1388 +1,1624 @@ import { Insurance } from "@spt/models/eft/profile/ISptProfile"; -export const profileInsuranceFixture: Insurance[] = [{ - scheduledTime: 1712950044.4, - traderId: "54cb50c76803fa8b248b4571", - maxStorageTime: 345600, - systemData: { date: "11.04.2024", time: "18:59", location: "factory4_day" }, - messageType: 8, - messageTemplateId: "58fe0e4586f774728248ca13 0", - items: [{ - _id: "35111c9b72a87b6b7d95ad35", - _tpl: "58948c8e86f77409493f7266", - parentId: "d2b3b859f667d4fd8b35bc96", - slotId: "hideout", - upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, - }, { - _id: "d45436a159654f43ca3aa52f", - _tpl: "5580223e4bdc2d1c128b457f", - parentId: "d2b3b859f667d4fd8b35bc96", - slotId: "hideout", - upd: { - FireMode: { FireMode: "single" }, - StackObjectsCount: 1, - Repairable: { Durability: 100, MaxDurability: 100 }, - }, - }, { - _id: "2c60ad9b6051f059ab796aa6", - _tpl: "5a7ae0c351dfba0017554310", - parentId: "d2b3b859f667d4fd8b35bc96", - slotId: "hideout", - upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, - }, { - _id: "a5c86cef7d25f57bf0fb593c", - _tpl: "5b432f3d5acfc4704b4a1dfb", - parentId: "d2b3b859f667d4fd8b35bc96", - slotId: "hideout", - upd: { StackObjectsCount: 1 }, - }, { - _id: "8ac63abcbaf95d09a4d50c02", - _tpl: "5ea17ca01412a1425304d1c0", - parentId: "d2b3b859f667d4fd8b35bc96", - slotId: "hideout", - upd: { StackObjectsCount: 1 }, - }, { - _id: "33c99e86f72af509da01dc9a", - _tpl: "657f9a55c6679fefb3051e19", - parentId: "8ac63abcbaf95d09a4d50c02", - slotId: "Helmet_top", - upd: { Repairable: { Durability: 24, MaxDurability: 24 } }, - }, { - _id: "426902ae3d7efa5f8c78acf7", - _tpl: "657f9a94ada5fadd1f07a589", - parentId: "8ac63abcbaf95d09a4d50c02", - slotId: "Helmet_back", - upd: { Repairable: { Durability: 24, MaxDurability: 24 } }, - }, { - _id: "5d2be23efb34d0d1da9d3701", - _tpl: "603648ff5a45383c122086ac", - parentId: "d2b3b859f667d4fd8b35bc96", - slotId: "hideout", - upd: { StackObjectsCount: 1 }, - }, { - _id: "9f601faab37dcc58190898ac", - _tpl: "618bb76513f5097c8d5aa2d5", - parentId: "d2b3b859f667d4fd8b35bc96", - slotId: "hideout", - upd: { StackObjectsCount: 1 }, - }, { - _id: "f74d377063e65d350e0099be", - _tpl: "5c0e5bab86f77461f55ed1f3", - parentId: "d2b3b859f667d4fd8b35bc96", - slotId: "hideout", - upd: { StackObjectsCount: 1 }, - }, { - _id: "0ab2a81fc507ac846f43b15f", - _tpl: "6571b27a6d84a2b8b6007f92", - parentId: "f74d377063e65d350e0099be", - slotId: "Soft_armor_front", - upd: { Repairable: { Durability: 50.88512, MaxDurability: 52 } }, - }, { - _id: "2ca1b6606d918483ed6b70a5", - _tpl: "6571baa74cb80d995d0a1490", - parentId: "f74d377063e65d350e0099be", - slotId: "Soft_armor_back", - upd: { Repairable: { Durability: 49, MaxDurability: 52 } }, - }, { - _id: "5658a9d10f9d44112a991561", - _tpl: "6571baac6d84a2b8b6007fa3", - parentId: "f74d377063e65d350e0099be", - slotId: "Soft_armor_left", - upd: { Repairable: { Durability: 8, MaxDurability: 8 } }, - }, { - _id: "8d0ba4d12fa601312b71d3d7", - _tpl: "6571bab0f41985531a038091", - parentId: "f74d377063e65d350e0099be", - slotId: "soft_armor_right", - upd: { Repairable: { Durability: 8, MaxDurability: 8 } }, - }, { - _id: "45d19bbff6d42c8f781abb38", - _tpl: "6571babb4076795e5e07383f", - parentId: "f74d377063e65d350e0099be", - slotId: "Collar", - upd: { Repairable: { Durability: 14, MaxDurability: 14 } }, - }, { - _id: "cf2ba30bab4d8e80393a8ffe", - _tpl: "6571bac34076795e5e073843", - parentId: "f74d377063e65d350e0099be", - slotId: "Groin", - upd: { Repairable: { Durability: 10, MaxDurability: 10 } }, - }, { - _id: "a3f866e60ccd9c29e77eb5ef", - _tpl: "6571babf4cb80d995d0a1494", - parentId: "f74d377063e65d350e0099be", - slotId: "Groin_back", - upd: { Repairable: { Durability: 12, MaxDurability: 12 } }, - }, { - _id: "a3287a706e1b77b44db82fa1", - _tpl: "5aa2ba71e5b5b000137b758f", - parentId: "d2b3b859f667d4fd8b35bc96", - slotId: "hideout", - upd: { StackObjectsCount: 1 }, - }, { - _id: "c6ad1be7e8401755de69d6a0", - _tpl: "5d6d2ef3a4b93618084f58bd", - parentId: "d2b3b859f667d4fd8b35bc96", - slotId: "hideout", - upd: { StackObjectsCount: 1 }, - }, { - _id: "7c42d3dce0ddbc4806bce48b", - _tpl: "5894a51286f77426d13baf02", - parentId: "35111c9b72a87b6b7d95ad35", - slotId: "mod_pistol_grip", - upd: {}, - }, { - _id: "10b97872c5f4e0e1949a0369", - _tpl: "5c5db6742e2216000f1b2852", - upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, - parentId: "35111c9b72a87b6b7d95ad35", - slotId: "mod_magazine", - }, { - _id: "a6cd9986dde4cabddcd2dce2", - _tpl: "5894a5b586f77426d2590767", - parentId: "35111c9b72a87b6b7d95ad35", - slotId: "mod_reciever", - upd: {}, - }, { - _id: "b65635b515712f990fdcc201", - _tpl: "58ac1bf086f77420ed183f9f", - upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, - parentId: "35111c9b72a87b6b7d95ad35", - slotId: "mod_stock", - }, { - _id: "0e11045873efe3625695c1ae", - _tpl: "5c5db6b32e221600102611a0", - upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, - parentId: "35111c9b72a87b6b7d95ad35", - slotId: "mod_charge", - }, { - _id: "94c4161abe8bf654fb986063", - _tpl: "57adff4f24597737f373b6e6", - upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, - parentId: "a6cd9986dde4cabddcd2dce2", - slotId: "mod_scope", - }, { - _id: "9b284ccfd0d535acec1ff58b", - _tpl: "5c5db5c62e22160012542255", - parentId: "a6cd9986dde4cabddcd2dce2", - slotId: "mod_barrel", - upd: {}, - }, { - _id: "d730caa83a11fd01250a7261", - _tpl: "5c5db63a2e2216000f1b284a", - parentId: "a6cd9986dde4cabddcd2dce2", - slotId: "mod_handguard", - upd: {}, - }, { - _id: "24291c7bcf91e362adb6d68b", - _tpl: "5fb6564947ce63734e3fa1da", - parentId: "a6cd9986dde4cabddcd2dce2", - slotId: "mod_sight_rear", - upd: { StackObjectsCount: 1 }, - }, { - _id: "0d98fd0769cce8e473bbe540", - _tpl: "58d2664f86f7747fec5834f6", - upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, - parentId: "94c4161abe8bf654fb986063", - slotId: "mod_scope", - }, { - _id: "11b174510f039e8217fbd202", - _tpl: "58d268fc86f774111273f8c2", - upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, - parentId: "0d98fd0769cce8e473bbe540", - slotId: "mod_scope", - }, { - _id: "c435230e530574b1d7c32300", - _tpl: "5c7e8fab2e22165df16b889b", - parentId: "9b284ccfd0d535acec1ff58b", - slotId: "mod_muzzle", - upd: {}, - }, { - _id: "15666fe6fd2d95206612e418", - _tpl: "6269220d70b6c02e665f2635", - parentId: "d730caa83a11fd01250a7261", - slotId: "mod_mount_000", - upd: { StackObjectsCount: 1 }, - }, { - _id: "a54de8b9014eee71fdf1d01d", - _tpl: "6269220d70b6c02e665f2635", - parentId: "d730caa83a11fd01250a7261", - slotId: "mod_mount_001", - upd: { StackObjectsCount: 1 }, - }, { - _id: "c34555bc95a9a7a23150a36f", - _tpl: "6269220d70b6c02e665f2635", - parentId: "d730caa83a11fd01250a7261", - slotId: "mod_mount_002", - upd: { StackObjectsCount: 1 }, - }, { - _id: "91cae4ae30d1366b87158238", - _tpl: "6269220d70b6c02e665f2635", - parentId: "d730caa83a11fd01250a7261", - slotId: "mod_mount_003", - upd: { StackObjectsCount: 1 }, - }, { - _id: "48f23df4509164cf397b9ab5", - _tpl: "6269220d70b6c02e665f2635", - parentId: "d730caa83a11fd01250a7261", - slotId: "mod_mount_004", - upd: { StackObjectsCount: 1 }, - }, { - _id: "a55f05f689978ac65c7da654", - _tpl: "5b7be4895acfc400170e2dd5", - parentId: "d730caa83a11fd01250a7261", - slotId: "mod_foregrip", - upd: {}, - }, { - _id: "8ae4ea81a2d6074162d87a9c", - _tpl: "5b7be47f5acfc400170e2dd2", - parentId: "d730caa83a11fd01250a7261", - slotId: "mod_mount_005", - upd: {}, - }, { - _id: "312cc0f6687963305457235e", - _tpl: "5b7be47f5acfc400170e2dd2", - parentId: "d730caa83a11fd01250a7261", - slotId: "mod_mount_006", - upd: {}, - }, { - _id: "e1e5aaf474b7282a52ac9a14", - _tpl: "5fb6567747ce63734e3fa1dc", - parentId: "d730caa83a11fd01250a7261", - slotId: "mod_sight_front", - upd: { StackObjectsCount: 1 }, - }, { - _id: "bb9a34648e08f005db5d7484", - _tpl: "5cc9c20cd7f00c001336c65d", - upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, - parentId: "15666fe6fd2d95206612e418", - slotId: "mod_tactical", - }, { - _id: "dd9ac99d3ea4c9656221bcc9", - _tpl: "5cc9c20cd7f00c001336c65d", - upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, - parentId: "a54de8b9014eee71fdf1d01d", - slotId: "mod_tactical", - }, { - _id: "b22748de8da5f3c1362dd8e0", - _tpl: "5cc9c20cd7f00c001336c65d", - upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, - parentId: "c34555bc95a9a7a23150a36f", - slotId: "mod_tactical", - }, { - _id: "e3cc1be8954c4889f94b435a", - _tpl: "5cc9c20cd7f00c001336c65d", - upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, - parentId: "91cae4ae30d1366b87158238", - slotId: "mod_tactical", - }, { - _id: "e73f05be5a306168e847da82", - _tpl: "5cc9c20cd7f00c001336c65d", - parentId: "48f23df4509164cf397b9ab5", - slotId: "mod_tactical", - upd: { StackObjectsCount: 1 }, - }, { - _id: "847cf35ec92d8af8e4814ea8", - _tpl: "5c1cd46f2e22164bef5cfedb", - upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, - parentId: "a55f05f689978ac65c7da654", - slotId: "mod_foregrip", - }, { - _id: "bb4b7a4475fea0f0135305f6", - _tpl: "5cc9c20cd7f00c001336c65d", - parentId: "8ae4ea81a2d6074162d87a9c", - slotId: "mod_tactical", - upd: { StackObjectsCount: 1 }, - }, { - _id: "d0ac8e688a0bb17668589909", - _tpl: "5cc9c20cd7f00c001336c65d", - parentId: "312cc0f6687963305457235e", - slotId: "mod_tactical", - upd: { StackObjectsCount: 1 }, - }, { - _id: "5dbcf8cbbb3f8ef669836320", - _tpl: "5c793fc42e221600114ca25d", - upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, - parentId: "b65635b515712f990fdcc201", - slotId: "mod_stock", - }, { - _id: "f996645c809968f8033593a6", - _tpl: "5fc2369685fd526b824a5713", - upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, - parentId: "5dbcf8cbbb3f8ef669836320", - slotId: "mod_stock_000", - }, { - _id: "7d959c20811fdc440387f0a4", - _tpl: "55d447bb4bdc2d892f8b456f", - parentId: "d45436a159654f43ca3aa52f", - slotId: "mod_barrel", - upd: {}, - }, { - _id: "16969c588bd20e223d93e65a", - _tpl: "611a31ce5b7ffe001b4649d1", - parentId: "d45436a159654f43ca3aa52f", - slotId: "mod_stock", - upd: {}, - }, { - _id: "d3a31aa632d852bfe57d7aca", - _tpl: "5a6b5f868dc32e000a311389", - parentId: "2c60ad9b6051f059ab796aa6", - slotId: "mod_barrel", - upd: {}, - }, { - _id: "fdba343644672594e7c73f47", - _tpl: "5a7b4960e899ef197b331a2d", - parentId: "2c60ad9b6051f059ab796aa6", - slotId: "mod_pistol_grip", - upd: {}, - }, { - _id: "5f47943e00d184b3c8f9c2b5", - _tpl: "5a6f5e048dc32e00094b97da", - parentId: "2c60ad9b6051f059ab796aa6", - slotId: "mod_reciever", - upd: {}, - }, { - _id: "f616853cb3b860d670252e66", - _tpl: "5a718b548dc32e000d46d262", - parentId: "2c60ad9b6051f059ab796aa6", - slotId: "mod_magazine", - upd: {}, - }, { - _id: "5153ee12f6d4abc4856dd4ae", - _tpl: "5a7ad74e51dfba0015068f45", - parentId: "2c60ad9b6051f059ab796aa6", - slotId: "mod_tactical", - upd: {}, - }, { - _id: "aa5dc438d849a311e335667b", - _tpl: "5a7d9122159bd4001438dbf4", - parentId: "5f47943e00d184b3c8f9c2b5", - slotId: "mod_sight_rear", - upd: {}, - }, { - _id: "79a1dfa8bff1b7ca118d6b0f", - _tpl: "5a7d90eb159bd400165484f1", - parentId: "5f47943e00d184b3c8f9c2b5", - slotId: "mod_sight_front", - upd: {}, - }, { - _id: "e784a6d774f9a885bf5ed847", - _tpl: "5a7b483fe899ef0016170d15", - parentId: "5153ee12f6d4abc4856dd4ae", - slotId: "mod_tactical", - upd: {}, - }, { - _id: "fd79789b0e394e2cc1299ab1", - _tpl: "5c5db6742e2216000f1b2852", - parentId: "5d2be23efb34d0d1da9d3701", - slotId: "1", - upd: { StackObjectsCount: 1 }, - location: { x: 0, y: 0, r: "Horizontal", isSearched: true }, - }, { - _id: "a19f5e338bfd32f1c1f3fb73", - _tpl: "5c5db6742e2216000f1b2852", - upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, - parentId: "5d2be23efb34d0d1da9d3701", - slotId: "2", - location: { x: 0, y: 0, r: "Horizontal", isSearched: true }, - }, { - _id: "9e709808929c226f7bdbf57a", - _tpl: "5c5db6742e2216000f1b2852", - upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, - parentId: "5d2be23efb34d0d1da9d3701", - slotId: "3", - location: { x: 0, y: 0, r: "Horizontal", isSearched: true }, - }, { - _id: "9fe70bf25a2db7f8c1b23502", - _tpl: "5c5db6742e2216000f1b2852", - upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, - parentId: "5d2be23efb34d0d1da9d3701", - slotId: "4", - location: { x: 0, y: 0, r: "Horizontal", isSearched: true }, - }, { - _id: "4519dc962deebb2dbfc9e70c", - _tpl: "5c5db6742e2216000f1b2852", - upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, - parentId: "5d2be23efb34d0d1da9d3701", - slotId: "5", - location: { x: 0, y: 0, r: "Horizontal", isSearched: true }, - }, { - _id: "a94275912f1cbcd483563916", - _tpl: "5c5db6742e2216000f1b2852", - parentId: "5d2be23efb34d0d1da9d3701", - slotId: "6", - upd: { StackObjectsCount: 1 }, - location: { x: 0, y: 0, r: "Horizontal", isSearched: true }, - }, { - _id: "7f2ae8c0685bf3a2195185dd", - _tpl: "5c5db6742e2216000f1b2852", - upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, - parentId: "5d2be23efb34d0d1da9d3701", - slotId: "7", - location: { x: 0, y: 0, r: "Horizontal", isSearched: true }, - }, { - _id: "53a9f3dc5c08cbd02ff31b12", - _tpl: "5c5db6742e2216000f1b2852", - upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, - parentId: "5d2be23efb34d0d1da9d3701", - slotId: "8", - location: { x: 0, y: 0, r: "Horizontal", isSearched: true }, - }, { - _id: "e0ab45585b1a874dbaa68fb3", - _tpl: "5c5db6742e2216000f1b2852", - upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, - parentId: "5d2be23efb34d0d1da9d3701", - slotId: "9", - location: { x: 0, y: 0, r: "Horizontal", isSearched: true }, - }, { - _id: "3f66f7abde039a848f8b4cf0", - _tpl: "5c5db6742e2216000f1b2852", - upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, - parentId: "5d2be23efb34d0d1da9d3701", - slotId: "10", - location: { x: 0, y: 0, r: "Horizontal", isSearched: true }, - }, { - _id: "04a202a45f8a39b61a58a05a", - _tpl: "544a5caa4bdc2d1a388b4568", - parentId: "9f601faab37dcc58190898ac", - slotId: "main", - upd: { StackObjectsCount: 1 }, - location: { x: 0, y: 0, r: "Horizontal", isSearched: true }, - }, { - _id: "d5f6e03c07ede944e89fb407", - _tpl: "6570e83223c1f638ef0b0ede", - parentId: "04a202a45f8a39b61a58a05a", - slotId: "Soft_armor_front", - upd: { Repairable: { Durability: 42, MaxDurability: 42 } }, - }, { - _id: "5433cbf0f07a68651e888c74", - _tpl: "6570e87c23c1f638ef0b0ee2", - parentId: "04a202a45f8a39b61a58a05a", - slotId: "Soft_armor_back", - upd: { Repairable: { Durability: 42, MaxDurability: 42 } }, - }, { - _id: "da91bed43f688a80b627ad4d", - _tpl: "6570e90b3a5689d85f08db97", - parentId: "04a202a45f8a39b61a58a05a", - slotId: "Groin", - upd: { Repairable: { Durability: 28, MaxDurability: 28 } }, - }, { - _id: "ad7f524f3de9ad544df8c0b8", - _tpl: "5c5db6742e2216000f1b2852", - upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, - parentId: "9f601faab37dcc58190898ac", - slotId: "main", - location: { x: 3, y: 0, r: "Horizontal", isSearched: true }, - }, { - _id: "0844cf6b7a89c13454b6e3db", - _tpl: "5c5db6742e2216000f1b2852", - upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, - parentId: "9f601faab37dcc58190898ac", - slotId: "main", - location: { x: 4, y: 0, r: "Horizontal", isSearched: true }, - }, { - _id: "c3f58f44366d0a06d29d66ba", - _tpl: "5a38e6bac4a2826c6e06d79b", - parentId: "9f601faab37dcc58190898ac", - slotId: "main", - upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, - location: { x: 0, y: 4, r: "Horizontal", isSearched: true }, - }, { - _id: "d46e16faba780c68e0600532", - _tpl: "656fa0fb498d1b7e3e071d9c", - parentId: "9f601faab37dcc58190898ac", - slotId: "main", - upd: { StackObjectsCount: 1, Repairable: { Durability: 45, MaxDurability: 45 } }, - location: { x: 3, y: 2, r: "Horizontal", isSearched: true }, - }, { - _id: "26598f88d49198c4a0a9391c", - _tpl: "571a12c42459771f627b58a0", - parentId: "9f601faab37dcc58190898ac", - slotId: "main", - upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, - location: { x: 3, y: 4, r: "Horizontal", isSearched: true }, - }, { - _id: "5ee8e16837809adc34caae00", - _tpl: "656f9fa0498d1b7e3e071d98", - parentId: "04a202a45f8a39b61a58a05a", - slotId: "Front_plate", - upd: { Repairable: { Durability: 50, MaxDurability: 50 } }, - }, { - _id: "de042f9ebf0fd9ad451033d4", - _tpl: "656f9fa0498d1b7e3e071d98", - parentId: "04a202a45f8a39b61a58a05a", - slotId: "Back_plate", - upd: { Repairable: { Durability: 50, MaxDurability: 50 } }, - }, { - _id: "03de471c2a3faa359aca7486", - _tpl: "5c5db6742e2216000f1b2852", - upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, - parentId: "04a202a45f8a39b61a58a05a", - slotId: "1", - location: { x: 0, y: 0, r: "Horizontal", isSearched: true }, - }, { - _id: "091c85804613176da9478edd", - _tpl: "5c5db6742e2216000f1b2852", - upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, - parentId: "04a202a45f8a39b61a58a05a", - slotId: "2", - location: { x: 0, y: 0, r: "Horizontal", isSearched: true }, - }, { - _id: "5482888e242a98ff154c0ee8", - _tpl: "5c5db6742e2216000f1b2852", - upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, - parentId: "04a202a45f8a39b61a58a05a", - slotId: "3", - location: { x: 0, y: 0, r: "Horizontal", isSearched: true }, - }, { - _id: "3c8e206a2c2e9b0fee45b56b", - _tpl: "5c5db6742e2216000f1b2852", - upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, - parentId: "04a202a45f8a39b61a58a05a", - slotId: "4", - location: { x: 0, y: 0, r: "Horizontal", isSearched: true }, - }, { - _id: "b2405216e5730f3511884a10", - _tpl: "5ea17ca01412a1425304d1c0", - parentId: "04a202a45f8a39b61a58a05a", - slotId: "5", - upd: { StackObjectsCount: 1 }, - location: { x: 0, y: 0, r: "Horizontal", isSearched: true }, - }, { - _id: "7a0675280dbbad69ce592d74", - _tpl: "657f9a55c6679fefb3051e19", - parentId: "b2405216e5730f3511884a10", - slotId: "Helmet_top", - upd: { Repairable: { Durability: 24, MaxDurability: 24 } }, - }, { - _id: "c0c182942f54d3c183f0e179", - _tpl: "657f9a94ada5fadd1f07a589", - parentId: "b2405216e5730f3511884a10", - slotId: "Helmet_back", - upd: { Repairable: { Durability: 24, MaxDurability: 24 } }, - }, { - _id: "8ec4534a4fe96f89ea88c107", - _tpl: "5c165d832e2216398b5a7e36", - parentId: "04a202a45f8a39b61a58a05a", - slotId: "6", - upd: { StackObjectsCount: 1 }, - location: { x: 0, y: 0, r: "Horizontal", isSearched: true }, - }, { - _id: "0d91ed3d44881d33b1fd94ec", - _tpl: "5c5db6742e2216000f1b2852", - upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, - parentId: "04a202a45f8a39b61a58a05a", - slotId: "11", - location: { x: 0, y: 0, r: "Horizontal", isSearched: true }, - }, { - _id: "f7066fdfeefb29eca1d2dbeb", - _tpl: "5ea18c84ecf1982c7712d9a2", - upd: { StackObjectsCount: 1, Repairable: { Durability: 22, MaxDurability: 25 } }, - parentId: "b2405216e5730f3511884a10", - slotId: "mod_nvg", - }, { - _id: "ee0ec86e9608abe773175e3a", - _tpl: "5c0558060db834001b735271", - parentId: "f7066fdfeefb29eca1d2dbeb", - slotId: "mod_nvg", - upd: { StackObjectsCount: 1 }, - }, { - _id: "0515d1e589fd626b504e59cd", - _tpl: "5a38ee51c4a282000c5a955c", - parentId: "c3f58f44366d0a06d29d66ba", - slotId: "mod_magazine", - upd: {}, - }, { - _id: "cb30ae6f997a2e6d119f2186", - _tpl: "5a38ef1fc4a282000b1521f6", - parentId: "c3f58f44366d0a06d29d66ba", - slotId: "mod_stock", - upd: { Foldable: { Folded: true } }, - }, { - _id: "be57a04835a8c1ae85811949", - _tpl: "5a38eecdc4a282329a73b512", - parentId: "cb30ae6f997a2e6d119f2186", - slotId: "mod_pistol_grip", - upd: {}, - }, { - _id: "fd6ef6e377e6280ca9386dbc", - _tpl: "571a26d524597720680fbe8a", - parentId: "26598f88d49198c4a0a9391c", - slotId: "mod_barrel", - upd: {}, - }, { - _id: "5c40aff0d1c5d4f206123b83", - _tpl: "571a282c2459771fb2755a69", - parentId: "26598f88d49198c4a0a9391c", - slotId: "mod_pistol_grip", - upd: {}, - }, { - _id: "34b2c7cf0f6b8f484411cebf", - _tpl: "571a29dc2459771fb2755a6a", - parentId: "26598f88d49198c4a0a9391c", - slotId: "mod_magazine", - upd: {}, - }, { - _id: "9932dd0e1339053e27d54a41", - _tpl: "654a4dea7c17dec2f50cc86a", - parentId: "f74d377063e65d350e0099be", - slotId: "Front_plate", - upd: { Repairable: { Durability: 50, MaxDurability: 50 } }, - }, { - _id: "0f69c261881206320d8f583d", - _tpl: "657b22485f444d6dff0c6c2f", - parentId: "f74d377063e65d350e0099be", - slotId: "Back_plate", - upd: { StackObjectsCount: 1, Repairable: { Durability: 4.681114, MaxDurability: 40 } }, - }], -}, { - scheduledTime: 1712896726, - traderId: "54cb57776803fa99248b456e", - maxStorageTime: 518400, - systemData: { date: "11.04.2024", time: "19:19", location: "factory4_day" }, - messageType: 8, - messageTemplateId: "58fe0e3486f77471f772c3f2 3", - items: [{ - _id: "5cfe91bfe022641c19bc8c60", - _tpl: "5aafa857e5b5b00018480968", - upd: { - StackObjectsCount: 1, - sptPresetId: "5ac4ad3686f774181345c3da", - Repairable: { Durability: 98.33, MaxDurability: 98.33 }, - }, - parentId: "d2b3b859f667d4fd8b35bc96", - slotId: "hideout", - }, { - _id: "a5063619e7f4db123ca07fcc", - _tpl: "60db29ce99594040e04c4a27", - parentId: "d2b3b859f667d4fd8b35bc96", - slotId: "hideout", - upd: { - FireMode: { FireMode: "single" }, - StackObjectsCount: 1, - Repairable: { Durability: 100, MaxDurability: 100 }, - }, - }, { - _id: "3702c30b6333e28d6a15d62c", - _tpl: "56e0598dd2720bb5668b45a6", - parentId: "d2b3b859f667d4fd8b35bc96", - slotId: "hideout", - upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, - }, { - _id: "387c9f2b44d2da266f856b31", - _tpl: "6571bde39837cc51b800c212", - parentId: "d2b3b859f667d4fd8b35bc96", - slotId: "hideout", - upd: { StackObjectsCount: 1 }, - }, { - _id: "275f046ea1a7b40046cd54fa", - _tpl: "5b40e4035acfc47a87740943", - parentId: "d2b3b859f667d4fd8b35bc96", - slotId: "hideout", - upd: { StackObjectsCount: 1 }, - }, { - _id: "f30858ff9924b1fe211dd1f7", - _tpl: "657f95bff92cd718b701550c", - parentId: "275f046ea1a7b40046cd54fa", - slotId: "Helmet_top", - upd: { Repairable: { Durability: 10.3212032, MaxDurability: 18 } }, - }, { - _id: "eec1072ac0cc44984e1ed43b", - _tpl: "657f9605f4c82973640b2358", - parentId: "275f046ea1a7b40046cd54fa", - slotId: "Helmet_back", - upd: { Repairable: { Durability: 13.3160009, MaxDurability: 18 } }, - }, { - _id: "b82495b01ad0bfe5dd7e864d", - _tpl: "5c0e746986f7741453628fe5", - parentId: "d2b3b859f667d4fd8b35bc96", - slotId: "hideout", - upd: { StackObjectsCount: 1 }, - }, { - _id: "31531773990cd1aefa751db7", - _tpl: "6570df294cc0d2ab1e05ed74", - parentId: "b82495b01ad0bfe5dd7e864d", - slotId: "Soft_armor_front", - upd: { Repairable: { Durability: 31.0571022, MaxDurability: 35 } }, - }, { - _id: "eb8c6c7c671d2a2490454e7c", - _tpl: "6570df9c615f54368b04fca9", - parentId: "b82495b01ad0bfe5dd7e864d", - slotId: "Soft_armor_back", - upd: { Repairable: { Durability: 30.8, MaxDurability: 35 } }, - }, { - _id: "f9cc99048aa37c5a4a837ef9", - _tpl: "5ca20d5986f774331e7c9602", - parentId: "d2b3b859f667d4fd8b35bc96", - slotId: "hideout", - upd: { StackObjectsCount: 1 }, - }, { - _id: "bd8a4a3783d80b81cc8655ee", - _tpl: "5aa2ba71e5b5b000137b758f", - parentId: "d2b3b859f667d4fd8b35bc96", - slotId: "hideout", - upd: { StackObjectsCount: 1 }, - }, { - _id: "025748ec34dcd1bfb2529537", - _tpl: "5c0d32fcd174af02a1659c75", - parentId: "d2b3b859f667d4fd8b35bc96", - slotId: "hideout", - upd: { StackObjectsCount: 1 }, - }, { - _id: "9c552e79f1ae38350afb3723", - _tpl: "5addccf45acfc400185c2989", - upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, - parentId: "5cfe91bfe022641c19bc8c60", - slotId: "mod_magazine", - }, { - _id: "14cb5b7c9789876325670163", - _tpl: "5aaf8e43e5b5b00015693246", - parentId: "5cfe91bfe022641c19bc8c60", - slotId: "mod_stock", - upd: {}, - }, { - _id: "0e4c9e11000589751523a62c", - _tpl: "5addbac75acfc400194dbc56", - parentId: "5cfe91bfe022641c19bc8c60", - slotId: "mod_barrel", - upd: { StackObjectsCount: 1 }, - }, { - _id: "a63cf65e9646a04944d18106", - _tpl: "5abcbb20d8ce87001773e258", - upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, - parentId: "5cfe91bfe022641c19bc8c60", - slotId: "mod_sight_rear", - }, { - _id: "f67388e02546cd97c976d479", - _tpl: "5addbfe15acfc4001a5fc58b", - parentId: "5cfe91bfe022641c19bc8c60", - slotId: "mod_mount", - upd: { StackObjectsCount: 1 }, - }, { - _id: "bed3b1a2f866e18743db2a63", - _tpl: "5addbfbb5acfc400194dbcf7", - upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, - parentId: "14cb5b7c9789876325670163", - slotId: "mod_mount", - }, { - _id: "821a4953b87f562b3f435fd7", - _tpl: "5649a2464bdc2d91118b45a8", - upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, - parentId: "bed3b1a2f866e18743db2a63", - slotId: "mod_scope", - }, { - _id: "24813deb9b9a6ec3ca8376ef", - _tpl: "5d10b49bd7ad1a1a560708b0", - upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, - parentId: "bed3b1a2f866e18743db2a63", - slotId: "mod_tactical", - }, { - _id: "4194116ceb7e9e623cba4e89", - _tpl: "609bab8b455afd752b2e6138", - upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, - parentId: "821a4953b87f562b3f435fd7", - slotId: "mod_scope", - }, { - _id: "3bd8b76ba1ff8f1cf954af91", - _tpl: "59bffc1f86f77435b128b872", - parentId: "0e4c9e11000589751523a62c", - slotId: "mod_muzzle", - upd: { StackObjectsCount: 1 }, - }, { - _id: "3d953b4a4283363d0494d614", - _tpl: "59bffbb386f77435b379b9c2", - upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, - parentId: "3bd8b76ba1ff8f1cf954af91", - slotId: "mod_muzzle", - }, { - _id: "4b2c9fb752a7c3458e07a35d", - _tpl: "626bb8532c923541184624b4", - upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, - parentId: "f67388e02546cd97c976d479", - slotId: "mod_scope", - }, { - _id: "ce39864f056a3ad649d77243", - _tpl: "60dc519adf4c47305f6d410d", - parentId: "a5063619e7f4db123ca07fcc", - slotId: "mod_magazine", - upd: {}, - }, { - _id: "4ffc8f4e80708f6b9336c224", - _tpl: "612368f58b401f4f51239b33", - parentId: "a5063619e7f4db123ca07fcc", - slotId: "mod_barrel", - upd: {}, - }, { - _id: "b401a4ce551dfcb0602e4073", - _tpl: "612781056f3d944a17348d60", - parentId: "a5063619e7f4db123ca07fcc", - slotId: "mod_stock", - upd: {}, - }, { - _id: "b206761507a97037d05f0268", - _tpl: "6123649463849f3d843da7c4", - parentId: "a5063619e7f4db123ca07fcc", - slotId: "mod_handguard", - upd: {}, - }, { - _id: "25af8615f5c902fd5920965f", - _tpl: "619d36da53b4d42ee724fae4", - parentId: "4ffc8f4e80708f6b9336c224", - slotId: "mod_muzzle", - upd: {}, - }, { - _id: "38c5e9751e1d69d4d0804a49", - _tpl: "5448c12b4bdc2d02308b456f", - parentId: "3702c30b6333e28d6a15d62c", - slotId: "mod_magazine", - upd: {}, - }, { - _id: "54da5dc9656bb9477eb16c88", - _tpl: "56e05b06d2720bb2668b4586", - parentId: "3702c30b6333e28d6a15d62c", - slotId: "mod_muzzle", - upd: {}, - }, { - _id: "ad690f7145984b942288457f", - _tpl: "56e05a6ed2720bd0748b4567", - parentId: "3702c30b6333e28d6a15d62c", - slotId: "mod_pistolgrip", - upd: {}, - }, { - _id: "c4ffff33f0a5f48c9500699a", - _tpl: "656fa0fb498d1b7e3e071d9c", - parentId: "b82495b01ad0bfe5dd7e864d", - slotId: "Front_plate", - upd: { Repairable: { Durability: 31.1713047, MaxDurability: 45 } }, - }, { - _id: "8453961a28b572039197e140", - _tpl: "656fa0fb498d1b7e3e071d9c", - parentId: "b82495b01ad0bfe5dd7e864d", - slotId: "Back_plate", - upd: { Repairable: { Durability: 32.4, MaxDurability: 45 } }, - }, { - _id: "43e7482d78b276a5db4f4fef", - _tpl: "5addccf45acfc400185c2989", - upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, - parentId: "b82495b01ad0bfe5dd7e864d", - slotId: "1", - location: { x: 0, y: 1, r: "Horizontal", isSearched: true }, - }, { - _id: "7372a194a2de632f5941b701", - _tpl: "5addccf45acfc400185c2989", - upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, - parentId: "b82495b01ad0bfe5dd7e864d", - slotId: "2", - location: { x: 0, y: 1, r: "Horizontal", isSearched: true }, - }, { - _id: "624555830937dfa5190a11bf", - _tpl: "5addccf45acfc400185c2989", - upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, - parentId: "b82495b01ad0bfe5dd7e864d", - slotId: "3", - location: { x: 0, y: 1, r: "Horizontal", isSearched: true }, - }, { - _id: "05aedd00b683ce0d00ac5c74", - _tpl: "5addccf45acfc400185c2989", - upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, - parentId: "b82495b01ad0bfe5dd7e864d", - slotId: "4", - location: { x: 0, y: 0, r: "Horizontal", isSearched: true }, - }, { - _id: "8c3eccca9f25989d68d90e59", - _tpl: "5addccf45acfc400185c2989", - upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, - parentId: "b82495b01ad0bfe5dd7e864d", - slotId: "5", - location: { x: 0, y: 0, r: "Horizontal", isSearched: true }, - }, { - _id: "b8b2e1651d7dbb891053b514", - _tpl: "5aa7e454e5b5b0214e506fa2", - parentId: "b82495b01ad0bfe5dd7e864d", - slotId: "8", - upd: { StackObjectsCount: 1 }, - location: { x: 0, y: 0, r: "Horizontal", isSearched: true }, - }, { - _id: "f9b891b8a5cf948b858a7b1b", - _tpl: "657f925dada5fadd1f07a57a", - parentId: "b8b2e1651d7dbb891053b514", - slotId: "Helmet_top", - upd: { Repairable: { Durability: 21, MaxDurability: 21 } }, - }, { - _id: "8b66bc46287219eb0e7c190d", - _tpl: "657f92acada5fadd1f07a57e", - parentId: "b8b2e1651d7dbb891053b514", - slotId: "Helmet_back", - upd: { Repairable: { Durability: 21, MaxDurability: 21 } }, - }, { - _id: "24cd31ecc0fdac526c8bd21d", - _tpl: "657f92e7f4c82973640b2354", - parentId: "b8b2e1651d7dbb891053b514", - slotId: "Helmet_ears", - upd: { Repairable: { Durability: 21, MaxDurability: 21 } }, - }, { - _id: "c6125558f051cd10cfaf77e0", - _tpl: "5d6d3716a4b9361bc8618872", - parentId: "b82495b01ad0bfe5dd7e864d", - slotId: "9", - upd: { StackObjectsCount: 1 }, - location: { x: 0, y: 0, r: "Horizontal", isSearched: true }, - }, { - _id: "ee92a87a762b35b45f9d7fa7", - _tpl: "657fa009d4caf976440afe3a", - parentId: "c6125558f051cd10cfaf77e0", - slotId: "Helmet_top", - upd: { Repairable: { Durability: 33, MaxDurability: 33 } }, - }, { - _id: "be9a15c5ab850ae0437315bb", - _tpl: "657fa04ac6679fefb3051e24", - parentId: "c6125558f051cd10cfaf77e0", - slotId: "Helmet_back", - upd: { Repairable: { Durability: 33, MaxDurability: 33 } }, - }, { - _id: "65c9ceccbebe5f2813a8c70e", - _tpl: "657fa07387e11c61f70bface", - parentId: "c6125558f051cd10cfaf77e0", - slotId: "Helmet_ears", - upd: { Repairable: { Durability: 33, MaxDurability: 33 } }, - }, { - _id: "769eab07773ecfaa6e12e4c4", - _tpl: "5aa7e3abe5b5b000171d064d", - upd: { StackObjectsCount: 1, Repairable: { Durability: 50, MaxDurability: 50 }, Togglable: { On: true } }, - parentId: "b8b2e1651d7dbb891053b514", - slotId: "mod_equipment", - }, { - _id: "82aa530739c59be8dd5a0911", - _tpl: "5d6d3829a4b9361bc8618943", - upd: { StackObjectsCount: 1, Repairable: { Durability: 50, MaxDurability: 50 }, Togglable: { On: true } }, - parentId: "c6125558f051cd10cfaf77e0", - slotId: "mod_equipment_000", - }, { - _id: "996a6f0f8e90cb31f758c801", - _tpl: "5d6d3be5a4b9361bc73bc763", - upd: { StackObjectsCount: 1, Repairable: { Durability: 10, MaxDurability: 24 } }, - parentId: "c6125558f051cd10cfaf77e0", - slotId: "mod_equipment_001", - }, { - _id: "8c43cca672e16a931590945f", - _tpl: "5d6d3943a4b9360dbc46d0cc", - upd: { StackObjectsCount: 1, Repairable: { Durability: 1, MaxDurability: 1 } }, - parentId: "c6125558f051cd10cfaf77e0", - slotId: "mod_equipment_002", - }, { - _id: "5858b72da0ca732b2fb5ed95", - _tpl: "544a5caa4bdc2d1a388b4568", - parentId: "f9cc99048aa37c5a4a837ef9", - slotId: "main", - upd: { StackObjectsCount: 1 }, - location: { x: 0, y: 0, r: "Vertical", isSearched: true }, - }, { - _id: "43ef5a5e1c93ba3ab032811f", - _tpl: "6570e83223c1f638ef0b0ede", - parentId: "5858b72da0ca732b2fb5ed95", - slotId: "Soft_armor_front", - upd: { Repairable: { Durability: 42, MaxDurability: 42 } }, - }, { - _id: "e1f16c6d9e853f2735948665", - _tpl: "6570e87c23c1f638ef0b0ee2", - parentId: "5858b72da0ca732b2fb5ed95", - slotId: "Soft_armor_back", - upd: { Repairable: { Durability: 42, MaxDurability: 42 } }, - }, { - _id: "d9bdf684a8264ac1fb3208bf", - _tpl: "6570e90b3a5689d85f08db97", - parentId: "5858b72da0ca732b2fb5ed95", - slotId: "Groin", - upd: { Repairable: { Durability: 28, MaxDurability: 28 } }, - }, { - _id: "e4b484ba7209d770482732c8", - _tpl: "5addccf45acfc400185c2989", - upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, - parentId: "f9cc99048aa37c5a4a837ef9", - slotId: "main", - location: { x: 0, y: 3, r: "Horizontal", isSearched: true }, - }, { - _id: "ddc3945694d52dcdae9cba4d", - _tpl: "5addccf45acfc400185c2989", - upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, - parentId: "f9cc99048aa37c5a4a837ef9", - slotId: "main", - location: { x: 1, y: 3, r: "Horizontal", isSearched: true }, - }, { - _id: "59923cfba8be35031e5d95e6", - _tpl: "5addccf45acfc400185c2989", - upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, - parentId: "f9cc99048aa37c5a4a837ef9", - slotId: "main", - location: { x: 2, y: 3, r: "Horizontal", isSearched: true }, - }, { - _id: "95cf47373df5c4f07f458a93", - _tpl: "5addccf45acfc400185c2989", - upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, - parentId: "f9cc99048aa37c5a4a837ef9", - slotId: "main", - location: { x: 3, y: 3, r: "Horizontal", isSearched: true }, - }, { - _id: "98661f27ea826095d0cdd609", - _tpl: "656f9fa0498d1b7e3e071d98", - parentId: "5858b72da0ca732b2fb5ed95", - slotId: "Front_plate", - upd: { Repairable: { Durability: 50, MaxDurability: 50 } }, - }, { - _id: "525179b06d14baaddb2b04fb", - _tpl: "656f9fa0498d1b7e3e071d98", - parentId: "5858b72da0ca732b2fb5ed95", - slotId: "Back_plate", - upd: { Repairable: { Durability: 50, MaxDurability: 50 } }, - }, { - _id: "353638d16450339e40f5b5eb", - _tpl: "5addccf45acfc400185c2989", - upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, - parentId: "5858b72da0ca732b2fb5ed95", - slotId: "1", - location: { x: 0, y: 0, r: "Horizontal", isSearched: true }, - }, { - _id: "fa4a5c3e4e3c2f017e35eb1a", - _tpl: "5addccf45acfc400185c2989", - upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, - parentId: "5858b72da0ca732b2fb5ed95", - slotId: "2", - location: { x: 0, y: 0, r: "Horizontal", isSearched: true }, - }, { - _id: "7554a8ddb30e0306de7b7d80", - _tpl: "5addccf45acfc400185c2989", - upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, - parentId: "5858b72da0ca732b2fb5ed95", - slotId: "3", - location: { x: 0, y: 0, r: "Horizontal", isSearched: true }, - }, { - _id: "4c73b93f4d9f17a05a5782fa", - _tpl: "5addccf45acfc400185c2989", - upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, - parentId: "5858b72da0ca732b2fb5ed95", - slotId: "4", - location: { x: 0, y: 0, r: "Horizontal", isSearched: true }, - }, { - _id: "8ce190fcd2ffe5f1f9ad345a", - _tpl: "5aa7e4a4e5b5b000137b76f2", - parentId: "5858b72da0ca732b2fb5ed95", - slotId: "5", - upd: { StackObjectsCount: 1 }, - location: { x: 0, y: 0, r: "Horizontal", isSearched: true }, - }, { - _id: "6607b1b9d73f83e559304208", - _tpl: "657f925dada5fadd1f07a57a", - parentId: "8ce190fcd2ffe5f1f9ad345a", - slotId: "Helmet_top", - upd: { Repairable: { Durability: 21, MaxDurability: 21 } }, - }, { - _id: "41912d06dac91585499c05a2", - _tpl: "657f92acada5fadd1f07a57e", - parentId: "8ce190fcd2ffe5f1f9ad345a", - slotId: "Helmet_back", - upd: { Repairable: { Durability: 21, MaxDurability: 21 } }, - }, { - _id: "db24f69de28bddd7f09b9c3e", - _tpl: "657f92e7f4c82973640b2354", - parentId: "8ce190fcd2ffe5f1f9ad345a", - slotId: "Helmet_ears", - upd: { Repairable: { Durability: 21, MaxDurability: 21 } }, - }, { - _id: "6c578731bc0c3f91c8089116", - _tpl: "5addccf45acfc400185c2989", - upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, - parentId: "5858b72da0ca732b2fb5ed95", - slotId: "6", - location: { x: 0, y: 0, r: "Horizontal", isSearched: true }, - }, { - _id: "aa7b1ce4897aa7e64309ce86", - _tpl: "5addccf45acfc400185c2989", - upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, - parentId: "5858b72da0ca732b2fb5ed95", - slotId: "6", - location: { x: 1, y: 0, r: "Horizontal", isSearched: true }, - }, { - _id: "7e5e5dbe18de6aea779d904d", - _tpl: "5addccf45acfc400185c2989", - upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, - parentId: "5858b72da0ca732b2fb5ed95", - slotId: "11", - location: { x: 0, y: 0, r: "Horizontal", isSearched: true }, - }, { - _id: "b50b5052892729841e26934f", - _tpl: "5aa7e3abe5b5b000171d064d", - upd: { StackObjectsCount: 1, Repairable: { Durability: 47, MaxDurability: 47 }, Togglable: { On: true } }, - parentId: "8ce190fcd2ffe5f1f9ad345a", - slotId: "mod_equipment", - }], -}, { - scheduledTime: 1712960777.6, - traderId: "54cb50c76803fa8b248b4571", - maxStorageTime: 345600, - systemData: { date: "11.04.2024", time: "19:30", location: "factory4_day" }, - messageType: 8, - messageTemplateId: "58fe0e4586f774728248ca13 4", - items: [{ - _id: "b29c463afe52421ba72b1816", - _tpl: "5aa7e3abe5b5b000171d064d", - upd: { StackObjectsCount: 1, Repairable: { Durability: 50, MaxDurability: 50 } }, - parentId: "d2b3b859f667d4fd8b35bc96", - slotId: "hideout", - }, { - _id: "1813e676a1bceefd5424b4bb", - _tpl: "5ac7655e5acfc40016339a19", - parentId: "d2b3b859f667d4fd8b35bc96", - slotId: "hideout", - upd: {}, - }, { - _id: "a58746a7e98ac16ba9105fc9", - _tpl: "5cf50850d7f00c056e24104c", - parentId: "d2b3b859f667d4fd8b35bc96", - slotId: "hideout", - upd: {}, - }, { - _id: "70acf65d9944b19d17d92b19", - _tpl: "55d480c04bdc2d1d4e8b456a", - parentId: "d2b3b859f667d4fd8b35bc96", - slotId: "hideout", - upd: {}, - }, { - _id: "e3a54ae66a2970372eee1888", - _tpl: "602e63fb6335467b0c5ac94d", - parentId: "d2b3b859f667d4fd8b35bc96", - slotId: "hideout", - upd: {}, - }, { - _id: "a4b1cb12dc5ece274d348e2b", - _tpl: "6033749e88382f4fab3fd2c5", - parentId: "d2b3b859f667d4fd8b35bc96", - slotId: "hideout", - upd: {}, - }, { - _id: "e3c2162f4001a0d6ed2a199d", - _tpl: "602f85fd9b513876d4338d9c", - parentId: "d2b3b859f667d4fd8b35bc96", - slotId: "hideout", - upd: {}, - }, { - _id: "548a111c4e48fb058e7a5c09", - _tpl: "603372b4da11d6478d5a07ff", - parentId: "e3a54ae66a2970372eee1888", - slotId: "mod_barrel", - upd: {}, - }, { - _id: "d58db125fdd3f3b15a9798ca", - _tpl: "602e620f9b513876d4338d9a", - parentId: "d2b3b859f667d4fd8b35bc96", - slotId: "hideout", - upd: {}, - }, { - _id: "f85ba56791757174e3447c55", - _tpl: "630764fea987397c0816d219", - parentId: "d2b3b859f667d4fd8b35bc96", - slotId: "hideout", - upd: {}, - }, { - _id: "e3c409642a067f980ca168b7", - _tpl: "63075cc5962d0247b029dc2a", - parentId: "d2b3b859f667d4fd8b35bc96", - slotId: "hideout", - upd: {}, - }, { - _id: "5ff60d8b2b61c9f20ee8e91b", - _tpl: "63076701a987397c0816d21b", - parentId: "d2b3b859f667d4fd8b35bc96", - slotId: "hideout", - upd: {}, - }, { - _id: "b212acf3c8f09f48b4beaa0d", - _tpl: "5648a69d4bdc2ded0b8b457b", - parentId: "d2b3b859f667d4fd8b35bc96", - slotId: "hideout", - upd: { StackObjectsCount: 1 }, - }], -}, { - scheduledTime: 1712920104.8, - traderId: "54cb57776803fa99248b456e", - maxStorageTime: 518400, - systemData: { date: "11.04.2024", time: "19:30", location: "factory4_day" }, - messageType: 8, - messageTemplateId: "58fe0e3486f77471f772c3f2 0", - items: [{ - _id: "203161dde59c5a2fdd362da9", - _tpl: "5aa7e4a4e5b5b000137b76f2", - upd: { StackObjectsCount: 1, sptPresetId: "657fa87fc6679fefb3051e32" }, - parentId: "d2b3b859f667d4fd8b35bc96", - slotId: "hideout", - }, { - _id: "37c9968cfc4372c968f57c42", - _tpl: "657f925dada5fadd1f07a57a", - parentId: "203161dde59c5a2fdd362da9", - slotId: "Helmet_top", - upd: { Repairable: { Durability: 21, MaxDurability: 21 } }, - }, { - _id: "5517446f3cd41cf75d3a9cd2", - _tpl: "657f92acada5fadd1f07a57e", - parentId: "203161dde59c5a2fdd362da9", - slotId: "Helmet_back", - upd: { Repairable: { Durability: 21, MaxDurability: 21 } }, - }, { - _id: "0fdc8f25f7dfc61678cdef01", - _tpl: "657f92e7f4c82973640b2354", - parentId: "203161dde59c5a2fdd362da9", - slotId: "Helmet_ears", - upd: { Repairable: { Durability: 21, MaxDurability: 21 } }, - }, { - _id: "e2cba41b10edfc595e2bb574", - _tpl: "628b916469015a4e1711ed8d", - parentId: "6c5ef8a5fb3b88641420e9a0", - slotId: "mod_handguard", - upd: {}, - }, { - _id: "dd3aa187f853187198860933", - _tpl: "628b9be6cff66b70c002b14c", - parentId: "e2cba41b10edfc595e2bb574", - slotId: "mod_reciever", - upd: {}, - }, { - _id: "13d29ea647b01f0ecb774a54", - _tpl: "628b9471078f94059a4b9bfb", - parentId: "dd3aa187f853187198860933", - slotId: "mod_sight_rear", - upd: {}, - }, { - _id: "6c5ef8a5fb3b88641420e9a0", - _tpl: "628b8d83717774443b15e248", - parentId: "afcef56bf4fa36d0ec1f4166", - slotId: "mod_gas_block", - upd: {}, - }, { - _id: "7980e04a92db0858cb7f4bfa", - _tpl: "55d4ae6c4bdc2d8b2f8b456e", - parentId: "929c1577ba7390558c59d8a5", - slotId: "mod_stock", - upd: {}, - }, { - _id: "929c1577ba7390558c59d8a5", - _tpl: "628b9a40717774443b15e9f2", - parentId: "afcef56bf4fa36d0ec1f4166", - slotId: "mod_stock_000", - upd: {}, - }, { - _id: "afcef56bf4fa36d0ec1f4166", - _tpl: "628b5638ad252a16da6dd245", - parentId: "d2b3b859f667d4fd8b35bc96", - slotId: "hideout", - upd: { - FireMode: { FireMode: "single" }, - StackObjectsCount: 1, - Repairable: { Durability: 100, MaxDurability: 100 }, - }, - }, { - _id: "a94905f708670fca5de11e7e", - _tpl: "60339954d62c9b14ed777c06", - parentId: "d2b3b859f667d4fd8b35bc96", - slotId: "hideout", - upd: { - FireMode: { FireMode: "single" }, - StackObjectsCount: 1, - Repairable: { Durability: 100, MaxDurability: 100 }, - }, - }, { - _id: "8f5ce6d3c7730240c3ae78ad", - _tpl: "602e71bd53a60014f9705bfa", - parentId: "a94905f708670fca5de11e7e", - slotId: "mod_pistol_grip", - upd: {}, - }, { - _id: "c320122de049da2880d0a235", - _tpl: "5a7ad2e851dfba0016153692", - parentId: "a94905f708670fca5de11e7e", - slotId: "mod_magazine", - upd: {}, - }, { - _id: "d2923c8984f26f68f01d20d7", - _tpl: "602e3f1254072b51b239f713", - parentId: "a94905f708670fca5de11e7e", - slotId: "mod_stock_001", - upd: {}, - }, { - _id: "ecd363cddbb5361670d531b0", - _tpl: "60337f5dce399e10262255d1", - parentId: "d2b3b859f667d4fd8b35bc96", - slotId: "hideout", - upd: {}, - }, { - _id: "704c139d092f1bd3e3d18df2", - _tpl: "6034e3cb0ddce744014cb870", - parentId: "d2b3b859f667d4fd8b35bc96", - slotId: "hideout", - upd: {}, - }, { - _id: "72bd97cb21996a2282ff7bcd", - _tpl: "630765cb962d0247b029dc45", - parentId: "d2b3b859f667d4fd8b35bc96", - slotId: "hideout", - upd: {}, - }, { - _id: "44e3df51e01d5b23445fb95f", - _tpl: "630765777d50ff5e8a1ea718", - parentId: "d2b3b859f667d4fd8b35bc96", - slotId: "hideout", - upd: {}, - }, { - _id: "1cb0900a4bd068b04ca05db1", - _tpl: "63088377b5cd696784087147", - parentId: "d2b3b859f667d4fd8b35bc96", - slotId: "hideout", - upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, - }, { - _id: "379ca7cd56ebb1434bd89d62", - _tpl: "656f9d5900d62bcd2e02407c", - parentId: "eb3bbc6cb084a53ff48b672d", - slotId: "Front_plate", - upd: { Repairable: { Durability: 32.4841042, MaxDurability: 45 } }, - }, { - _id: "d700aaa1d7a15644f6b91dc7", - _tpl: "656f9d5900d62bcd2e02407c", - parentId: "eb3bbc6cb084a53ff48b672d", - slotId: "Back_plate", - upd: { Repairable: { Durability: 45, MaxDurability: 45 } }, - }, { - _id: "eb3bbc6cb084a53ff48b672d", - _tpl: "5b44d22286f774172b0c9de8", - parentId: "d2b3b859f667d4fd8b35bc96", - slotId: "hideout", - upd: { StackObjectsCount: 1 }, - }, { - _id: "6a3d83c5230d1779060e17a9", - _tpl: "65704de13e7bba58ea0285c8", - parentId: "eb3bbc6cb084a53ff48b672d", - slotId: "Soft_armor_front", - upd: { Repairable: { Durability: 37.4214172, MaxDurability: 56 } }, - }, { - _id: "9fba54de64b37902dd14b6e5", - _tpl: "65705c3c14f2ed6d7d0b7738", - parentId: "eb3bbc6cb084a53ff48b672d", - slotId: "Soft_armor_back", - upd: { Repairable: { Durability: 49.93156, MaxDurability: 56 } }, - }, { - _id: "2b534b3af5f240c625a77424", - _tpl: "65705c777260e1139e091408", - parentId: "eb3bbc6cb084a53ff48b672d", - slotId: "Soft_armor_left", - upd: { Repairable: { Durability: 12, MaxDurability: 12 } }, - }, { - _id: "e046688c9167ceaced5af3a7", - _tpl: "65705cb314f2ed6d7d0b773c", - parentId: "eb3bbc6cb084a53ff48b672d", - slotId: "soft_armor_right", - upd: { Repairable: { Durability: 12, MaxDurability: 12 } }, - }, { - _id: "6c612d370959e61b6c10b7bf", - _tpl: "65705cea4916448ae1050897", - parentId: "eb3bbc6cb084a53ff48b672d", - slotId: "Collar", - upd: { Repairable: { Durability: 14, MaxDurability: 14 } }, - }], -}]; +export const profileInsuranceFixture: Insurance[] = [ + { + scheduledTime: 1712950044.4, + traderId: "54cb50c76803fa8b248b4571", + maxStorageTime: 345600, + systemData: { date: "11.04.2024", time: "18:59", location: "factory4_day" }, + messageType: 8, + messageTemplateId: "58fe0e4586f774728248ca13 0", + items: [ + { + _id: "35111c9b72a87b6b7d95ad35", + _tpl: "58948c8e86f77409493f7266", + parentId: "d2b3b859f667d4fd8b35bc96", + slotId: "hideout", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + }, + { + _id: "d45436a159654f43ca3aa52f", + _tpl: "5580223e4bdc2d1c128b457f", + parentId: "d2b3b859f667d4fd8b35bc96", + slotId: "hideout", + upd: { + FireMode: { FireMode: "single" }, + StackObjectsCount: 1, + Repairable: { Durability: 100, MaxDurability: 100 }, + }, + }, + { + _id: "2c60ad9b6051f059ab796aa6", + _tpl: "5a7ae0c351dfba0017554310", + parentId: "d2b3b859f667d4fd8b35bc96", + slotId: "hideout", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + }, + { + _id: "a5c86cef7d25f57bf0fb593c", + _tpl: "5b432f3d5acfc4704b4a1dfb", + parentId: "d2b3b859f667d4fd8b35bc96", + slotId: "hideout", + upd: { StackObjectsCount: 1 }, + }, + { + _id: "8ac63abcbaf95d09a4d50c02", + _tpl: "5ea17ca01412a1425304d1c0", + parentId: "d2b3b859f667d4fd8b35bc96", + slotId: "hideout", + upd: { StackObjectsCount: 1 }, + }, + { + _id: "33c99e86f72af509da01dc9a", + _tpl: "657f9a55c6679fefb3051e19", + parentId: "8ac63abcbaf95d09a4d50c02", + slotId: "Helmet_top", + upd: { Repairable: { Durability: 24, MaxDurability: 24 } }, + }, + { + _id: "426902ae3d7efa5f8c78acf7", + _tpl: "657f9a94ada5fadd1f07a589", + parentId: "8ac63abcbaf95d09a4d50c02", + slotId: "Helmet_back", + upd: { Repairable: { Durability: 24, MaxDurability: 24 } }, + }, + { + _id: "5d2be23efb34d0d1da9d3701", + _tpl: "603648ff5a45383c122086ac", + parentId: "d2b3b859f667d4fd8b35bc96", + slotId: "hideout", + upd: { StackObjectsCount: 1 }, + }, + { + _id: "9f601faab37dcc58190898ac", + _tpl: "618bb76513f5097c8d5aa2d5", + parentId: "d2b3b859f667d4fd8b35bc96", + slotId: "hideout", + upd: { StackObjectsCount: 1 }, + }, + { + _id: "f74d377063e65d350e0099be", + _tpl: "5c0e5bab86f77461f55ed1f3", + parentId: "d2b3b859f667d4fd8b35bc96", + slotId: "hideout", + upd: { StackObjectsCount: 1 }, + }, + { + _id: "0ab2a81fc507ac846f43b15f", + _tpl: "6571b27a6d84a2b8b6007f92", + parentId: "f74d377063e65d350e0099be", + slotId: "Soft_armor_front", + upd: { Repairable: { Durability: 50.88512, MaxDurability: 52 } }, + }, + { + _id: "2ca1b6606d918483ed6b70a5", + _tpl: "6571baa74cb80d995d0a1490", + parentId: "f74d377063e65d350e0099be", + slotId: "Soft_armor_back", + upd: { Repairable: { Durability: 49, MaxDurability: 52 } }, + }, + { + _id: "5658a9d10f9d44112a991561", + _tpl: "6571baac6d84a2b8b6007fa3", + parentId: "f74d377063e65d350e0099be", + slotId: "Soft_armor_left", + upd: { Repairable: { Durability: 8, MaxDurability: 8 } }, + }, + { + _id: "8d0ba4d12fa601312b71d3d7", + _tpl: "6571bab0f41985531a038091", + parentId: "f74d377063e65d350e0099be", + slotId: "soft_armor_right", + upd: { Repairable: { Durability: 8, MaxDurability: 8 } }, + }, + { + _id: "45d19bbff6d42c8f781abb38", + _tpl: "6571babb4076795e5e07383f", + parentId: "f74d377063e65d350e0099be", + slotId: "Collar", + upd: { Repairable: { Durability: 14, MaxDurability: 14 } }, + }, + { + _id: "cf2ba30bab4d8e80393a8ffe", + _tpl: "6571bac34076795e5e073843", + parentId: "f74d377063e65d350e0099be", + slotId: "Groin", + upd: { Repairable: { Durability: 10, MaxDurability: 10 } }, + }, + { + _id: "a3f866e60ccd9c29e77eb5ef", + _tpl: "6571babf4cb80d995d0a1494", + parentId: "f74d377063e65d350e0099be", + slotId: "Groin_back", + upd: { Repairable: { Durability: 12, MaxDurability: 12 } }, + }, + { + _id: "a3287a706e1b77b44db82fa1", + _tpl: "5aa2ba71e5b5b000137b758f", + parentId: "d2b3b859f667d4fd8b35bc96", + slotId: "hideout", + upd: { StackObjectsCount: 1 }, + }, + { + _id: "c6ad1be7e8401755de69d6a0", + _tpl: "5d6d2ef3a4b93618084f58bd", + parentId: "d2b3b859f667d4fd8b35bc96", + slotId: "hideout", + upd: { StackObjectsCount: 1 }, + }, + { + _id: "7c42d3dce0ddbc4806bce48b", + _tpl: "5894a51286f77426d13baf02", + parentId: "35111c9b72a87b6b7d95ad35", + slotId: "mod_pistol_grip", + upd: {}, + }, + { + _id: "10b97872c5f4e0e1949a0369", + _tpl: "5c5db6742e2216000f1b2852", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "35111c9b72a87b6b7d95ad35", + slotId: "mod_magazine", + }, + { + _id: "a6cd9986dde4cabddcd2dce2", + _tpl: "5894a5b586f77426d2590767", + parentId: "35111c9b72a87b6b7d95ad35", + slotId: "mod_reciever", + upd: {}, + }, + { + _id: "b65635b515712f990fdcc201", + _tpl: "58ac1bf086f77420ed183f9f", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "35111c9b72a87b6b7d95ad35", + slotId: "mod_stock", + }, + { + _id: "0e11045873efe3625695c1ae", + _tpl: "5c5db6b32e221600102611a0", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "35111c9b72a87b6b7d95ad35", + slotId: "mod_charge", + }, + { + _id: "94c4161abe8bf654fb986063", + _tpl: "57adff4f24597737f373b6e6", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "a6cd9986dde4cabddcd2dce2", + slotId: "mod_scope", + }, + { + _id: "9b284ccfd0d535acec1ff58b", + _tpl: "5c5db5c62e22160012542255", + parentId: "a6cd9986dde4cabddcd2dce2", + slotId: "mod_barrel", + upd: {}, + }, + { + _id: "d730caa83a11fd01250a7261", + _tpl: "5c5db63a2e2216000f1b284a", + parentId: "a6cd9986dde4cabddcd2dce2", + slotId: "mod_handguard", + upd: {}, + }, + { + _id: "24291c7bcf91e362adb6d68b", + _tpl: "5fb6564947ce63734e3fa1da", + parentId: "a6cd9986dde4cabddcd2dce2", + slotId: "mod_sight_rear", + upd: { StackObjectsCount: 1 }, + }, + { + _id: "0d98fd0769cce8e473bbe540", + _tpl: "58d2664f86f7747fec5834f6", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "94c4161abe8bf654fb986063", + slotId: "mod_scope", + }, + { + _id: "11b174510f039e8217fbd202", + _tpl: "58d268fc86f774111273f8c2", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "0d98fd0769cce8e473bbe540", + slotId: "mod_scope", + }, + { + _id: "c435230e530574b1d7c32300", + _tpl: "5c7e8fab2e22165df16b889b", + parentId: "9b284ccfd0d535acec1ff58b", + slotId: "mod_muzzle", + upd: {}, + }, + { + _id: "15666fe6fd2d95206612e418", + _tpl: "6269220d70b6c02e665f2635", + parentId: "d730caa83a11fd01250a7261", + slotId: "mod_mount_000", + upd: { StackObjectsCount: 1 }, + }, + { + _id: "a54de8b9014eee71fdf1d01d", + _tpl: "6269220d70b6c02e665f2635", + parentId: "d730caa83a11fd01250a7261", + slotId: "mod_mount_001", + upd: { StackObjectsCount: 1 }, + }, + { + _id: "c34555bc95a9a7a23150a36f", + _tpl: "6269220d70b6c02e665f2635", + parentId: "d730caa83a11fd01250a7261", + slotId: "mod_mount_002", + upd: { StackObjectsCount: 1 }, + }, + { + _id: "91cae4ae30d1366b87158238", + _tpl: "6269220d70b6c02e665f2635", + parentId: "d730caa83a11fd01250a7261", + slotId: "mod_mount_003", + upd: { StackObjectsCount: 1 }, + }, + { + _id: "48f23df4509164cf397b9ab5", + _tpl: "6269220d70b6c02e665f2635", + parentId: "d730caa83a11fd01250a7261", + slotId: "mod_mount_004", + upd: { StackObjectsCount: 1 }, + }, + { + _id: "a55f05f689978ac65c7da654", + _tpl: "5b7be4895acfc400170e2dd5", + parentId: "d730caa83a11fd01250a7261", + slotId: "mod_foregrip", + upd: {}, + }, + { + _id: "8ae4ea81a2d6074162d87a9c", + _tpl: "5b7be47f5acfc400170e2dd2", + parentId: "d730caa83a11fd01250a7261", + slotId: "mod_mount_005", + upd: {}, + }, + { + _id: "312cc0f6687963305457235e", + _tpl: "5b7be47f5acfc400170e2dd2", + parentId: "d730caa83a11fd01250a7261", + slotId: "mod_mount_006", + upd: {}, + }, + { + _id: "e1e5aaf474b7282a52ac9a14", + _tpl: "5fb6567747ce63734e3fa1dc", + parentId: "d730caa83a11fd01250a7261", + slotId: "mod_sight_front", + upd: { StackObjectsCount: 1 }, + }, + { + _id: "bb9a34648e08f005db5d7484", + _tpl: "5cc9c20cd7f00c001336c65d", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "15666fe6fd2d95206612e418", + slotId: "mod_tactical", + }, + { + _id: "dd9ac99d3ea4c9656221bcc9", + _tpl: "5cc9c20cd7f00c001336c65d", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "a54de8b9014eee71fdf1d01d", + slotId: "mod_tactical", + }, + { + _id: "b22748de8da5f3c1362dd8e0", + _tpl: "5cc9c20cd7f00c001336c65d", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "c34555bc95a9a7a23150a36f", + slotId: "mod_tactical", + }, + { + _id: "e3cc1be8954c4889f94b435a", + _tpl: "5cc9c20cd7f00c001336c65d", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "91cae4ae30d1366b87158238", + slotId: "mod_tactical", + }, + { + _id: "e73f05be5a306168e847da82", + _tpl: "5cc9c20cd7f00c001336c65d", + parentId: "48f23df4509164cf397b9ab5", + slotId: "mod_tactical", + upd: { StackObjectsCount: 1 }, + }, + { + _id: "847cf35ec92d8af8e4814ea8", + _tpl: "5c1cd46f2e22164bef5cfedb", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "a55f05f689978ac65c7da654", + slotId: "mod_foregrip", + }, + { + _id: "bb4b7a4475fea0f0135305f6", + _tpl: "5cc9c20cd7f00c001336c65d", + parentId: "8ae4ea81a2d6074162d87a9c", + slotId: "mod_tactical", + upd: { StackObjectsCount: 1 }, + }, + { + _id: "d0ac8e688a0bb17668589909", + _tpl: "5cc9c20cd7f00c001336c65d", + parentId: "312cc0f6687963305457235e", + slotId: "mod_tactical", + upd: { StackObjectsCount: 1 }, + }, + { + _id: "5dbcf8cbbb3f8ef669836320", + _tpl: "5c793fc42e221600114ca25d", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "b65635b515712f990fdcc201", + slotId: "mod_stock", + }, + { + _id: "f996645c809968f8033593a6", + _tpl: "5fc2369685fd526b824a5713", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "5dbcf8cbbb3f8ef669836320", + slotId: "mod_stock_000", + }, + { + _id: "7d959c20811fdc440387f0a4", + _tpl: "55d447bb4bdc2d892f8b456f", + parentId: "d45436a159654f43ca3aa52f", + slotId: "mod_barrel", + upd: {}, + }, + { + _id: "16969c588bd20e223d93e65a", + _tpl: "611a31ce5b7ffe001b4649d1", + parentId: "d45436a159654f43ca3aa52f", + slotId: "mod_stock", + upd: {}, + }, + { + _id: "d3a31aa632d852bfe57d7aca", + _tpl: "5a6b5f868dc32e000a311389", + parentId: "2c60ad9b6051f059ab796aa6", + slotId: "mod_barrel", + upd: {}, + }, + { + _id: "fdba343644672594e7c73f47", + _tpl: "5a7b4960e899ef197b331a2d", + parentId: "2c60ad9b6051f059ab796aa6", + slotId: "mod_pistol_grip", + upd: {}, + }, + { + _id: "5f47943e00d184b3c8f9c2b5", + _tpl: "5a6f5e048dc32e00094b97da", + parentId: "2c60ad9b6051f059ab796aa6", + slotId: "mod_reciever", + upd: {}, + }, + { + _id: "f616853cb3b860d670252e66", + _tpl: "5a718b548dc32e000d46d262", + parentId: "2c60ad9b6051f059ab796aa6", + slotId: "mod_magazine", + upd: {}, + }, + { + _id: "5153ee12f6d4abc4856dd4ae", + _tpl: "5a7ad74e51dfba0015068f45", + parentId: "2c60ad9b6051f059ab796aa6", + slotId: "mod_tactical", + upd: {}, + }, + { + _id: "aa5dc438d849a311e335667b", + _tpl: "5a7d9122159bd4001438dbf4", + parentId: "5f47943e00d184b3c8f9c2b5", + slotId: "mod_sight_rear", + upd: {}, + }, + { + _id: "79a1dfa8bff1b7ca118d6b0f", + _tpl: "5a7d90eb159bd400165484f1", + parentId: "5f47943e00d184b3c8f9c2b5", + slotId: "mod_sight_front", + upd: {}, + }, + { + _id: "e784a6d774f9a885bf5ed847", + _tpl: "5a7b483fe899ef0016170d15", + parentId: "5153ee12f6d4abc4856dd4ae", + slotId: "mod_tactical", + upd: {}, + }, + { + _id: "fd79789b0e394e2cc1299ab1", + _tpl: "5c5db6742e2216000f1b2852", + parentId: "5d2be23efb34d0d1da9d3701", + slotId: "1", + upd: { StackObjectsCount: 1 }, + location: { x: 0, y: 0, r: "Horizontal", isSearched: true }, + }, + { + _id: "a19f5e338bfd32f1c1f3fb73", + _tpl: "5c5db6742e2216000f1b2852", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "5d2be23efb34d0d1da9d3701", + slotId: "2", + location: { x: 0, y: 0, r: "Horizontal", isSearched: true }, + }, + { + _id: "9e709808929c226f7bdbf57a", + _tpl: "5c5db6742e2216000f1b2852", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "5d2be23efb34d0d1da9d3701", + slotId: "3", + location: { x: 0, y: 0, r: "Horizontal", isSearched: true }, + }, + { + _id: "9fe70bf25a2db7f8c1b23502", + _tpl: "5c5db6742e2216000f1b2852", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "5d2be23efb34d0d1da9d3701", + slotId: "4", + location: { x: 0, y: 0, r: "Horizontal", isSearched: true }, + }, + { + _id: "4519dc962deebb2dbfc9e70c", + _tpl: "5c5db6742e2216000f1b2852", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "5d2be23efb34d0d1da9d3701", + slotId: "5", + location: { x: 0, y: 0, r: "Horizontal", isSearched: true }, + }, + { + _id: "a94275912f1cbcd483563916", + _tpl: "5c5db6742e2216000f1b2852", + parentId: "5d2be23efb34d0d1da9d3701", + slotId: "6", + upd: { StackObjectsCount: 1 }, + location: { x: 0, y: 0, r: "Horizontal", isSearched: true }, + }, + { + _id: "7f2ae8c0685bf3a2195185dd", + _tpl: "5c5db6742e2216000f1b2852", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "5d2be23efb34d0d1da9d3701", + slotId: "7", + location: { x: 0, y: 0, r: "Horizontal", isSearched: true }, + }, + { + _id: "53a9f3dc5c08cbd02ff31b12", + _tpl: "5c5db6742e2216000f1b2852", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "5d2be23efb34d0d1da9d3701", + slotId: "8", + location: { x: 0, y: 0, r: "Horizontal", isSearched: true }, + }, + { + _id: "e0ab45585b1a874dbaa68fb3", + _tpl: "5c5db6742e2216000f1b2852", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "5d2be23efb34d0d1da9d3701", + slotId: "9", + location: { x: 0, y: 0, r: "Horizontal", isSearched: true }, + }, + { + _id: "3f66f7abde039a848f8b4cf0", + _tpl: "5c5db6742e2216000f1b2852", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "5d2be23efb34d0d1da9d3701", + slotId: "10", + location: { x: 0, y: 0, r: "Horizontal", isSearched: true }, + }, + { + _id: "04a202a45f8a39b61a58a05a", + _tpl: "544a5caa4bdc2d1a388b4568", + parentId: "9f601faab37dcc58190898ac", + slotId: "main", + upd: { StackObjectsCount: 1 }, + location: { x: 0, y: 0, r: "Horizontal", isSearched: true }, + }, + { + _id: "d5f6e03c07ede944e89fb407", + _tpl: "6570e83223c1f638ef0b0ede", + parentId: "04a202a45f8a39b61a58a05a", + slotId: "Soft_armor_front", + upd: { Repairable: { Durability: 42, MaxDurability: 42 } }, + }, + { + _id: "5433cbf0f07a68651e888c74", + _tpl: "6570e87c23c1f638ef0b0ee2", + parentId: "04a202a45f8a39b61a58a05a", + slotId: "Soft_armor_back", + upd: { Repairable: { Durability: 42, MaxDurability: 42 } }, + }, + { + _id: "da91bed43f688a80b627ad4d", + _tpl: "6570e90b3a5689d85f08db97", + parentId: "04a202a45f8a39b61a58a05a", + slotId: "Groin", + upd: { Repairable: { Durability: 28, MaxDurability: 28 } }, + }, + { + _id: "ad7f524f3de9ad544df8c0b8", + _tpl: "5c5db6742e2216000f1b2852", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "9f601faab37dcc58190898ac", + slotId: "main", + location: { x: 3, y: 0, r: "Horizontal", isSearched: true }, + }, + { + _id: "0844cf6b7a89c13454b6e3db", + _tpl: "5c5db6742e2216000f1b2852", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "9f601faab37dcc58190898ac", + slotId: "main", + location: { x: 4, y: 0, r: "Horizontal", isSearched: true }, + }, + { + _id: "c3f58f44366d0a06d29d66ba", + _tpl: "5a38e6bac4a2826c6e06d79b", + parentId: "9f601faab37dcc58190898ac", + slotId: "main", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + location: { x: 0, y: 4, r: "Horizontal", isSearched: true }, + }, + { + _id: "d46e16faba780c68e0600532", + _tpl: "656fa0fb498d1b7e3e071d9c", + parentId: "9f601faab37dcc58190898ac", + slotId: "main", + upd: { StackObjectsCount: 1, Repairable: { Durability: 45, MaxDurability: 45 } }, + location: { x: 3, y: 2, r: "Horizontal", isSearched: true }, + }, + { + _id: "26598f88d49198c4a0a9391c", + _tpl: "571a12c42459771f627b58a0", + parentId: "9f601faab37dcc58190898ac", + slotId: "main", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + location: { x: 3, y: 4, r: "Horizontal", isSearched: true }, + }, + { + _id: "5ee8e16837809adc34caae00", + _tpl: "656f9fa0498d1b7e3e071d98", + parentId: "04a202a45f8a39b61a58a05a", + slotId: "Front_plate", + upd: { Repairable: { Durability: 50, MaxDurability: 50 } }, + }, + { + _id: "de042f9ebf0fd9ad451033d4", + _tpl: "656f9fa0498d1b7e3e071d98", + parentId: "04a202a45f8a39b61a58a05a", + slotId: "Back_plate", + upd: { Repairable: { Durability: 50, MaxDurability: 50 } }, + }, + { + _id: "03de471c2a3faa359aca7486", + _tpl: "5c5db6742e2216000f1b2852", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "04a202a45f8a39b61a58a05a", + slotId: "1", + location: { x: 0, y: 0, r: "Horizontal", isSearched: true }, + }, + { + _id: "091c85804613176da9478edd", + _tpl: "5c5db6742e2216000f1b2852", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "04a202a45f8a39b61a58a05a", + slotId: "2", + location: { x: 0, y: 0, r: "Horizontal", isSearched: true }, + }, + { + _id: "5482888e242a98ff154c0ee8", + _tpl: "5c5db6742e2216000f1b2852", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "04a202a45f8a39b61a58a05a", + slotId: "3", + location: { x: 0, y: 0, r: "Horizontal", isSearched: true }, + }, + { + _id: "3c8e206a2c2e9b0fee45b56b", + _tpl: "5c5db6742e2216000f1b2852", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "04a202a45f8a39b61a58a05a", + slotId: "4", + location: { x: 0, y: 0, r: "Horizontal", isSearched: true }, + }, + { + _id: "b2405216e5730f3511884a10", + _tpl: "5ea17ca01412a1425304d1c0", + parentId: "04a202a45f8a39b61a58a05a", + slotId: "5", + upd: { StackObjectsCount: 1 }, + location: { x: 0, y: 0, r: "Horizontal", isSearched: true }, + }, + { + _id: "7a0675280dbbad69ce592d74", + _tpl: "657f9a55c6679fefb3051e19", + parentId: "b2405216e5730f3511884a10", + slotId: "Helmet_top", + upd: { Repairable: { Durability: 24, MaxDurability: 24 } }, + }, + { + _id: "c0c182942f54d3c183f0e179", + _tpl: "657f9a94ada5fadd1f07a589", + parentId: "b2405216e5730f3511884a10", + slotId: "Helmet_back", + upd: { Repairable: { Durability: 24, MaxDurability: 24 } }, + }, + { + _id: "8ec4534a4fe96f89ea88c107", + _tpl: "5c165d832e2216398b5a7e36", + parentId: "04a202a45f8a39b61a58a05a", + slotId: "6", + upd: { StackObjectsCount: 1 }, + location: { x: 0, y: 0, r: "Horizontal", isSearched: true }, + }, + { + _id: "0d91ed3d44881d33b1fd94ec", + _tpl: "5c5db6742e2216000f1b2852", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "04a202a45f8a39b61a58a05a", + slotId: "11", + location: { x: 0, y: 0, r: "Horizontal", isSearched: true }, + }, + { + _id: "f7066fdfeefb29eca1d2dbeb", + _tpl: "5ea18c84ecf1982c7712d9a2", + upd: { StackObjectsCount: 1, Repairable: { Durability: 22, MaxDurability: 25 } }, + parentId: "b2405216e5730f3511884a10", + slotId: "mod_nvg", + }, + { + _id: "ee0ec86e9608abe773175e3a", + _tpl: "5c0558060db834001b735271", + parentId: "f7066fdfeefb29eca1d2dbeb", + slotId: "mod_nvg", + upd: { StackObjectsCount: 1 }, + }, + { + _id: "0515d1e589fd626b504e59cd", + _tpl: "5a38ee51c4a282000c5a955c", + parentId: "c3f58f44366d0a06d29d66ba", + slotId: "mod_magazine", + upd: {}, + }, + { + _id: "cb30ae6f997a2e6d119f2186", + _tpl: "5a38ef1fc4a282000b1521f6", + parentId: "c3f58f44366d0a06d29d66ba", + slotId: "mod_stock", + upd: { Foldable: { Folded: true } }, + }, + { + _id: "be57a04835a8c1ae85811949", + _tpl: "5a38eecdc4a282329a73b512", + parentId: "cb30ae6f997a2e6d119f2186", + slotId: "mod_pistol_grip", + upd: {}, + }, + { + _id: "fd6ef6e377e6280ca9386dbc", + _tpl: "571a26d524597720680fbe8a", + parentId: "26598f88d49198c4a0a9391c", + slotId: "mod_barrel", + upd: {}, + }, + { + _id: "5c40aff0d1c5d4f206123b83", + _tpl: "571a282c2459771fb2755a69", + parentId: "26598f88d49198c4a0a9391c", + slotId: "mod_pistol_grip", + upd: {}, + }, + { + _id: "34b2c7cf0f6b8f484411cebf", + _tpl: "571a29dc2459771fb2755a6a", + parentId: "26598f88d49198c4a0a9391c", + slotId: "mod_magazine", + upd: {}, + }, + { + _id: "9932dd0e1339053e27d54a41", + _tpl: "654a4dea7c17dec2f50cc86a", + parentId: "f74d377063e65d350e0099be", + slotId: "Front_plate", + upd: { Repairable: { Durability: 50, MaxDurability: 50 } }, + }, + { + _id: "0f69c261881206320d8f583d", + _tpl: "657b22485f444d6dff0c6c2f", + parentId: "f74d377063e65d350e0099be", + slotId: "Back_plate", + upd: { StackObjectsCount: 1, Repairable: { Durability: 4.681114, MaxDurability: 40 } }, + }, + ], + }, + { + scheduledTime: 1712896726, + traderId: "54cb57776803fa99248b456e", + maxStorageTime: 518400, + systemData: { date: "11.04.2024", time: "19:19", location: "factory4_day" }, + messageType: 8, + messageTemplateId: "58fe0e3486f77471f772c3f2 3", + items: [ + { + _id: "5cfe91bfe022641c19bc8c60", + _tpl: "5aafa857e5b5b00018480968", + upd: { + StackObjectsCount: 1, + sptPresetId: "5ac4ad3686f774181345c3da", + Repairable: { Durability: 98.33, MaxDurability: 98.33 }, + }, + parentId: "d2b3b859f667d4fd8b35bc96", + slotId: "hideout", + }, + { + _id: "a5063619e7f4db123ca07fcc", + _tpl: "60db29ce99594040e04c4a27", + parentId: "d2b3b859f667d4fd8b35bc96", + slotId: "hideout", + upd: { + FireMode: { FireMode: "single" }, + StackObjectsCount: 1, + Repairable: { Durability: 100, MaxDurability: 100 }, + }, + }, + { + _id: "3702c30b6333e28d6a15d62c", + _tpl: "56e0598dd2720bb5668b45a6", + parentId: "d2b3b859f667d4fd8b35bc96", + slotId: "hideout", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + }, + { + _id: "387c9f2b44d2da266f856b31", + _tpl: "6571bde39837cc51b800c212", + parentId: "d2b3b859f667d4fd8b35bc96", + slotId: "hideout", + upd: { StackObjectsCount: 1 }, + }, + { + _id: "275f046ea1a7b40046cd54fa", + _tpl: "5b40e4035acfc47a87740943", + parentId: "d2b3b859f667d4fd8b35bc96", + slotId: "hideout", + upd: { StackObjectsCount: 1 }, + }, + { + _id: "f30858ff9924b1fe211dd1f7", + _tpl: "657f95bff92cd718b701550c", + parentId: "275f046ea1a7b40046cd54fa", + slotId: "Helmet_top", + upd: { Repairable: { Durability: 10.3212032, MaxDurability: 18 } }, + }, + { + _id: "eec1072ac0cc44984e1ed43b", + _tpl: "657f9605f4c82973640b2358", + parentId: "275f046ea1a7b40046cd54fa", + slotId: "Helmet_back", + upd: { Repairable: { Durability: 13.3160009, MaxDurability: 18 } }, + }, + { + _id: "b82495b01ad0bfe5dd7e864d", + _tpl: "5c0e746986f7741453628fe5", + parentId: "d2b3b859f667d4fd8b35bc96", + slotId: "hideout", + upd: { StackObjectsCount: 1 }, + }, + { + _id: "31531773990cd1aefa751db7", + _tpl: "6570df294cc0d2ab1e05ed74", + parentId: "b82495b01ad0bfe5dd7e864d", + slotId: "Soft_armor_front", + upd: { Repairable: { Durability: 31.0571022, MaxDurability: 35 } }, + }, + { + _id: "eb8c6c7c671d2a2490454e7c", + _tpl: "6570df9c615f54368b04fca9", + parentId: "b82495b01ad0bfe5dd7e864d", + slotId: "Soft_armor_back", + upd: { Repairable: { Durability: 30.8, MaxDurability: 35 } }, + }, + { + _id: "f9cc99048aa37c5a4a837ef9", + _tpl: "5ca20d5986f774331e7c9602", + parentId: "d2b3b859f667d4fd8b35bc96", + slotId: "hideout", + upd: { StackObjectsCount: 1 }, + }, + { + _id: "bd8a4a3783d80b81cc8655ee", + _tpl: "5aa2ba71e5b5b000137b758f", + parentId: "d2b3b859f667d4fd8b35bc96", + slotId: "hideout", + upd: { StackObjectsCount: 1 }, + }, + { + _id: "025748ec34dcd1bfb2529537", + _tpl: "5c0d32fcd174af02a1659c75", + parentId: "d2b3b859f667d4fd8b35bc96", + slotId: "hideout", + upd: { StackObjectsCount: 1 }, + }, + { + _id: "9c552e79f1ae38350afb3723", + _tpl: "5addccf45acfc400185c2989", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "5cfe91bfe022641c19bc8c60", + slotId: "mod_magazine", + }, + { + _id: "14cb5b7c9789876325670163", + _tpl: "5aaf8e43e5b5b00015693246", + parentId: "5cfe91bfe022641c19bc8c60", + slotId: "mod_stock", + upd: {}, + }, + { + _id: "0e4c9e11000589751523a62c", + _tpl: "5addbac75acfc400194dbc56", + parentId: "5cfe91bfe022641c19bc8c60", + slotId: "mod_barrel", + upd: { StackObjectsCount: 1 }, + }, + { + _id: "a63cf65e9646a04944d18106", + _tpl: "5abcbb20d8ce87001773e258", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "5cfe91bfe022641c19bc8c60", + slotId: "mod_sight_rear", + }, + { + _id: "f67388e02546cd97c976d479", + _tpl: "5addbfe15acfc4001a5fc58b", + parentId: "5cfe91bfe022641c19bc8c60", + slotId: "mod_mount", + upd: { StackObjectsCount: 1 }, + }, + { + _id: "bed3b1a2f866e18743db2a63", + _tpl: "5addbfbb5acfc400194dbcf7", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "14cb5b7c9789876325670163", + slotId: "mod_mount", + }, + { + _id: "821a4953b87f562b3f435fd7", + _tpl: "5649a2464bdc2d91118b45a8", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "bed3b1a2f866e18743db2a63", + slotId: "mod_scope", + }, + { + _id: "24813deb9b9a6ec3ca8376ef", + _tpl: "5d10b49bd7ad1a1a560708b0", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "bed3b1a2f866e18743db2a63", + slotId: "mod_tactical", + }, + { + _id: "4194116ceb7e9e623cba4e89", + _tpl: "609bab8b455afd752b2e6138", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "821a4953b87f562b3f435fd7", + slotId: "mod_scope", + }, + { + _id: "3bd8b76ba1ff8f1cf954af91", + _tpl: "59bffc1f86f77435b128b872", + parentId: "0e4c9e11000589751523a62c", + slotId: "mod_muzzle", + upd: { StackObjectsCount: 1 }, + }, + { + _id: "3d953b4a4283363d0494d614", + _tpl: "59bffbb386f77435b379b9c2", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "3bd8b76ba1ff8f1cf954af91", + slotId: "mod_muzzle", + }, + { + _id: "4b2c9fb752a7c3458e07a35d", + _tpl: "626bb8532c923541184624b4", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "f67388e02546cd97c976d479", + slotId: "mod_scope", + }, + { + _id: "ce39864f056a3ad649d77243", + _tpl: "60dc519adf4c47305f6d410d", + parentId: "a5063619e7f4db123ca07fcc", + slotId: "mod_magazine", + upd: {}, + }, + { + _id: "4ffc8f4e80708f6b9336c224", + _tpl: "612368f58b401f4f51239b33", + parentId: "a5063619e7f4db123ca07fcc", + slotId: "mod_barrel", + upd: {}, + }, + { + _id: "b401a4ce551dfcb0602e4073", + _tpl: "612781056f3d944a17348d60", + parentId: "a5063619e7f4db123ca07fcc", + slotId: "mod_stock", + upd: {}, + }, + { + _id: "b206761507a97037d05f0268", + _tpl: "6123649463849f3d843da7c4", + parentId: "a5063619e7f4db123ca07fcc", + slotId: "mod_handguard", + upd: {}, + }, + { + _id: "25af8615f5c902fd5920965f", + _tpl: "619d36da53b4d42ee724fae4", + parentId: "4ffc8f4e80708f6b9336c224", + slotId: "mod_muzzle", + upd: {}, + }, + { + _id: "38c5e9751e1d69d4d0804a49", + _tpl: "5448c12b4bdc2d02308b456f", + parentId: "3702c30b6333e28d6a15d62c", + slotId: "mod_magazine", + upd: {}, + }, + { + _id: "54da5dc9656bb9477eb16c88", + _tpl: "56e05b06d2720bb2668b4586", + parentId: "3702c30b6333e28d6a15d62c", + slotId: "mod_muzzle", + upd: {}, + }, + { + _id: "ad690f7145984b942288457f", + _tpl: "56e05a6ed2720bd0748b4567", + parentId: "3702c30b6333e28d6a15d62c", + slotId: "mod_pistolgrip", + upd: {}, + }, + { + _id: "c4ffff33f0a5f48c9500699a", + _tpl: "656fa0fb498d1b7e3e071d9c", + parentId: "b82495b01ad0bfe5dd7e864d", + slotId: "Front_plate", + upd: { Repairable: { Durability: 31.1713047, MaxDurability: 45 } }, + }, + { + _id: "8453961a28b572039197e140", + _tpl: "656fa0fb498d1b7e3e071d9c", + parentId: "b82495b01ad0bfe5dd7e864d", + slotId: "Back_plate", + upd: { Repairable: { Durability: 32.4, MaxDurability: 45 } }, + }, + { + _id: "43e7482d78b276a5db4f4fef", + _tpl: "5addccf45acfc400185c2989", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "b82495b01ad0bfe5dd7e864d", + slotId: "1", + location: { x: 0, y: 1, r: "Horizontal", isSearched: true }, + }, + { + _id: "7372a194a2de632f5941b701", + _tpl: "5addccf45acfc400185c2989", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "b82495b01ad0bfe5dd7e864d", + slotId: "2", + location: { x: 0, y: 1, r: "Horizontal", isSearched: true }, + }, + { + _id: "624555830937dfa5190a11bf", + _tpl: "5addccf45acfc400185c2989", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "b82495b01ad0bfe5dd7e864d", + slotId: "3", + location: { x: 0, y: 1, r: "Horizontal", isSearched: true }, + }, + { + _id: "05aedd00b683ce0d00ac5c74", + _tpl: "5addccf45acfc400185c2989", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "b82495b01ad0bfe5dd7e864d", + slotId: "4", + location: { x: 0, y: 0, r: "Horizontal", isSearched: true }, + }, + { + _id: "8c3eccca9f25989d68d90e59", + _tpl: "5addccf45acfc400185c2989", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "b82495b01ad0bfe5dd7e864d", + slotId: "5", + location: { x: 0, y: 0, r: "Horizontal", isSearched: true }, + }, + { + _id: "b8b2e1651d7dbb891053b514", + _tpl: "5aa7e454e5b5b0214e506fa2", + parentId: "b82495b01ad0bfe5dd7e864d", + slotId: "8", + upd: { StackObjectsCount: 1 }, + location: { x: 0, y: 0, r: "Horizontal", isSearched: true }, + }, + { + _id: "f9b891b8a5cf948b858a7b1b", + _tpl: "657f925dada5fadd1f07a57a", + parentId: "b8b2e1651d7dbb891053b514", + slotId: "Helmet_top", + upd: { Repairable: { Durability: 21, MaxDurability: 21 } }, + }, + { + _id: "8b66bc46287219eb0e7c190d", + _tpl: "657f92acada5fadd1f07a57e", + parentId: "b8b2e1651d7dbb891053b514", + slotId: "Helmet_back", + upd: { Repairable: { Durability: 21, MaxDurability: 21 } }, + }, + { + _id: "24cd31ecc0fdac526c8bd21d", + _tpl: "657f92e7f4c82973640b2354", + parentId: "b8b2e1651d7dbb891053b514", + slotId: "Helmet_ears", + upd: { Repairable: { Durability: 21, MaxDurability: 21 } }, + }, + { + _id: "c6125558f051cd10cfaf77e0", + _tpl: "5d6d3716a4b9361bc8618872", + parentId: "b82495b01ad0bfe5dd7e864d", + slotId: "9", + upd: { StackObjectsCount: 1 }, + location: { x: 0, y: 0, r: "Horizontal", isSearched: true }, + }, + { + _id: "ee92a87a762b35b45f9d7fa7", + _tpl: "657fa009d4caf976440afe3a", + parentId: "c6125558f051cd10cfaf77e0", + slotId: "Helmet_top", + upd: { Repairable: { Durability: 33, MaxDurability: 33 } }, + }, + { + _id: "be9a15c5ab850ae0437315bb", + _tpl: "657fa04ac6679fefb3051e24", + parentId: "c6125558f051cd10cfaf77e0", + slotId: "Helmet_back", + upd: { Repairable: { Durability: 33, MaxDurability: 33 } }, + }, + { + _id: "65c9ceccbebe5f2813a8c70e", + _tpl: "657fa07387e11c61f70bface", + parentId: "c6125558f051cd10cfaf77e0", + slotId: "Helmet_ears", + upd: { Repairable: { Durability: 33, MaxDurability: 33 } }, + }, + { + _id: "769eab07773ecfaa6e12e4c4", + _tpl: "5aa7e3abe5b5b000171d064d", + upd: { + StackObjectsCount: 1, + Repairable: { Durability: 50, MaxDurability: 50 }, + Togglable: { On: true }, + }, + parentId: "b8b2e1651d7dbb891053b514", + slotId: "mod_equipment", + }, + { + _id: "82aa530739c59be8dd5a0911", + _tpl: "5d6d3829a4b9361bc8618943", + upd: { + StackObjectsCount: 1, + Repairable: { Durability: 50, MaxDurability: 50 }, + Togglable: { On: true }, + }, + parentId: "c6125558f051cd10cfaf77e0", + slotId: "mod_equipment_000", + }, + { + _id: "996a6f0f8e90cb31f758c801", + _tpl: "5d6d3be5a4b9361bc73bc763", + upd: { StackObjectsCount: 1, Repairable: { Durability: 10, MaxDurability: 24 } }, + parentId: "c6125558f051cd10cfaf77e0", + slotId: "mod_equipment_001", + }, + { + _id: "8c43cca672e16a931590945f", + _tpl: "5d6d3943a4b9360dbc46d0cc", + upd: { StackObjectsCount: 1, Repairable: { Durability: 1, MaxDurability: 1 } }, + parentId: "c6125558f051cd10cfaf77e0", + slotId: "mod_equipment_002", + }, + { + _id: "5858b72da0ca732b2fb5ed95", + _tpl: "544a5caa4bdc2d1a388b4568", + parentId: "f9cc99048aa37c5a4a837ef9", + slotId: "main", + upd: { StackObjectsCount: 1 }, + location: { x: 0, y: 0, r: "Vertical", isSearched: true }, + }, + { + _id: "43ef5a5e1c93ba3ab032811f", + _tpl: "6570e83223c1f638ef0b0ede", + parentId: "5858b72da0ca732b2fb5ed95", + slotId: "Soft_armor_front", + upd: { Repairable: { Durability: 42, MaxDurability: 42 } }, + }, + { + _id: "e1f16c6d9e853f2735948665", + _tpl: "6570e87c23c1f638ef0b0ee2", + parentId: "5858b72da0ca732b2fb5ed95", + slotId: "Soft_armor_back", + upd: { Repairable: { Durability: 42, MaxDurability: 42 } }, + }, + { + _id: "d9bdf684a8264ac1fb3208bf", + _tpl: "6570e90b3a5689d85f08db97", + parentId: "5858b72da0ca732b2fb5ed95", + slotId: "Groin", + upd: { Repairable: { Durability: 28, MaxDurability: 28 } }, + }, + { + _id: "e4b484ba7209d770482732c8", + _tpl: "5addccf45acfc400185c2989", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "f9cc99048aa37c5a4a837ef9", + slotId: "main", + location: { x: 0, y: 3, r: "Horizontal", isSearched: true }, + }, + { + _id: "ddc3945694d52dcdae9cba4d", + _tpl: "5addccf45acfc400185c2989", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "f9cc99048aa37c5a4a837ef9", + slotId: "main", + location: { x: 1, y: 3, r: "Horizontal", isSearched: true }, + }, + { + _id: "59923cfba8be35031e5d95e6", + _tpl: "5addccf45acfc400185c2989", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "f9cc99048aa37c5a4a837ef9", + slotId: "main", + location: { x: 2, y: 3, r: "Horizontal", isSearched: true }, + }, + { + _id: "95cf47373df5c4f07f458a93", + _tpl: "5addccf45acfc400185c2989", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "f9cc99048aa37c5a4a837ef9", + slotId: "main", + location: { x: 3, y: 3, r: "Horizontal", isSearched: true }, + }, + { + _id: "98661f27ea826095d0cdd609", + _tpl: "656f9fa0498d1b7e3e071d98", + parentId: "5858b72da0ca732b2fb5ed95", + slotId: "Front_plate", + upd: { Repairable: { Durability: 50, MaxDurability: 50 } }, + }, + { + _id: "525179b06d14baaddb2b04fb", + _tpl: "656f9fa0498d1b7e3e071d98", + parentId: "5858b72da0ca732b2fb5ed95", + slotId: "Back_plate", + upd: { Repairable: { Durability: 50, MaxDurability: 50 } }, + }, + { + _id: "353638d16450339e40f5b5eb", + _tpl: "5addccf45acfc400185c2989", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "5858b72da0ca732b2fb5ed95", + slotId: "1", + location: { x: 0, y: 0, r: "Horizontal", isSearched: true }, + }, + { + _id: "fa4a5c3e4e3c2f017e35eb1a", + _tpl: "5addccf45acfc400185c2989", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "5858b72da0ca732b2fb5ed95", + slotId: "2", + location: { x: 0, y: 0, r: "Horizontal", isSearched: true }, + }, + { + _id: "7554a8ddb30e0306de7b7d80", + _tpl: "5addccf45acfc400185c2989", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "5858b72da0ca732b2fb5ed95", + slotId: "3", + location: { x: 0, y: 0, r: "Horizontal", isSearched: true }, + }, + { + _id: "4c73b93f4d9f17a05a5782fa", + _tpl: "5addccf45acfc400185c2989", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "5858b72da0ca732b2fb5ed95", + slotId: "4", + location: { x: 0, y: 0, r: "Horizontal", isSearched: true }, + }, + { + _id: "8ce190fcd2ffe5f1f9ad345a", + _tpl: "5aa7e4a4e5b5b000137b76f2", + parentId: "5858b72da0ca732b2fb5ed95", + slotId: "5", + upd: { StackObjectsCount: 1 }, + location: { x: 0, y: 0, r: "Horizontal", isSearched: true }, + }, + { + _id: "6607b1b9d73f83e559304208", + _tpl: "657f925dada5fadd1f07a57a", + parentId: "8ce190fcd2ffe5f1f9ad345a", + slotId: "Helmet_top", + upd: { Repairable: { Durability: 21, MaxDurability: 21 } }, + }, + { + _id: "41912d06dac91585499c05a2", + _tpl: "657f92acada5fadd1f07a57e", + parentId: "8ce190fcd2ffe5f1f9ad345a", + slotId: "Helmet_back", + upd: { Repairable: { Durability: 21, MaxDurability: 21 } }, + }, + { + _id: "db24f69de28bddd7f09b9c3e", + _tpl: "657f92e7f4c82973640b2354", + parentId: "8ce190fcd2ffe5f1f9ad345a", + slotId: "Helmet_ears", + upd: { Repairable: { Durability: 21, MaxDurability: 21 } }, + }, + { + _id: "6c578731bc0c3f91c8089116", + _tpl: "5addccf45acfc400185c2989", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "5858b72da0ca732b2fb5ed95", + slotId: "6", + location: { x: 0, y: 0, r: "Horizontal", isSearched: true }, + }, + { + _id: "aa7b1ce4897aa7e64309ce86", + _tpl: "5addccf45acfc400185c2989", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "5858b72da0ca732b2fb5ed95", + slotId: "6", + location: { x: 1, y: 0, r: "Horizontal", isSearched: true }, + }, + { + _id: "7e5e5dbe18de6aea779d904d", + _tpl: "5addccf45acfc400185c2989", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "5858b72da0ca732b2fb5ed95", + slotId: "11", + location: { x: 0, y: 0, r: "Horizontal", isSearched: true }, + }, + { + _id: "b50b5052892729841e26934f", + _tpl: "5aa7e3abe5b5b000171d064d", + upd: { + StackObjectsCount: 1, + Repairable: { Durability: 47, MaxDurability: 47 }, + Togglable: { On: true }, + }, + parentId: "8ce190fcd2ffe5f1f9ad345a", + slotId: "mod_equipment", + }, + ], + }, + { + scheduledTime: 1712960777.6, + traderId: "54cb50c76803fa8b248b4571", + maxStorageTime: 345600, + systemData: { date: "11.04.2024", time: "19:30", location: "factory4_day" }, + messageType: 8, + messageTemplateId: "58fe0e4586f774728248ca13 4", + items: [ + { + _id: "b29c463afe52421ba72b1816", + _tpl: "5aa7e3abe5b5b000171d064d", + upd: { StackObjectsCount: 1, Repairable: { Durability: 50, MaxDurability: 50 } }, + parentId: "d2b3b859f667d4fd8b35bc96", + slotId: "hideout", + }, + { + _id: "1813e676a1bceefd5424b4bb", + _tpl: "5ac7655e5acfc40016339a19", + parentId: "d2b3b859f667d4fd8b35bc96", + slotId: "hideout", + upd: {}, + }, + { + _id: "a58746a7e98ac16ba9105fc9", + _tpl: "5cf50850d7f00c056e24104c", + parentId: "d2b3b859f667d4fd8b35bc96", + slotId: "hideout", + upd: {}, + }, + { + _id: "70acf65d9944b19d17d92b19", + _tpl: "55d480c04bdc2d1d4e8b456a", + parentId: "d2b3b859f667d4fd8b35bc96", + slotId: "hideout", + upd: {}, + }, + { + _id: "e3a54ae66a2970372eee1888", + _tpl: "602e63fb6335467b0c5ac94d", + parentId: "d2b3b859f667d4fd8b35bc96", + slotId: "hideout", + upd: {}, + }, + { + _id: "a4b1cb12dc5ece274d348e2b", + _tpl: "6033749e88382f4fab3fd2c5", + parentId: "d2b3b859f667d4fd8b35bc96", + slotId: "hideout", + upd: {}, + }, + { + _id: "e3c2162f4001a0d6ed2a199d", + _tpl: "602f85fd9b513876d4338d9c", + parentId: "d2b3b859f667d4fd8b35bc96", + slotId: "hideout", + upd: {}, + }, + { + _id: "548a111c4e48fb058e7a5c09", + _tpl: "603372b4da11d6478d5a07ff", + parentId: "e3a54ae66a2970372eee1888", + slotId: "mod_barrel", + upd: {}, + }, + { + _id: "d58db125fdd3f3b15a9798ca", + _tpl: "602e620f9b513876d4338d9a", + parentId: "d2b3b859f667d4fd8b35bc96", + slotId: "hideout", + upd: {}, + }, + { + _id: "f85ba56791757174e3447c55", + _tpl: "630764fea987397c0816d219", + parentId: "d2b3b859f667d4fd8b35bc96", + slotId: "hideout", + upd: {}, + }, + { + _id: "e3c409642a067f980ca168b7", + _tpl: "63075cc5962d0247b029dc2a", + parentId: "d2b3b859f667d4fd8b35bc96", + slotId: "hideout", + upd: {}, + }, + { + _id: "5ff60d8b2b61c9f20ee8e91b", + _tpl: "63076701a987397c0816d21b", + parentId: "d2b3b859f667d4fd8b35bc96", + slotId: "hideout", + upd: {}, + }, + { + _id: "b212acf3c8f09f48b4beaa0d", + _tpl: "5648a69d4bdc2ded0b8b457b", + parentId: "d2b3b859f667d4fd8b35bc96", + slotId: "hideout", + upd: { StackObjectsCount: 1 }, + }, + ], + }, + { + scheduledTime: 1712920104.8, + traderId: "54cb57776803fa99248b456e", + maxStorageTime: 518400, + systemData: { date: "11.04.2024", time: "19:30", location: "factory4_day" }, + messageType: 8, + messageTemplateId: "58fe0e3486f77471f772c3f2 0", + items: [ + { + _id: "203161dde59c5a2fdd362da9", + _tpl: "5aa7e4a4e5b5b000137b76f2", + upd: { StackObjectsCount: 1, sptPresetId: "657fa87fc6679fefb3051e32" }, + parentId: "d2b3b859f667d4fd8b35bc96", + slotId: "hideout", + }, + { + _id: "37c9968cfc4372c968f57c42", + _tpl: "657f925dada5fadd1f07a57a", + parentId: "203161dde59c5a2fdd362da9", + slotId: "Helmet_top", + upd: { Repairable: { Durability: 21, MaxDurability: 21 } }, + }, + { + _id: "5517446f3cd41cf75d3a9cd2", + _tpl: "657f92acada5fadd1f07a57e", + parentId: "203161dde59c5a2fdd362da9", + slotId: "Helmet_back", + upd: { Repairable: { Durability: 21, MaxDurability: 21 } }, + }, + { + _id: "0fdc8f25f7dfc61678cdef01", + _tpl: "657f92e7f4c82973640b2354", + parentId: "203161dde59c5a2fdd362da9", + slotId: "Helmet_ears", + upd: { Repairable: { Durability: 21, MaxDurability: 21 } }, + }, + { + _id: "e2cba41b10edfc595e2bb574", + _tpl: "628b916469015a4e1711ed8d", + parentId: "6c5ef8a5fb3b88641420e9a0", + slotId: "mod_handguard", + upd: {}, + }, + { + _id: "dd3aa187f853187198860933", + _tpl: "628b9be6cff66b70c002b14c", + parentId: "e2cba41b10edfc595e2bb574", + slotId: "mod_reciever", + upd: {}, + }, + { + _id: "13d29ea647b01f0ecb774a54", + _tpl: "628b9471078f94059a4b9bfb", + parentId: "dd3aa187f853187198860933", + slotId: "mod_sight_rear", + upd: {}, + }, + { + _id: "6c5ef8a5fb3b88641420e9a0", + _tpl: "628b8d83717774443b15e248", + parentId: "afcef56bf4fa36d0ec1f4166", + slotId: "mod_gas_block", + upd: {}, + }, + { + _id: "7980e04a92db0858cb7f4bfa", + _tpl: "55d4ae6c4bdc2d8b2f8b456e", + parentId: "929c1577ba7390558c59d8a5", + slotId: "mod_stock", + upd: {}, + }, + { + _id: "929c1577ba7390558c59d8a5", + _tpl: "628b9a40717774443b15e9f2", + parentId: "afcef56bf4fa36d0ec1f4166", + slotId: "mod_stock_000", + upd: {}, + }, + { + _id: "afcef56bf4fa36d0ec1f4166", + _tpl: "628b5638ad252a16da6dd245", + parentId: "d2b3b859f667d4fd8b35bc96", + slotId: "hideout", + upd: { + FireMode: { FireMode: "single" }, + StackObjectsCount: 1, + Repairable: { Durability: 100, MaxDurability: 100 }, + }, + }, + { + _id: "a94905f708670fca5de11e7e", + _tpl: "60339954d62c9b14ed777c06", + parentId: "d2b3b859f667d4fd8b35bc96", + slotId: "hideout", + upd: { + FireMode: { FireMode: "single" }, + StackObjectsCount: 1, + Repairable: { Durability: 100, MaxDurability: 100 }, + }, + }, + { + _id: "8f5ce6d3c7730240c3ae78ad", + _tpl: "602e71bd53a60014f9705bfa", + parentId: "a94905f708670fca5de11e7e", + slotId: "mod_pistol_grip", + upd: {}, + }, + { + _id: "c320122de049da2880d0a235", + _tpl: "5a7ad2e851dfba0016153692", + parentId: "a94905f708670fca5de11e7e", + slotId: "mod_magazine", + upd: {}, + }, + { + _id: "d2923c8984f26f68f01d20d7", + _tpl: "602e3f1254072b51b239f713", + parentId: "a94905f708670fca5de11e7e", + slotId: "mod_stock_001", + upd: {}, + }, + { + _id: "ecd363cddbb5361670d531b0", + _tpl: "60337f5dce399e10262255d1", + parentId: "d2b3b859f667d4fd8b35bc96", + slotId: "hideout", + upd: {}, + }, + { + _id: "704c139d092f1bd3e3d18df2", + _tpl: "6034e3cb0ddce744014cb870", + parentId: "d2b3b859f667d4fd8b35bc96", + slotId: "hideout", + upd: {}, + }, + { + _id: "72bd97cb21996a2282ff7bcd", + _tpl: "630765cb962d0247b029dc45", + parentId: "d2b3b859f667d4fd8b35bc96", + slotId: "hideout", + upd: {}, + }, + { + _id: "44e3df51e01d5b23445fb95f", + _tpl: "630765777d50ff5e8a1ea718", + parentId: "d2b3b859f667d4fd8b35bc96", + slotId: "hideout", + upd: {}, + }, + { + _id: "1cb0900a4bd068b04ca05db1", + _tpl: "63088377b5cd696784087147", + parentId: "d2b3b859f667d4fd8b35bc96", + slotId: "hideout", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + }, + { + _id: "379ca7cd56ebb1434bd89d62", + _tpl: "656f9d5900d62bcd2e02407c", + parentId: "eb3bbc6cb084a53ff48b672d", + slotId: "Front_plate", + upd: { Repairable: { Durability: 32.4841042, MaxDurability: 45 } }, + }, + { + _id: "d700aaa1d7a15644f6b91dc7", + _tpl: "656f9d5900d62bcd2e02407c", + parentId: "eb3bbc6cb084a53ff48b672d", + slotId: "Back_plate", + upd: { Repairable: { Durability: 45, MaxDurability: 45 } }, + }, + { + _id: "eb3bbc6cb084a53ff48b672d", + _tpl: "5b44d22286f774172b0c9de8", + parentId: "d2b3b859f667d4fd8b35bc96", + slotId: "hideout", + upd: { StackObjectsCount: 1 }, + }, + { + _id: "6a3d83c5230d1779060e17a9", + _tpl: "65704de13e7bba58ea0285c8", + parentId: "eb3bbc6cb084a53ff48b672d", + slotId: "Soft_armor_front", + upd: { Repairable: { Durability: 37.4214172, MaxDurability: 56 } }, + }, + { + _id: "9fba54de64b37902dd14b6e5", + _tpl: "65705c3c14f2ed6d7d0b7738", + parentId: "eb3bbc6cb084a53ff48b672d", + slotId: "Soft_armor_back", + upd: { Repairable: { Durability: 49.93156, MaxDurability: 56 } }, + }, + { + _id: "2b534b3af5f240c625a77424", + _tpl: "65705c777260e1139e091408", + parentId: "eb3bbc6cb084a53ff48b672d", + slotId: "Soft_armor_left", + upd: { Repairable: { Durability: 12, MaxDurability: 12 } }, + }, + { + _id: "e046688c9167ceaced5af3a7", + _tpl: "65705cb314f2ed6d7d0b773c", + parentId: "eb3bbc6cb084a53ff48b672d", + slotId: "soft_armor_right", + upd: { Repairable: { Durability: 12, MaxDurability: 12 } }, + }, + { + _id: "6c612d370959e61b6c10b7bf", + _tpl: "65705cea4916448ae1050897", + parentId: "eb3bbc6cb084a53ff48b672d", + slotId: "Collar", + upd: { Repairable: { Durability: 14, MaxDurability: 14 } }, + }, + ], + }, +]; diff --git a/project/tests/__mocks__/WinstonLogger.mock.ts b/project/tests/__mocks__/WinstonLogger.mock.ts index a19c59bf..14c5673a 100644 --- a/project/tests/__mocks__/WinstonLogger.mock.ts +++ b/project/tests/__mocks__/WinstonLogger.mock.ts @@ -3,33 +3,24 @@ import { LogBackgroundColor } from "@spt/models/spt/logging/LogBackgroundColor"; import { LogTextColor } from "@spt/models/spt/logging/LogTextColor"; import { ILogger } from "@spt/models/spt/utils/ILogger"; -export class WinstonLogger implements ILogger -{ - writeToLogFile(data: string | Daum): void - {} +export class WinstonLogger implements ILogger { + writeToLogFile(data: string | Daum): void {} - log(data: string | Record | Error, color: string, backgroundColor?: string): void - {} + log(data: string | Record | Error, color: string, backgroundColor?: string): void {} logWithColor( data: string | Record, textColor: LogTextColor, backgroundColor?: LogBackgroundColor, - ): void - {} + ): void {} - error(data: string): void - {} + error(data: string): void {} - warning(data: string): void - {} + warning(data: string): void {} - success(data: string): void - {} + success(data: string): void {} - info(data: string): void - {} + info(data: string): void {} - debug(data: string | Record, onlyShowInConsole?: boolean): void - {} + debug(data: string | Record, onlyShowInConsole?: boolean): void {} } diff --git a/project/tests/controllers/HealthController.test.ts b/project/tests/controllers/HealthController.test.ts index d7a0841b..df799b67 100644 --- a/project/tests/controllers/HealthController.test.ts +++ b/project/tests/controllers/HealthController.test.ts @@ -1,29 +1,24 @@ import "reflect-metadata"; -import { container } from "tsyringe"; -import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import { HealthController } from "@spt/controllers/HealthController"; import { IPmcData } from "@spt/models/eft/common/IPmcData"; import { IHealthTreatmentRequestData } from "@spt/models/eft/health/IHealthTreatmentRequestData"; +import { container } from "tsyringe"; +import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; -describe("HealthController", () => -{ +describe("HealthController", () => { let healthController: HealthController; // Using "any" to access private/protected methods without type errors. - beforeEach(() => - { + beforeEach(() => { healthController = container.resolve("HealthController"); }); - afterEach(() => - { + afterEach(() => { vi.restoreAllMocks(); }); - describe("healthTreatment", () => - { - it("Should Heal Players heavy bleed and heal chest to full hp", () => - { + describe("healthTreatment", () => { + it("Should Heal Players heavy bleed and heal chest to full hp", () => { const maxHealth = 100; const pmcData = { Health: { @@ -77,8 +72,7 @@ describe("HealthController", () => expect(result.profileChanges[sessionId].health.BodyParts.Chest).not.toHaveProperty("Effects"); }); - it("Should Heal Players heavy bleed and leave limb health at existing value", () => - { + it("Should Heal Players heavy bleed and leave limb health at existing value", () => { const maxHealth = 100; const pmcData = { Health: { @@ -132,8 +126,7 @@ describe("HealthController", () => expect(result.profileChanges[sessionId].health.BodyParts.Chest).toHaveProperty("Effects"); }); - it("Should Heal Players heavy bleed and leave limb health at existing value", () => - { + it("Should Heal Players heavy bleed and leave limb health at existing value", () => { const maxHealth = 100; const currentHealth = 50; const pmcData = { diff --git a/project/tests/controllers/InsuranceController.test.ts b/project/tests/controllers/InsuranceController.test.ts index bf645a33..2b95320e 100644 --- a/project/tests/controllers/InsuranceController.test.ts +++ b/project/tests/controllers/InsuranceController.test.ts @@ -1,40 +1,35 @@ import "reflect-metadata"; -import { container } from "tsyringe"; -import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import { InsuranceController } from "@spt/controllers/InsuranceController"; import { Item } from "@spt/models/eft/common/tables/IItem"; import { Insurance } from "@spt/models/eft/profile/ISptProfile"; import { MessageType } from "@spt/models/enums/MessageType"; import { ProfileInsuranceFactory } from "@tests/__factories__/ProfileInsurance.factory"; +import { container } from "tsyringe"; +import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; -describe("InsuranceController", () => -{ +describe("InsuranceController", () => { let insuranceController: any; // Using "any" to access private/protected methods without type errors. let insuranceFixture: Insurance[]; - beforeEach(() => - { + beforeEach(() => { insuranceController = container.resolve("InsuranceController"); insuranceFixture = new ProfileInsuranceFactory().adjustPackageDates().get(); }); - afterEach(() => - { + afterEach(() => { vi.restoreAllMocks(); }); - describe("processReturn", () => - { - it("should process return for all profiles", () => - { + describe("processReturn", () => { + it("should process return for all profiles", () => { const session1 = "session1"; const session2 = "session2"; const profiles = { [session1]: {}, [session2]: {} }; const getProfilesSpy = vi.spyOn(insuranceController.saveServer, "getProfiles").mockReturnValue(profiles); - const processReturnByProfileSpy = vi.spyOn(insuranceController, "processReturnByProfile").mockReturnValue( - vi.fn(), - ); + const processReturnByProfileSpy = vi + .spyOn(insuranceController, "processReturnByProfile") + .mockReturnValue(vi.fn()); // Execute the method. insuranceController.processReturn(); @@ -48,9 +43,9 @@ describe("InsuranceController", () => expect(processReturnByProfileSpy).toHaveBeenCalledWith(session2); }); - it("should not attempt to process profiles if no profiles exist", () => - { - const processReturnByProfileSpy = vi.spyOn(insuranceController, "processReturnByProfile") + it("should not attempt to process profiles if no profiles exist", () => { + const processReturnByProfileSpy = vi + .spyOn(insuranceController, "processReturnByProfile") .mockImplementation(vi.fn()); // Execute the method. @@ -61,19 +56,17 @@ describe("InsuranceController", () => }); }); - describe("processReturnByProfile", () => - { - it("should process insurance for a profile", () => - { + describe("processReturnByProfile", () => { + it("should process insurance for a profile", () => { const sessionId = "session-id"; // Mock internal methods. - const mockFilterInsuredItems = vi.spyOn(insuranceController, "filterInsuredItems").mockReturnValue( - insuranceFixture, - ); - const mockProcessInsuredItems = vi.spyOn(insuranceController, "processInsuredItems").mockImplementation( - vi.fn(), - ); + const mockFilterInsuredItems = vi + .spyOn(insuranceController, "filterInsuredItems") + .mockReturnValue(insuranceFixture); + const mockProcessInsuredItems = vi + .spyOn(insuranceController, "processInsuredItems") + .mockImplementation(vi.fn()); insuranceController.processReturnByProfile(sessionId); @@ -82,15 +75,14 @@ describe("InsuranceController", () => expect(mockProcessInsuredItems).toHaveBeenNthCalledWith(1, insuranceFixture, sessionId); }); - it("should skip processing if there are no insurance packages found within the profile", () => - { + it("should skip processing if there are no insurance packages found within the profile", () => { const sessionId = "session-id"; // Mock internal methods. const mockFilterInsuredItems = vi.spyOn(insuranceController, "filterInsuredItems").mockReturnValue([]); // Return an empty array. - const mockProcessInsuredItems = vi.spyOn(insuranceController, "processInsuredItems").mockImplementation( - vi.fn(), - ); + const mockProcessInsuredItems = vi + .spyOn(insuranceController, "processInsuredItems") + .mockImplementation(vi.fn()); insuranceController.processReturnByProfile(sessionId); @@ -100,10 +92,8 @@ describe("InsuranceController", () => }); }); - describe("filterInsuredItems", () => - { - it("should return all insurance packages if no time is specified", () => - { + describe("filterInsuredItems", () => { + it("should return all insurance packages if no time is specified", () => { const sessionID = "session-id"; const insured = JSON.parse(JSON.stringify(insuranceFixture)); @@ -122,13 +112,12 @@ describe("InsuranceController", () => expect(insuredFiltered.length).toBe(insuranceFixture.length); }); - it("should filter out insurance packages with scheduledTime values in the future", () => - { + it("should filter out insurance packages with scheduledTime values in the future", () => { const sessionID = "session-id"; const insured = JSON.parse(JSON.stringify(insuranceFixture)); // Set the scheduledTime to 2 hours in the future so it should be skipped over. - insured[0].scheduledTime = Math.floor((Date.now() / 1000) + (2 * 60 * 60)); + insured[0].scheduledTime = Math.floor(Date.now() / 1000 + 2 * 60 * 60); // Mock getProfile to return the fixture. const mockGetProfile = vi.spyOn(insuranceController.saveServer, "getProfile").mockReturnValue({ @@ -145,8 +134,7 @@ describe("InsuranceController", () => expect(insuredFiltered.length).toBe(insuranceFixture.length - 1); // Should be 1 less than the original fixture. }); - it("should return an empty array if no insurance packages match the criteria", () => - { + it("should return an empty array if no insurance packages match the criteria", () => { const sessionID = "session-id"; const insured = JSON.parse(JSON.stringify(insuranceFixture)); @@ -160,7 +148,7 @@ describe("InsuranceController", () => // date as the target to judge if an insurance package is ready to be sent or not. const insuredFiltered = insuranceController.filterInsuredItems( sessionID, - Math.floor((Date.now() / 1000) - (2 * 60 * 60)), + Math.floor(Date.now() / 1000 - 2 * 60 * 60), ); // Verify that the correct methods were called. @@ -172,10 +160,8 @@ describe("InsuranceController", () => }); }); - describe("processInsuredItems", () => - { - it("should log information about the insurance package", () => - { + describe("processInsuredItems", () => { + it("should log information about the insurance package", () => { const sessionId = "session-id"; const numberOfItems = 666; @@ -198,24 +184,24 @@ describe("InsuranceController", () => ); }); - it("should call processing methods once per insurance package", () => - { + it("should call processing methods once per insurance package", () => { const sessionId = "session-id"; const packageCount = insuranceFixture.length; // Spy on the processing methods. - const mockFindItemsToDelete = vi.spyOn(insuranceController, "findItemsToDelete").mockImplementation( - vi.fn(), - ); - const mockRemoveItemsFromInsurance = vi.spyOn(insuranceController, "removeItemsFromInsurance") + const mockFindItemsToDelete = vi + .spyOn(insuranceController, "findItemsToDelete") .mockImplementation(vi.fn()); - const mockAdoptOrphanedItems = vi.spyOn(insuranceController.itemHelper, "adoptOrphanedItems") + const mockRemoveItemsFromInsurance = vi + .spyOn(insuranceController, "removeItemsFromInsurance") + .mockImplementation(vi.fn()); + const mockAdoptOrphanedItems = vi + .spyOn(insuranceController.itemHelper, "adoptOrphanedItems") .mockImplementation(vi.fn()); const mockSendMail = vi.spyOn(insuranceController, "sendMail").mockImplementation(vi.fn()); - const mockRemoveInsurancePackageFromProfile = vi.spyOn( - insuranceController, - "removeInsurancePackageFromProfile", - ).mockImplementation(vi.fn()); + const mockRemoveInsurancePackageFromProfile = vi + .spyOn(insuranceController, "removeInsurancePackageFromProfile") + .mockImplementation(vi.fn()); vi.spyOn(insuranceController.insuranceService.saveServer, "getProfile").mockReturnValue({}); @@ -231,23 +217,31 @@ describe("InsuranceController", () => }); }); - describe("countAllInsuranceItems", () => - { - it("should return the total number of items in all insurance packages", () => - { - const insurance = [{ - _id: "1", - upd: 1234567890, - items: [{ _id: "1", parentId: "1", slotId: "1" }, { _id: "2", parentId: "1", slotId: "2" }], - }, { - _id: "2", - upd: 1234567890, - items: [{ _id: "3", parentId: "2", slotId: "1" }, { _id: "4", parentId: "2", slotId: "2" }, { - _id: "5", - parentId: "2", - slotId: "3", - }], - }]; + describe("countAllInsuranceItems", () => { + it("should return the total number of items in all insurance packages", () => { + const insurance = [ + { + _id: "1", + upd: 1234567890, + items: [ + { _id: "1", parentId: "1", slotId: "1" }, + { _id: "2", parentId: "1", slotId: "2" }, + ], + }, + { + _id: "2", + upd: 1234567890, + items: [ + { _id: "3", parentId: "2", slotId: "1" }, + { _id: "4", parentId: "2", slotId: "2" }, + { + _id: "5", + parentId: "2", + slotId: "3", + }, + ], + }, + ]; const expectedCount = 5; // 2 items in the first package + 3 items in the second package. // Execute the method. @@ -257,8 +251,7 @@ describe("InsuranceController", () => expect(actualCount).toBe(expectedCount); }); - it("should return 0 if there are no insurance packages", () => - { + it("should return 0 if there are no insurance packages", () => { const insurance = []; const expectedCount = 0; @@ -269,9 +262,11 @@ describe("InsuranceController", () => expect(actualCount).toBe(expectedCount); }); - it("should return 0 if there are no items in any of the insurance packages", () => - { - const insurance = [{ _id: "1", upd: 1234567890, items: [] }, { _id: "2", upd: 1234567890, items: [] }]; + it("should return 0 if there are no items in any of the insurance packages", () => { + const insurance = [ + { _id: "1", upd: 1234567890, items: [] }, + { _id: "2", upd: 1234567890, items: [] }, + ]; const expectedCount = 0; // Execute the method. @@ -282,23 +277,24 @@ describe("InsuranceController", () => }); }); - describe("removeInsurancePackageFromProfile", () => - { - it("should remove the specified insurance package from the profile", () => - { + describe("removeInsurancePackageFromProfile", () => { + it("should remove the specified insurance package from the profile", () => { const sessionID = "session-id"; const packageToRemove = { traderId: "54cb50c76803fa8b248b4571", systemData: { date: "01.11.2023", time: "11:18", location: "factory4_day" }, }; const profile = { - insurance: [{ - traderId: "54cb50c76803fa8b248b4571", - systemData: { date: "01.11.2023", time: "11:18", location: "factory4_day" }, - }, { - traderId: "54cb57776803fa99248b456e", - systemData: { date: "01.11.2023", time: "10:51", location: "factory4_day" }, - }], + insurance: [ + { + traderId: "54cb50c76803fa8b248b4571", + systemData: { date: "01.11.2023", time: "11:18", location: "factory4_day" }, + }, + { + traderId: "54cb57776803fa99248b456e", + systemData: { date: "01.11.2023", time: "10:51", location: "factory4_day" }, + }, + ], }; // Mock the getProfile method to return the above profile. @@ -309,24 +305,27 @@ describe("InsuranceController", () => // Verify that the specified insurance package was removed. expect(profile.insurance.length).toBe(1); - expect(profile.insurance).toStrictEqual([{ - traderId: "54cb57776803fa99248b456e", - systemData: { date: "01.11.2023", time: "10:51", location: "factory4_day" }, - }]); + expect(profile.insurance).toStrictEqual([ + { + traderId: "54cb57776803fa99248b456e", + systemData: { date: "01.11.2023", time: "10:51", location: "factory4_day" }, + }, + ]); }); - it("should log a message indicating that the package was removed", () => - { + it("should log a message indicating that the package was removed", () => { const sessionID = "session-id"; const packageToRemove = { traderId: "54cb50c76803fa8b248b4571", systemData: { date: "01.11.2023", time: "11:18", location: "factory4_day" }, }; const profile = { - insurance: [{ - traderId: "54cb50c76803fa8b248b4571", - systemData: { date: "01.11.2023", time: "11:18", location: "factory4_day" }, - }], + insurance: [ + { + traderId: "54cb50c76803fa8b248b4571", + systemData: { date: "01.11.2023", time: "11:18", location: "factory4_day" }, + }, + ], }; // Mock the getProfile method to return the above profile. @@ -344,21 +343,23 @@ describe("InsuranceController", () => ); }); - it("should not remove any packages if the specified package is not found", () => - { + it("should not remove any packages if the specified package is not found", () => { const sessionID = "session-id"; const packageToRemove = { traderId: "54cb50c76803fa8b248b4571", systemData: { date: "01.11.2023", time: "11:25", location: "factory4_day" }, }; const profile = { - insurance: [{ - traderId: "54cb50c76803fa8b248b4571", - systemData: { date: "01.11.2023", time: "11:18", location: "factory4_day" }, - }, { - traderId: "54cb57776803fa99248b456e", - systemData: { date: "01.11.2023", time: "10:51", location: "factory4_day" }, - }], + insurance: [ + { + traderId: "54cb50c76803fa8b248b4571", + systemData: { date: "01.11.2023", time: "11:18", location: "factory4_day" }, + }, + { + traderId: "54cb57776803fa99248b456e", + systemData: { date: "01.11.2023", time: "10:51", location: "factory4_day" }, + }, + ], }; // Mock the getProfile method to return the above profile. @@ -372,10 +373,8 @@ describe("InsuranceController", () => }); }); - describe("findItemsToDelete", () => - { - it("should handle an empty insurance package", () => - { + describe("findItemsToDelete", () => { + it("should handle an empty insurance package", () => { const insurancePackage = insuranceFixture[0]; insurancePackage.items = []; @@ -389,8 +388,7 @@ describe("InsuranceController", () => expect(result.size).toBe(0); }); - it("should handle regular items", () => - { + it("should handle regular items", () => { // Remove attachment items from the fixture. insuranceFixture = new ProfileInsuranceFactory().adjustPackageDates().removeAttachmentItems().get(); const insured = insuranceFixture[0]; @@ -399,15 +397,13 @@ describe("InsuranceController", () => // Mock helper methods. const mockPopulateParentAttachmentsMap = vi.spyOn(insuranceController, "populateParentAttachmentsMap"); const mockIsAttachmentAttached = vi.spyOn(insuranceController.itemHelper, "isAttachmentAttached"); - const mockProcessAttachments = vi.spyOn(insuranceController, "processAttachments").mockImplementation( - vi.fn(), - ); + const mockProcessAttachments = vi + .spyOn(insuranceController, "processAttachments") + .mockImplementation(vi.fn()); // Add all items to the toDelete set. Not realistic, but it's fine for this test. - const mockProcessRegularItems = vi.fn((insured, toDelete) => - { - for (const item of insured.items) - { + const mockProcessRegularItems = vi.fn((insured, toDelete) => { + for (const item of insured.items) { toDelete.add(item._id); } }); @@ -427,8 +423,7 @@ describe("InsuranceController", () => expect(result).toEqual(new Set(insured.items.map((item) => item._id))); }); - it("should ignore orphaned attachments", () => - { + it("should ignore orphaned attachments", () => { // Remove regular items from the fixture, creating orphaned attachments. insuranceFixture = new ProfileInsuranceFactory().adjustPackageDates().removeRegularItems().get(); const insured = insuranceFixture[0]; @@ -438,8 +433,7 @@ describe("InsuranceController", () => const mockProcessAttachments = vi.spyOn(insuranceController, "processAttachments"); // Since no parent attachments exist, the map should be empty. - const mockPopulateParentAttachmentsMap = vi.fn(() => - { + const mockPopulateParentAttachmentsMap = vi.fn(() => { return new Map(); }); vi.spyOn(insuranceController, "populateParentAttachmentsMap").mockImplementation( @@ -459,8 +453,7 @@ describe("InsuranceController", () => expect(result).toEqual(new Set()); }); - it("should handle a mix of regular items and attachments", () => - { + it("should handle a mix of regular items and attachments", () => { const insured = insuranceFixture[0]; const numberOfItems = insured.items.length; @@ -468,18 +461,14 @@ describe("InsuranceController", () => const mockPopulateParentAttachmentsMap = vi.spyOn(insuranceController, "populateParentAttachmentsMap"); // Add all items to the toDelete set. Not realistic, but it's fine for this test. - const mockProcessRegularItems = vi.fn((insured, toDelete) => - { - for (const item of insured.items) - { + const mockProcessRegularItems = vi.fn((insured, toDelete) => { + for (const item of insured.items) { toDelete.add(item._id); } }); vi.spyOn(insuranceController, "processRegularItems").mockImplementation(mockProcessRegularItems); - const mockProcessAttachments = vi.fn((parentAttachmentsMap, itemsMap, traderId, toDelete) => - { - for (const item of insured.items) - { + const mockProcessAttachments = vi.fn((parentAttachmentsMap, itemsMap, traderId, toDelete) => { + for (const item of insured.items) { toDelete.add(item._id); } }); @@ -498,20 +487,19 @@ describe("InsuranceController", () => expect(result).toEqual(new Set(insured.items.map((item) => item._id))); }); - it("should return an empty set if no items are to be deleted", () => - { + it("should return an empty set if no items are to be deleted", () => { const insured = insuranceFixture[0]; // Mock helper methods. const mockPopulateParentAttachmentsMap = vi.spyOn(insuranceController, "populateParentAttachmentsMap"); // Don't add any items to the toDelete set. - const mockProcessRegularItems = vi.spyOn(insuranceController, "processRegularItems").mockImplementation( - vi.fn(), - ); - const mockProcessAttachments = vi.spyOn(insuranceController, "processAttachments").mockImplementation( - vi.fn(), - ); + const mockProcessRegularItems = vi + .spyOn(insuranceController, "processRegularItems") + .mockImplementation(vi.fn()); + const mockProcessAttachments = vi + .spyOn(insuranceController, "processAttachments") + .mockImplementation(vi.fn()); // Execute the method. const result = insuranceController.findItemsToDelete(insuranceController.hashUtil.generate(), insured); @@ -526,8 +514,7 @@ describe("InsuranceController", () => expect(result).toEqual(new Set()); }); - it("should log the number of items to be deleted", () => - { + it("should log the number of items to be deleted", () => { const insured = insuranceFixture[0]; const numberOfItems = insured.items.length; @@ -535,18 +522,14 @@ describe("InsuranceController", () => const mockLoggerDebug = vi.spyOn(insuranceController.logger, "debug"); // Add all items to the toDelete set. Not realistic, but it's fine for this test. - const mockProcessRegularItems = vi.fn((insured, toDelete) => - { - for (const item of insured.items) - { + const mockProcessRegularItems = vi.fn((insured, toDelete) => { + for (const item of insured.items) { toDelete.add(item._id); } }); vi.spyOn(insuranceController, "processRegularItems").mockImplementation(mockProcessRegularItems); - const mockProcessAttachments = vi.fn((parentAttachmentsMap, itemsMap, traderId, toDelete) => - { - for (const item of insured.items) - { + const mockProcessAttachments = vi.fn((parentAttachmentsMap, itemsMap, traderId, toDelete) => { + for (const item of insured.items) { toDelete.add(item._id); } }); @@ -561,10 +544,8 @@ describe("InsuranceController", () => }); }); - describe("populateParentAttachmentsMap", () => - { - it("should correctly map gun to all of its attachments", () => - { + describe("populateParentAttachmentsMap", () => { + it("should correctly map gun to all of its attachments", () => { const insured = insuranceFixture[0]; // Generate the items map. @@ -617,15 +598,13 @@ describe("InsuranceController", () => "5dbcf8cbbb3f8ef669836320", "f996645c809968f8033593a6", ]; - for (const value of validAttachmentTemplates) - { + for (const value of validAttachmentTemplates) { // Verify that each template is present in the array of attachments. expect(gun.some((item) => item._id === value)).toBe(true); } }); - it("should correctly map helmet to all of its attachments", () => - { + it("should correctly map helmet to all of its attachments", () => { const insured = insuranceFixture[0]; // Generate the items map. @@ -651,15 +630,13 @@ describe("InsuranceController", () => "f7066fdfeefb29eca1d2dbeb", "ee0ec86e9608abe773175e3a", ]; - for (const value of validAttachmentTemplates) - { + for (const value of validAttachmentTemplates) { // Verify that each template is present in the array of attachments. expect(helmet.some((item) => item._id === value)).toBe(true); } }); - it("should correctly map gun to all of its attachments when gun is within a container", () => - { + it("should correctly map gun to all of its attachments when gun is within a container", () => { const insured = insuranceFixture[0]; // Generate the items map. @@ -680,8 +657,7 @@ describe("InsuranceController", () => expect(gun.length).toBe(3); }); - it("should not map items that do not have a main-parent", () => - { + it("should not map items that do not have a main-parent", () => { // Remove regular items from the fixture. insuranceFixture = new ProfileInsuranceFactory().adjustPackageDates().removeRegularItems().get(); const insured = insuranceFixture[0]; @@ -703,8 +679,7 @@ describe("InsuranceController", () => expect(result.size).toBe(0); }); - it("should log a warning when an item does not have a main-parent", () => - { + it("should log a warning when an item does not have a main-parent", () => { // Remove regular items from the fixture. insuranceFixture = new ProfileInsuranceFactory().adjustPackageDates().removeRegularItems().get(); const insured = insuranceFixture[0]; @@ -727,10 +702,8 @@ describe("InsuranceController", () => }); }); - describe("removeNonModdableAttachments", () => - { - it("should return a Map where each parent item ID is mapped to only moddable attachments", () => - { + describe("removeNonModdableAttachments", () => { + it("should return a Map where each parent item ID is mapped to only moddable attachments", () => { const insured = insuranceFixture[0]; const itemsMap = insuranceController.itemHelper.generateItemsMap(insured.items); const parentAttachmentsMap = insuranceController.populateParentAttachmentsMap( @@ -743,10 +716,8 @@ describe("InsuranceController", () => const result = insuranceController.removeNonModdableAttachments(parentAttachmentsMap, itemsMap); // Verify that the map is populated correctly. - for (const [parentId, attachments] of result) - { - for (const attachment of attachments) - { + for (const [parentId, attachments] of result) { + for (const attachment of attachments) { // Verify that each attachment is moddable. const attachmentParentItem = itemsMap.get(parentId); expect(insuranceController.itemHelper.isRaidModdable(attachment, attachmentParentItem)).toBe(true); @@ -754,8 +725,7 @@ describe("InsuranceController", () => } }); - it("should remove parents that do not have any moddable attachments", () => - { + it("should remove parents that do not have any moddable attachments", () => { const insured = insuranceFixture[0]; const itemsMap = insuranceController.itemHelper.generateItemsMap(insured.items); const parentAttachmentsMap = insuranceController.populateParentAttachmentsMap( @@ -775,10 +745,8 @@ describe("InsuranceController", () => }); }); - describe("processRegularItems", () => - { - it("should process regular items and their non-attachment children", () => - { + describe("processRegularItems", () => { + it("should process regular items and their non-attachment children", () => { // Remove attachment items from the fixture. insuranceFixture = new ProfileInsuranceFactory().adjustPackageDates().removeAttachmentItems().get(); @@ -814,8 +782,7 @@ describe("InsuranceController", () => expect(toDelete).toEqual(new Set(insured.items.map((item) => item._id))); }); - it("should not roll attached attachments", () => - { + it("should not roll attached attachments", () => { const insured = insuranceFixture[0]; const toDelete = new Set(); const itemsMap = insuranceController.itemHelper.generateItemsMap(insured.items); @@ -841,8 +808,7 @@ describe("InsuranceController", () => expect(toDelete).toEqual(new Set()); }); - it("should mark attachments for deletion when parent is marked for deletion", () => - { + it("should mark attachments for deletion when parent is marked for deletion", () => { const insured = insuranceFixture[0]; const toDelete = new Set(); const itemsMap = insuranceController.itemHelper.generateItemsMap(insured.items); @@ -853,8 +819,7 @@ describe("InsuranceController", () => ); // Mock rollForDelete to return true for all base-parent items. - const mockRollForDelete = vi.fn((traderId, insuredItem) => - { + const mockRollForDelete = vi.fn((traderId, insuredItem) => { return !insuranceController.itemHelper.isAttachmentAttached(insuredItem); }); vi.spyOn(insuranceController, "rollForDelete").mockImplementation(mockRollForDelete); @@ -867,10 +832,8 @@ describe("InsuranceController", () => }); }); - describe("processAttachments", () => - { - it("should iterate over each parent item", () => - { + describe("processAttachments", () => { + it("should iterate over each parent item", () => { const insured = insuranceFixture[0]; const toDelete = new Set(); const itemsMap = insuranceController.itemHelper.generateItemsMap(insured.items); @@ -890,8 +853,7 @@ describe("InsuranceController", () => expect(mockProcessAttachmentByParent).toHaveBeenCalledTimes(parentAttachmentsMap.size); }); - it("should log the name of each parent item", () => - { + it("should log the name of each parent item", () => { const insured = insuranceFixture[0]; const toDelete = new Set(); const itemsMap = insuranceController.itemHelper.generateItemsMap(insured.items); @@ -911,24 +873,20 @@ describe("InsuranceController", () => insuranceController.processAttachments(parentAttachmentsMap, itemsMap, insured.traderId, toDelete); // Verify that the name of each parent item is logged. - for (const [parentId] of parentAttachmentsMap) - { + for (const [parentId] of parentAttachmentsMap) { const parentItem = itemsMap.get(parentId); - if (parentItem) - { - const expectedMessage = `Processing attachments of parent "${ - insuranceController.itemHelper.getItemName(parentItem._tpl) - }":`; + if (parentItem) { + const expectedMessage = `Processing attachments of parent "${insuranceController.itemHelper.getItemName( + parentItem._tpl, + )}":`; expect(mockLoggerDebug).toHaveBeenCalledWith(expectedMessage); } } }); }); - describe("processAttachmentByParent", () => - { - it("should handle weighing and counting of attachments by calling helper methods", () => - { + describe("processAttachmentByParent", () => { + it("should handle weighing and counting of attachments by calling helper methods", () => { const insured = insuranceFixture[0]; const itemsMap = insuranceController.itemHelper.generateItemsMap(insured.items); const parentAttachmentsMap = insuranceController.populateParentAttachmentsMap( @@ -941,7 +899,8 @@ describe("InsuranceController", () => // Mock helper methods. const weightAttachmentsByPrice = vi.spyOn(insuranceController, "weightAttachmentsByPrice"); - const getAttachmentCountToRemove = vi.spyOn(insuranceController, "getAttachmentCountToRemove") + const getAttachmentCountToRemove = vi + .spyOn(insuranceController, "getAttachmentCountToRemove") .mockReturnValue(4); const logAttachmentsBeingRemoved = vi.spyOn(insuranceController, "logAttachmentsBeingRemoved"); @@ -955,10 +914,8 @@ describe("InsuranceController", () => }); }); - describe("getAttachmentCountToRemove", () => - { - it("should handle returning a count of attachments that should be removed that is below the total attachment count", () => - { + describe("getAttachmentCountToRemove", () => { + it("should handle returning a count of attachments that should be removed that is below the total attachment count", () => { const insured = insuranceFixture[0]; const itemsMap = insuranceController.itemHelper.generateItemsMap(insured.items); const parentAttachmentsMap = insuranceController.populateParentAttachmentsMap( @@ -974,8 +931,7 @@ describe("InsuranceController", () => expect(result).lessThanOrEqual(attachmentCount); }); - it("should handle returning 0 when chanceNoAttachmentsTakenPercent is 100%", () => - { + it("should handle returning 0 when chanceNoAttachmentsTakenPercent is 100%", () => { const insured = insuranceFixture[0]; const itemsMap = insuranceController.itemHelper.generateItemsMap(insured.items); const parentAttachmentsMap = insuranceController.populateParentAttachmentsMap( @@ -991,8 +947,7 @@ describe("InsuranceController", () => expect(result).toBe(0); }); - it("should handle returning 0 when all attachments are below configured threshold price", () => - { + it("should handle returning 0 when all attachments are below configured threshold price", () => { const insured = insuranceFixture[0]; const itemsMap = insuranceController.itemHelper.generateItemsMap(insured.items); const parentAttachmentsMap = insuranceController.populateParentAttachmentsMap( @@ -1011,10 +966,8 @@ describe("InsuranceController", () => }); }); - describe("weightAttachmentsByPrice", () => - { - it("Should create a dictionary of 2 items with weights of 1 for each", () => - { + describe("weightAttachmentsByPrice", () => { + it("Should create a dictionary of 2 items with weights of 1 for each", () => { const insured = insuranceFixture[0]; const itemsMap = insuranceController.itemHelper.generateItemsMap(insured.items); const parentAttachmentsMap = insuranceController.populateParentAttachmentsMap( @@ -1032,16 +985,13 @@ describe("InsuranceController", () => }); }); - describe("removeItemsFromInsurance", () => - { - it("should remove items from insurance based on the toDelete set", () => - { + describe("removeItemsFromInsurance", () => { + it("should remove items from insurance based on the toDelete set", () => { const insured = insuranceFixture[0]; const toDelete = new Set(); const numberToDelete = 2; - for (let i = 0; i < numberToDelete; i++) - { + for (let i = 0; i < numberToDelete; i++) { toDelete.add(insured.items[i]._id); } @@ -1049,14 +999,12 @@ describe("InsuranceController", () => insuranceController.removeItemsFromInsurance(insured, toDelete); // Ensure that the items in the toDelete set are not present in the insured items array. - for (const toDeleteId of toDelete) - { + for (const toDeleteId of toDelete) { expect(insured.items.some((item) => item._id === toDeleteId)).toBe(false); } }); - it("should not remove any items if toDelete set is empty", () => - { + it("should not remove any items if toDelete set is empty", () => { const insured = insuranceFixture[0]; const originalCount = insured.items.length; const toDelete = new Set(); @@ -1068,13 +1016,11 @@ describe("InsuranceController", () => expect(insured.items.length).toBe(originalCount); }); - it("should leave the insurance items empty if all are to be deleted", () => - { + it("should leave the insurance items empty if all are to be deleted", () => { const insured = insuranceFixture[0]; const originalCount = insured.items.length; const toDelete = new Set(); - for (const item of insured.items) - { + for (const item of insured.items) { toDelete.add(item._id); } @@ -1089,22 +1035,21 @@ describe("InsuranceController", () => }); }); - describe("sendMail", () => - { - it("should send insurance failed message when no items are present", () => - { + describe("sendMail", () => { + it("should send insurance failed message when no items are present", () => { const insurance = insuranceFixture[0]; insurance.items = []; // Empty the items array const sessionID = "session-id"; const insuranceFailedTpl = "failed-message-template"; // Mock the randomUtil to return a static failed template string. - const mockGetArrayValue = vi.spyOn(insuranceController.randomUtil, "getArrayValue").mockReturnValue( - insuranceFailedTpl, - ); + const mockGetArrayValue = vi + .spyOn(insuranceController.randomUtil, "getArrayValue") + .mockReturnValue(insuranceFailedTpl); // Don't actually send the message. - const sendMessageSpy = vi.spyOn(insuranceController.mailSendService, "sendLocalisedNpcMessageToPlayer") + const sendMessageSpy = vi + .spyOn(insuranceController.mailSendService, "sendLocalisedNpcMessageToPlayer") .mockImplementation(vi.fn()); // Execute the method. @@ -1125,19 +1070,19 @@ describe("InsuranceController", () => ); }); - it("should not send insurance failed message when items are present", () => - { + it("should not send insurance failed message when items are present", () => { const insurance = insuranceFixture[0]; const sessionID = "session-id"; const insuranceFailedTpl = "failed-message-template"; // Mock the randomUtil to return a static failed template string. - const mockGetArrayValue = vi.spyOn(insuranceController.randomUtil, "getArrayValue").mockReturnValue( - insuranceFailedTpl, - ); + const mockGetArrayValue = vi + .spyOn(insuranceController.randomUtil, "getArrayValue") + .mockReturnValue(insuranceFailedTpl); // Don't actually send the message. - const sendMessageSpy = vi.spyOn(insuranceController.mailSendService, "sendLocalisedNpcMessageToPlayer") + const sendMessageSpy = vi + .spyOn(insuranceController.mailSendService, "sendLocalisedNpcMessageToPlayer") .mockImplementation(vi.fn()); // Execute the method. @@ -1159,10 +1104,8 @@ describe("InsuranceController", () => }); }); - describe("rollForDelete", () => - { - it("should return true when random roll is equal to trader return chance", () => - { + describe("rollForDelete", () => { + it("should return true when random roll is equal to trader return chance", () => { vi.spyOn(insuranceController.randomUtil, "getInt").mockReturnValue(8500); // Our "random" roll. const traderId = "54cb57776803fa99248b456e"; // Therapist (85% return chance) insuranceController.insuranceConfig = { @@ -1178,8 +1121,7 @@ describe("InsuranceController", () => expect(result).toBe(true); }); - it("should return true when random roll is greater than trader return chance", () => - { + it("should return true when random roll is greater than trader return chance", () => { vi.spyOn(insuranceController.randomUtil, "getInt").mockReturnValue(8501); // Our "random" roll. const traderId = "54cb57776803fa99248b456e"; // Therapist (85% return chance) insuranceController.insuranceConfig = { @@ -1195,8 +1137,7 @@ describe("InsuranceController", () => expect(result).toBe(true); }); - it("should return false when random roll is less than trader return chance", () => - { + it("should return false when random roll is less than trader return chance", () => { vi.spyOn(insuranceController.randomUtil, "getInt").mockReturnValue(8499); // Our "random" roll. const traderId = "54cb57776803fa99248b456e"; // Therapist (85% return chance) insuranceController.insuranceConfig = { @@ -1212,8 +1153,7 @@ describe("InsuranceController", () => expect(result).toBe(false); }); - it("should log error if trader can not be found", () => - { + it("should log error if trader can not be found", () => { const traderId = "invalid-trader-id"; const loggerErrorSpy = vi.spyOn(insuranceController.logger, "error"); @@ -1225,8 +1165,7 @@ describe("InsuranceController", () => expect(loggerErrorSpy).toHaveBeenCalled(); }); - it("should return null if trader can not be found", () => - { + it("should return null if trader can not be found", () => { const traderId = "invalid-trader-id"; // Execute the method. @@ -1237,8 +1176,7 @@ describe("InsuranceController", () => }); }); - describe("insure", () => - { + describe("insure", () => { let pmcData: any; let body: any; let sessionId: string; @@ -1247,20 +1185,26 @@ describe("InsuranceController", () => let mockPayMoney: any; let mockGetOutput: any; - beforeEach(() => - { + beforeEach(() => { insuranceController = container.resolve("InsuranceController"); // Setup shared test data. pmcData = { - Inventory: { items: [{ _id: "item1", otherProps: "value1" }, { _id: "item2", otherProps: "value2" }] }, + Inventory: { + items: [ + { _id: "item1", otherProps: "value1" }, + { _id: "item2", otherProps: "value2" }, + ], + }, InsuredItems: [], }; body = { items: ["item1", "item2"], tid: "someTraderId" }; sessionId = "session-id"; // Setup shared mocks. - mockGetRoublePriceToInsureItemWithTrader = vi.spyOn(insuranceController.insuranceService, "getRoublePriceToInsureItemWithTrader").mockReturnValue(100); + mockGetRoublePriceToInsureItemWithTrader = vi + .spyOn(insuranceController.insuranceService, "getRoublePriceToInsureItemWithTrader") + .mockReturnValue(100); mockPayMoney = vi.spyOn(insuranceController.paymentService, "payMoney").mockReturnValue({ warnings: [], otherProperty: "property-value", @@ -1271,8 +1215,7 @@ describe("InsuranceController", () => }); }); - it("should create a hash of inventory items by ID", () => - { + it("should create a hash of inventory items by ID", () => { // Execute the method. insuranceController.insure(pmcData, body, sessionId); @@ -1281,10 +1224,13 @@ describe("InsuranceController", () => expect(mockPayMoney).toHaveBeenCalledWith( pmcData, { - scheme_items: [{ id: "5449016a4bdc2d6f028b456f", count: 100 }, { - id: "5449016a4bdc2d6f028b456f", - count: 100, - }], + scheme_items: [ + { id: "5449016a4bdc2d6f028b456f", count: 100 }, + { + id: "5449016a4bdc2d6f028b456f", + count: 100, + }, + ], tid: "someTraderId", Action: "SptInsure", type: "", @@ -1297,14 +1243,12 @@ describe("InsuranceController", () => ); }); - it("should calculate the insurance premium for each item to insure", () => - { + it("should calculate the insurance premium for each item to insure", () => { // Execute the method. insuranceController.insure(pmcData, body, sessionId); // Verify that getRoublePriceToInsureItemWithTrader is called with each item from the pmcData.Inventory.items array. - for (const item of pmcData.Inventory.items) - { + for (const item of pmcData.Inventory.items) { expect(mockGetRoublePriceToInsureItemWithTrader).toHaveBeenCalledWith(pmcData, item, body.tid); } @@ -1312,17 +1256,19 @@ describe("InsuranceController", () => expect(mockGetRoublePriceToInsureItemWithTrader).toHaveBeenCalledTimes(body.items.length); }); - it("should call the payment service with the correct parameters", () => - { + it("should call the payment service with the correct parameters", () => { // Execute the method. insuranceController.insure(pmcData, body, sessionId); // Define the expected payment options structure based on the setup data. const expectedPaymentOptions = { - scheme_items: [{ id: "5449016a4bdc2d6f028b456f", count: 100 }, { - id: "5449016a4bdc2d6f028b456f", - count: 100, - }], + scheme_items: [ + { id: "5449016a4bdc2d6f028b456f", count: 100 }, + { + id: "5449016a4bdc2d6f028b456f", + count: 100, + }, + ], tid: body.tid, Action: "SptInsure", type: "", @@ -1343,8 +1289,7 @@ describe("InsuranceController", () => ); }); - it("should add items to InsuredItems after successful payment", () => - { + it("should add items to InsuredItems after successful payment", () => { // Execute the method. insuranceController.insure(pmcData, body, sessionId); @@ -1357,15 +1302,13 @@ describe("InsuranceController", () => expect(pmcData.InsuredItems.length).toBe(body.items.length); }); - it("should update output with warnings if payment fails", () => - { + it("should update output with warnings if payment fails", () => { // Override the payMoney mock to simulate a payment failure with a warning. const expectedPayMoneyReturn = { warnings: [{ index: 0, errmsg: "You broke.", code: 500 }], otherProperty: "property-value", }; - mockPayMoney.mockImplementation((pmcData, request, sessionID, output) => - { + mockPayMoney.mockImplementation((pmcData, request, sessionID, output) => { output.warnings = expectedPayMoneyReturn.warnings; }); @@ -1379,15 +1322,13 @@ describe("InsuranceController", () => expect(response).toHaveProperty("otherProperty", "property-value"); }); - it("should not add items to InsuredItems if payment fails", () => - { + it("should not add items to InsuredItems if payment fails", () => { // Override the payMoney mock to simulate a payment failure with a warning. const expectedPayMoneyReturn = { warnings: [{ index: 0, errmsg: "You broke.", code: 500 }], otherProperty: "property-value", }; - mockPayMoney.mockImplementation((pmcData, request, sessionID, output) => - { + mockPayMoney.mockImplementation((pmcData, request, sessionID, output) => { output.warnings = expectedPayMoneyReturn.warnings; }); @@ -1399,29 +1340,30 @@ describe("InsuranceController", () => }); }); - describe("cost", () => - { + describe("cost", () => { let sessionId: string; - beforeEach(() => - { + beforeEach(() => { insuranceController = container.resolve("InsuranceController"); sessionId = "session-id"; vi.spyOn(insuranceController.profileHelper, "getPmcProfile").mockReturnValue({ Inventory: { - items: [{ _id: "itemId1", _tpl: "itemTpl1", otherProperty: "property-value1" }, { - _id: "itemId2", - _tpl: "itemTpl2", - otherProperty: "property-value2", - }, { _id: "itemId3", _tpl: "itemTpl3", otherProperty: "property-value3" }], + items: [ + { _id: "itemId1", _tpl: "itemTpl1", otherProperty: "property-value1" }, + { + _id: "itemId2", + _tpl: "itemTpl2", + otherProperty: "property-value2", + }, + { _id: "itemId3", _tpl: "itemTpl3", otherProperty: "property-value3" }, + ], }, }); }); - it("should return an empty object if no traders and items are specified", () => - { + it("should return an empty object if no traders and items are specified", () => { const request = { traders: [], items: [] }; const expected = {}; @@ -1430,8 +1372,7 @@ describe("InsuranceController", () => expect(result).toEqual(expected); }); - it("should return an empty object if no items are specified", () => - { + it("should return an empty object if no items are specified", () => { const request = { traders: ["prapor"], items: [] }; const expected = { prapor: {} }; @@ -1440,8 +1381,7 @@ describe("InsuranceController", () => expect(result).toEqual(expected); }); - it("should return an empty object if no trader is specified but items are", () => - { + it("should return an empty object if no trader is specified but items are", () => { const request = { traders: [], items: ["itemId1", "itemId2"] }; const expected = {}; @@ -1450,8 +1390,7 @@ describe("InsuranceController", () => expect(result).toEqual(expected); }); - it("should return the expected cost for each item and trader", () => - { + it("should return the expected cost for each item and trader", () => { const request = { traders: ["prapor", "therapist"], items: ["itemId1", "itemId2", "itemId3"] }; const expected = { prapor: { itemTpl1: 100, itemTpl2: 200, itemTpl3: 300 }, @@ -1459,17 +1398,20 @@ describe("InsuranceController", () => }; // Mock the InsuranceService.getRoublePriceToInsureItemWithTrader method to return the expected values. - vi.spyOn(insuranceController.insuranceService, "getRoublePriceToInsureItemWithTrader").mockReturnValueOnce(100).mockReturnValueOnce( - 200, - ).mockReturnValueOnce(300).mockReturnValueOnce(150).mockReturnValueOnce(250).mockReturnValueOnce(350); + vi.spyOn(insuranceController.insuranceService, "getRoublePriceToInsureItemWithTrader") + .mockReturnValueOnce(100) + .mockReturnValueOnce(200) + .mockReturnValueOnce(300) + .mockReturnValueOnce(150) + .mockReturnValueOnce(250) + .mockReturnValueOnce(350); const result = insuranceController.cost(request, sessionId); expect(result).toEqual(expected); }); - it("should skip items that are not in the player's inventory", () => - { + it("should skip items that are not in the player's inventory", () => { const request = { traders: ["prapor"], items: [ @@ -1481,9 +1423,9 @@ describe("InsuranceController", () => const expected = { prapor: { itemTpl1: 100, itemTpl2: 200 } }; // Mock the InsuranceService.getRoublePriceToInsureItemWithTrader method to return the expected values. - vi.spyOn(insuranceController.insuranceService, "getRoublePriceToInsureItemWithTrader").mockReturnValueOnce(100).mockReturnValueOnce( - 200, - ); + vi.spyOn(insuranceController.insuranceService, "getRoublePriceToInsureItemWithTrader") + .mockReturnValueOnce(100) + .mockReturnValueOnce(200); const result = insuranceController.cost(request, sessionId); diff --git a/project/tests/generators/BotGenerator.test.ts b/project/tests/generators/BotGenerator.test.ts index 6ef378da..26f43809 100644 --- a/project/tests/generators/BotGenerator.test.ts +++ b/project/tests/generators/BotGenerator.test.ts @@ -1,20 +1,17 @@ import "reflect-metadata"; -import { container } from "tsyringe"; -import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import { BotGenerator } from "@spt/generators/BotGenerator"; import { IPmcData } from "@spt/models/eft/common/IPmcData"; +import { container } from "tsyringe"; +import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; -describe("BotGenerator", () => -{ +describe("BotGenerator", () => { let botGenerator: any; - beforeEach(() => - { + beforeEach(() => { botGenerator = container.resolve("BotGenerator"); }); - afterEach(() => - { + afterEach(() => { vi.restoreAllMocks(); }); @@ -52,10 +49,8 @@ describe("BotGenerator", () => // }); // }); - describe("generateBotNickname", () => - { - it("should choose random firstname for non player scav assault bot", () => - { + describe("generateBotNickname", () => { + it("should choose random firstname for non player scav assault bot", () => { const botJsonTemplate = { firstName: ["one", "two"], lastName: [] }; const botGenerationDetails = { isPlayerScav: false, isPmc: true, allPmcsHaveSameNameAsPlayer: false }; const botRole = "assault"; @@ -70,8 +65,7 @@ describe("BotGenerator", () => expect(result).toMatch(/(one|two)/); }); - it("should choose random lastname for non player scav assault bot", () => - { + it("should choose random lastname for non player scav assault bot", () => { const botJsonTemplate = { firstName: [], lastName: [["one", "two"]] }; const botGenerationDetails = { isPlayerScav: false, isPmc: true, allPmcsHaveSameNameAsPlayer: false }; const botRole = "assault"; @@ -86,8 +80,7 @@ describe("BotGenerator", () => expect(result).toMatch(/(one|two)/); }); - it("should choose random firstname and lastname for non player scav assault bot", () => - { + it("should choose random firstname and lastname for non player scav assault bot", () => { const botJsonTemplate = { firstName: ["first-one", "first-two"], lastName: [["last-one", "last-two"]] }; const botGenerationDetails = { isPlayerScav: false, isPmc: true, allPmcsHaveSameNameAsPlayer: false }; const botRole = "assault"; @@ -102,8 +95,7 @@ describe("BotGenerator", () => expect(result).toMatch(/first-(one|two) last-(one|two)/); }); - it("should choose random firstname for player scav assault bot", () => - { + it("should choose random firstname for player scav assault bot", () => { const botJsonTemplate = { firstName: ["one", "two"], lastName: [] }; const botGenerationDetails = { isPlayerScav: true, isPmc: false, allPmcsHaveSameNameAsPlayer: false }; const botRole = "assault"; @@ -118,8 +110,7 @@ describe("BotGenerator", () => expect(result).toMatch(/(one|two)/); }); - it("should choose random lastname for player scav assault bot", () => - { + it("should choose random lastname for player scav assault bot", () => { const botJsonTemplate = { firstName: [], lastName: [["one", "two"]] }; const botGenerationDetails = { isPlayerScav: true, isPmc: false, allPmcsHaveSameNameAsPlayer: false }; const botRole = "assault"; @@ -134,8 +125,7 @@ describe("BotGenerator", () => expect(result).toMatch(/(one|two)/); }); - it("should choose random firstname and lastname for player scav assault bot", () => - { + it("should choose random firstname and lastname for player scav assault bot", () => { const botJsonTemplate = { firstName: ["first-one", "first-two"], lastName: [["last-one", "last-two"]] }; const botGenerationDetails = { isPlayerScav: true, isPmc: false, allPmcsHaveSameNameAsPlayer: false }; const botRole = "assault"; @@ -150,8 +140,7 @@ describe("BotGenerator", () => expect(result).toMatch(/first-(one|two) last-(one|two)/); }); - it("should append bot type to end of name when showTypeInNickname option is enabled ", () => - { + it("should append bot type to end of name when showTypeInNickname option is enabled ", () => { const botJsonTemplate = { firstName: ["firstname"], lastName: ["lastname"] }; const botGenerationDetails = { isPlayerScav: false, isPmc: true, allPmcsHaveSameNameAsPlayer: false }; const botRole = "assault"; @@ -167,8 +156,7 @@ describe("BotGenerator", () => expect(result).toBe("firstname lastname assault"); }); - it("should return name prefix for PMC bot with same name as player if allPmcsHaveSameNameAsPlayer is enabled", () => - { + it("should return name prefix for PMC bot with same name as player if allPmcsHaveSameNameAsPlayer is enabled", () => { const botJsonTemplate = { firstName: ["player"], lastName: [] }; const botGenerationDetails = { isPlayerScav: false, isPmc: true, allPmcsHaveSameNameAsPlayer: true }; const botRole = "assault"; @@ -179,10 +167,9 @@ describe("BotGenerator", () => const mockPlayerProfile = { Info: { Nickname: "player", Level: 1 } }; vi.spyOn(botGenerator.profileHelper, "getPmcProfile").mockReturnValue(mockPlayerProfile); - const getRandomTextThatMatchesPartialKeySpy = vi.spyOn( - (botGenerator as any).localisationService, - "getRandomTextThatMatchesPartialKey", - ).mockReturnValue("test"); + const getRandomTextThatMatchesPartialKeySpy = vi + .spyOn((botGenerator as any).localisationService, "getRandomTextThatMatchesPartialKey") + .mockReturnValue("test"); const result = botGenerator.generateBotNickname(botJsonTemplate, botGenerationDetails, botRole); @@ -190,8 +177,7 @@ describe("BotGenerator", () => expect(result).toBe("test player"); }); - it("should generate PMC name in brackets behind scav name when chanceAssaultScavHasPlayerScavName is enabled", () => - { + it("should generate PMC name in brackets behind scav name when chanceAssaultScavHasPlayerScavName is enabled", () => { const botJsonTemplate = { firstName: ["scav"], lastName: [] }; const botGenerationDetails = { isPlayerScav: false, isPmc: true, allPmcsHaveSameNameAsPlayer: false }; const botRole = "assault"; diff --git a/project/tests/generators/BotLevelGenerator.test.ts b/project/tests/generators/BotLevelGenerator.test.ts index 82b69b4f..7c638383 100644 --- a/project/tests/generators/BotLevelGenerator.test.ts +++ b/project/tests/generators/BotLevelGenerator.test.ts @@ -1,32 +1,27 @@ import "reflect-metadata"; -import { container } from "tsyringe"; -import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import { BotLevelGenerator } from "@spt/generators/BotLevelGenerator"; import { MinMax } from "@spt/models/common/MinMax"; import { BotGenerationDetails } from "@spt/models/spt/bots/BotGenerationDetails"; import { DatabaseServer } from "@spt/servers/DatabaseServer"; +import { container } from "tsyringe"; +import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; -describe("BotLevelGenerator", () => -{ +describe("BotLevelGenerator", () => { let botLevelGenerator: any; let databaseServer: DatabaseServer; - beforeEach(() => - { + beforeEach(() => { botLevelGenerator = container.resolve("BotLevelGenerator"); databaseServer = container.resolve("DatabaseServer"); }); - afterEach(() => - { + afterEach(() => { vi.restoreAllMocks(); }); - describe("generateBotLevel", () => - { - it("should return value between 5 and 10 when player is level 5 and max is 10", () => - { + describe("generateBotLevel", () => { + it("should return value between 5 and 10 when player is level 5 and max is 10", () => { const levelDetails: MinMax = { min: 5, max: 10 }; const botGenerationDetails: BotGenerationDetails = { @@ -47,10 +42,8 @@ describe("BotLevelGenerator", () => }); }); - describe("getHighestRelativeBotLevel", () => - { - it("should return 10 when player level is 5 and delta is 5", () => - { + describe("getHighestRelativeBotLevel", () => { + it("should return 10 when player level is 5 and delta is 5", () => { const levelDetails: MinMax = { min: 5, max: 10 }; const botGenDetails: BotGenerationDetails = { isPmc: false, @@ -69,8 +62,7 @@ describe("BotLevelGenerator", () => expect(result).toBe(10); }); - it("should return 79 when player level is above possible max (100), desired max is 100 and delta is 5", () => - { + it("should return 79 when player level is above possible max (100), desired max is 100 and delta is 5", () => { const levelDetails: MinMax = { min: 100, max: 100 }; const botGenDetails: BotGenerationDetails = { isPmc: false, @@ -84,11 +76,7 @@ describe("BotLevelGenerator", () => isPlayerScav: false, }; - const result = botLevelGenerator.getHighestRelativeBotLevel( - botGenDetails, - levelDetails, - 79, - ); + const result = botLevelGenerator.getHighestRelativeBotLevel(botGenDetails, levelDetails, 79); expect(result).toBe(79); }); diff --git a/project/tests/helpers/BotDifficultyHelper.test.ts b/project/tests/helpers/BotDifficultyHelper.test.ts index 407144fa..459d369b 100644 --- a/project/tests/helpers/BotDifficultyHelper.test.ts +++ b/project/tests/helpers/BotDifficultyHelper.test.ts @@ -1,59 +1,45 @@ import "reflect-metadata"; +import { BotDifficultyHelper } from "@spt/helpers/BotDifficultyHelper"; import { container } from "tsyringe"; import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; -import { BotDifficultyHelper } from "@spt/helpers/BotDifficultyHelper"; -describe("BotHelper", () => -{ +describe("BotHelper", () => { let botDifficultyHelper: any; - beforeEach(() => - { + beforeEach(() => { botDifficultyHelper = container.resolve("BotDifficultyHelper"); }); - afterEach(() => - { + afterEach(() => { vi.restoreAllMocks(); }); - describe("convertBotDifficultyDropdownToBotDifficulty", () => - { - it("should return 'normal' when medium passed in", () => - { + describe("convertBotDifficultyDropdownToBotDifficulty", () => { + it("should return 'normal' when medium passed in", () => { expect(botDifficultyHelper.convertBotDifficultyDropdownToBotDifficulty("medium")).toBe("normal"); }); - it("should return 'normal' when randomly capitalized medium passed in", () => - { + it("should return 'normal' when randomly capitalized medium passed in", () => { expect(botDifficultyHelper.convertBotDifficultyDropdownToBotDifficulty("mEdIuM")).toBe("normal"); }); - it("should return passed in value when its not medium or random", () => - { + it("should return passed in value when its not medium or random", () => { expect(botDifficultyHelper.convertBotDifficultyDropdownToBotDifficulty("test_value")).toBe("test_value"); }); - it("should return randomised value when random passed in", () => - { - vi.spyOn(botDifficultyHelper, "chooseRandomDifficulty").mockReturnValue( - "randomValue", - ); + it("should return randomised value when random passed in", () => { + vi.spyOn(botDifficultyHelper, "chooseRandomDifficulty").mockReturnValue("randomValue"); expect(botDifficultyHelper.convertBotDifficultyDropdownToBotDifficulty("random")).toBe("randomValue"); }); }); - describe("getBotDifficultySettings", () => - { - it("should return assault bot if invalid bot type provided", () => - { - vi.spyOn(botDifficultyHelper, "convertBotDifficultyDropdownToBotDifficulty").mockReturnValue( - "normal", - ); - vi.spyOn(botDifficultyHelper.botHelper, "getBotTemplate").mockReturnValue( - { difficulty: { normal: "test" } }, - ); + describe("getBotDifficultySettings", () => { + it("should return assault bot if invalid bot type provided", () => { + vi.spyOn(botDifficultyHelper, "convertBotDifficultyDropdownToBotDifficulty").mockReturnValue("normal"); + vi.spyOn(botDifficultyHelper.botHelper, "getBotTemplate").mockReturnValue({ + difficulty: { normal: "test" }, + }); const warningLogSpy = vi.spyOn(botDifficultyHelper.logger, "warning"); const result = botDifficultyHelper.getBotDifficultySettings("INVALID_TYPE", "normal"); diff --git a/project/tests/helpers/BotHelper.test.ts b/project/tests/helpers/BotHelper.test.ts index 0315c5e4..e2073366 100644 --- a/project/tests/helpers/BotHelper.test.ts +++ b/project/tests/helpers/BotHelper.test.ts @@ -1,132 +1,108 @@ import "reflect-metadata"; +import { BotHelper } from "@spt/helpers/BotHelper"; import { container } from "tsyringe"; import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; -import { BotHelper } from "@spt/helpers/BotHelper"; -describe("BotHelper", () => -{ +describe("BotHelper", () => { let botHelper: any; - beforeEach(() => - { + beforeEach(() => { botHelper = container.resolve("BotHelper"); }); - afterEach(() => - { + afterEach(() => { vi.restoreAllMocks(); }); - describe("isBotPmc", () => - { - it("should return true when lowercase PMC role is provided", () => - { + describe("isBotPmc", () => { + it("should return true when lowercase PMC role is provided", () => { const result = botHelper.isBotPmc("usec"); expect(result).toBe(true); }); - it("should return true when uppercase PMC role is provided", () => - { + it("should return true when uppercase PMC role is provided", () => { const result = botHelper.isBotPmc("pmcBEAR"); expect(result).toBe(true); }); - it("should return false when legitimate non-PMC role is provided", () => - { + it("should return false when legitimate non-PMC role is provided", () => { const result = botHelper.isBotPmc("assault"); expect(result).toBe(false); }); - it("should return false when legitimate non-PMC role is provided", () => - { + it("should return false when legitimate non-PMC role is provided", () => { const result = botHelper.isBotPmc("FLUBBUB"); expect(result).toBe(false); }); - it("should return false when undefined role is provided", () => - { + it("should return false when undefined role is provided", () => { const result = botHelper.isBotPmc(undefined); expect(result).toBe(false); }); - it("should return false when empty string role is provided", () => - { + it("should return false when empty string role is provided", () => { const result = botHelper.isBotPmc(""); expect(result).toBe(false); }); }); - describe("isBotBoss", () => - { - it("should return true when lowercase boss role is provided", () => - { + describe("isBotBoss", () => { + it("should return true when lowercase boss role is provided", () => { const result = botHelper.isBotBoss("bossboar"); expect(result).toBe(true); }); - it("should return true when uppercase boss role is provided", () => - { + it("should return true when uppercase boss role is provided", () => { const result = botHelper.isBotBoss("BOSSBOAR"); expect(result).toBe(true); }); - it("should return false when legitimate non-boss role is provided", () => - { + it("should return false when legitimate non-boss role is provided", () => { const result = botHelper.isBotBoss("assault"); expect(result).toBe(false); }); - it("should return false when undefined role is provided", () => - { + it("should return false when undefined role is provided", () => { const result = botHelper.isBotBoss(undefined); expect(result).toBe(false); }); - it("should return false when empty string role is provided", () => - { + it("should return false when empty string role is provided", () => { const result = botHelper.isBotBoss(""); expect(result).toBe(false); }); }); - describe("getPmcSideByRole", () => - { - it("should return `Bear` when pmcBEAR role is provided", () => - { + describe("getPmcSideByRole", () => { + it("should return `Bear` when pmcBEAR role is provided", () => { const result = botHelper.getPmcSideByRole("pmcBEAR"); expect(result).toBe("Bear"); }); - it("should return `Usec` when pmcUSEC role is provided", () => - { + it("should return `Usec` when pmcUSEC role is provided", () => { const result = botHelper.getPmcSideByRole("pmcUSEC"); expect(result).toBe("Usec"); }); - it("should return `Usec` or `Bear` when non-PMC role is provided", () => - { + it("should return `Usec` or `Bear` when non-PMC role is provided", () => { const result = botHelper.getPmcSideByRole("assault"); expect(["Usec", "Bear"]).toContain(result); }); - it("should return `Usec` or `Bear` when empty string role is provided", () => - { + it("should return `Usec` or `Bear` when empty string role is provided", () => { const result = botHelper.getPmcSideByRole(""); expect(["Usec", "Bear"]).toContain(result); }); }); - describe("getRandomizedPmcSide", () => - { - it("should return `Bear` when isUsec config set to 0", () => - { + describe("getRandomizedPmcSide", () => { + it("should return `Bear` when isUsec config set to 0", () => { botHelper.pmcConfig.isUsec = 0; const result = botHelper.getRandomizedPmcSide(); expect(result).toBe("Bear"); }); - it("should return `Bear` when isUsec config set to 100", () => - { + it("should return `Bear` when isUsec config set to 100", () => { botHelper.pmcConfig.isUsec = 100; const result = botHelper.getRandomizedPmcSide(); expect(result).toBe("Usec"); diff --git a/project/tests/helpers/HandbookHelper.test.ts b/project/tests/helpers/HandbookHelper.test.ts index 9bf1be59..65c4f120 100644 --- a/project/tests/helpers/HandbookHelper.test.ts +++ b/project/tests/helpers/HandbookHelper.test.ts @@ -1,33 +1,27 @@ import "reflect-metadata"; -import { container } from "tsyringe"; -import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import { HandbookHelper } from "@spt/helpers/HandbookHelper"; import { Money } from "@spt/models/enums/Money"; +import { container } from "tsyringe"; +import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; -describe("HandbookHelper", () => -{ +describe("HandbookHelper", () => { let handbookHelper: any; - beforeEach(() => - { + beforeEach(() => { handbookHelper = container.resolve("HandbookHelper"); }); - afterEach(() => - { + afterEach(() => { vi.restoreAllMocks(); }); - describe("getTemplatePrice", () => - { - it("should return value greater than 1 when legitimate item is supplied and internal price cache not generated", () => - { + describe("getTemplatePrice", () => { + it("should return value greater than 1 when legitimate item is supplied and internal price cache not generated", () => { const result = handbookHelper.getTemplatePrice("544fb45d4bdc2dee738b4568"); // Salewa first aid kit expect(result).greaterThan(1); }); - it("should return value greater than 1 when legitimate item is supplied and internal price cache has been generated", () => - { + it("should return value greater than 1 when legitimate item is supplied and internal price cache has been generated", () => { handbookHelper.lookupCacheGenerated = false; handbookHelper.getTemplatePrice("544fb45d4bdc2dee738b4568"); // Salewa first aid kit @@ -36,16 +30,14 @@ describe("HandbookHelper", () => expect(secondResult).greaterThan(1); }); - it("should return 0 when item not found in handbook is supplied and internal price cache has not been updated", () => - { + it("should return 0 when item not found in handbook is supplied and internal price cache has not been updated", () => { handbookHelper.lookupCacheGenerated = false; const result = handbookHelper.getTemplatePrice("fakeItem"); expect(result).toBe(0); }); - it("should return 1 when item not found in handbook is supplied and internal price cache has been updated", () => - { + it("should return 1 when item not found in handbook is supplied and internal price cache has been updated", () => { handbookHelper.lookupCacheGenerated = false; // Add item to cache @@ -58,37 +50,30 @@ describe("HandbookHelper", () => }); }); - describe("templatesWithParent", () => - { - it("should return multiple items when supplied with Drinks category id", () => - { + describe("templatesWithParent", () => { + it("should return multiple items when supplied with Drinks category id", () => { const result = handbookHelper.templatesWithParent("5b47574386f77428ca22b335"); // Drinks category expect(result.length).greaterThan(5); }); - it("should return empty array when supplied with invalid id", () => - { + it("should return empty array when supplied with invalid id", () => { const result = handbookHelper.templatesWithParent("fakeCategory"); expect(result.length).toBe(0); }); }); - describe("inRUB", () => - { - it("should return 100 roubles when given 100 roubles", () => - { + describe("inRUB", () => { + it("should return 100 roubles when given 100 roubles", () => { const result = handbookHelper.inRUB(100, Money.ROUBLES); expect(result).toBe(100); }); - it("should return 0 roubles when given 0 roubles", () => - { + it("should return 0 roubles when given 0 roubles", () => { const result = handbookHelper.inRUB(0, Money.ROUBLES); expect(result).toBe(0); }); - it("should lookup currency value and multiply the input by the value", () => - { + it("should lookup currency value and multiply the input by the value", () => { // Mock the getTemplatePrice method to return a value of 100 roubles const getTemplatePriceSpy = vi.spyOn(handbookHelper, "getTemplatePrice").mockReturnValue(100); @@ -98,8 +83,7 @@ describe("HandbookHelper", () => expect(result).toBe(500); }); - it("should always return a whole number", () => - { + it("should always return a whole number", () => { // Mock the getTemplatePrice method to return a value of 100 roubles const getTemplatePriceSpy = vi.spyOn(handbookHelper, "getTemplatePrice").mockReturnValue(123.321); @@ -110,22 +94,18 @@ describe("HandbookHelper", () => }); }); - describe("fromRUB", () => - { - it("should return 100 roubles when given 100 roubles", () => - { + describe("fromRUB", () => { + it("should return 100 roubles when given 100 roubles", () => { const result = handbookHelper.fromRUB(100, Money.ROUBLES); expect(result).toBe(100); }); - it("should return 0 roubles when given 0 roubles", () => - { + it("should return 0 roubles when given 0 roubles", () => { const result = handbookHelper.fromRUB(0, Money.ROUBLES); expect(result).toBe(0); }); - it("should return roughly 72 Dollars when given 10000 roubles ", () => - { + it("should return roughly 72 Dollars when given 10000 roubles ", () => { const result = handbookHelper.fromRUB(10000, Money.EUROS); expect(result).closeTo(72, 5); }); diff --git a/project/tests/helpers/InRaidHelper.test.ts b/project/tests/helpers/InRaidHelper.test.ts index df41ea9b..6c2a9693 100644 --- a/project/tests/helpers/InRaidHelper.test.ts +++ b/project/tests/helpers/InRaidHelper.test.ts @@ -1,27 +1,22 @@ import "reflect-metadata"; -import { container } from "tsyringe"; -import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import { InRaidHelper } from "@spt/helpers/InRaidHelper"; import { IPmcData } from "@spt/models/eft/common/IPmcData"; +import { container } from "tsyringe"; +import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; -describe("InRaidHelper", () => -{ +describe("InRaidHelper", () => { let inraidHelper: any; - beforeEach(() => - { + beforeEach(() => { inraidHelper = container.resolve("InRaidHelper"); }); - afterEach(() => - { + afterEach(() => { vi.restoreAllMocks(); }); - describe("resetSkillPointsEarnedDuringRaid", () => - { - it("should reset PointsEarnedDuringSession for each skill in profile", () => - { + describe("resetSkillPointsEarnedDuringRaid", () => { + it("should reset PointsEarnedDuringSession for each skill in profile", () => { const mockProfile = { Skills: { Common: [ @@ -40,8 +35,7 @@ describe("InRaidHelper", () => (inraidHelper as any).resetSkillPointsEarnedDuringRaid(mockProfile); - for (const skill of mockProfile.Skills.Common) - { + for (const skill of mockProfile.Skills.Common) { expect(skill.PointsEarnedDuringSession).toBe(0); } }); diff --git a/project/tests/helpers/ItemHelper.test.ts b/project/tests/helpers/ItemHelper.test.ts index fdfff153..bbf09661 100644 --- a/project/tests/helpers/ItemHelper.test.ts +++ b/project/tests/helpers/ItemHelper.test.ts @@ -1,49 +1,41 @@ import "reflect-metadata"; -import { container } from "tsyringe"; -import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import { ItemHelper } from "@spt/helpers/ItemHelper"; import { Item, Repairable } from "@spt/models/eft/common/tables/IItem"; import { ITemplateItem } from "@spt/models/eft/common/tables/ITemplateItem"; import { DatabaseServer } from "@spt/servers/DatabaseServer"; import { HashUtil } from "@spt/utils/HashUtil"; +import { container } from "tsyringe"; +import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; -describe("ItemHelper", () => -{ +describe("ItemHelper", () => { let itemHelper: ItemHelper; - beforeEach(() => - { + beforeEach(() => { itemHelper = container.resolve("ItemHelper"); }); - afterEach(() => - { + afterEach(() => { vi.restoreAllMocks(); }); - describe("isValidItem", () => - { - it("should return false when item details are not available", () => - { + describe("isValidItem", () => { + it("should return false when item details are not available", () => { const result = itemHelper.isValidItem("non-existent-item"); expect(result).toBe(false); }); - it("should return false when item is a quest item", () => - { + it("should return false when item is a quest item", () => { const result = itemHelper.isValidItem("590de92486f77423d9312a33"); // "Gold pocket watch on a chain" expect(result).toBe(false); }); - it("should return false when item is of an invalid base type", () => - { + it("should return false when item is of an invalid base type", () => { const result = itemHelper.isValidItem("5fc64ea372b0dd78d51159dc", ["5447e1d04bdc2dff2f8b4567"]); // "Cultist knife" expect(result).toBe(false); }); - it("should return false when item's price is zero", () => - { + it("should return false when item's price is zero", () => { // Unsure if any item has price of "0", so mock the getItemPrice method to return 0. vi.spyOn(itemHelper, "getItemPrice").mockReturnValue(0); @@ -51,57 +43,47 @@ describe("ItemHelper", () => expect(result).toBe(false); }); - it("should return false when item is in the blacklist", () => - { + it("should return false when item is in the blacklist", () => { const result = itemHelper.isValidItem("6087e570b998180e9f76dc24"); // "Superfors DB 2020 Dead Blow Hammer" expect(result).toBe(false); }); - it("should return true when item is valid", () => - { + it("should return true when item is valid", () => { const result = itemHelper.isValidItem("5fc64ea372b0dd78d51159dc"); // "Cultist knife" expect(result).toBe(true); }); }); - describe("isOfBaseclass", () => - { - it("should return true when item has the given base class", () => - { + describe("isOfBaseclass", () => { + it("should return true when item has the given base class", () => { // ID 590c657e86f77412b013051d is a "Grizzly medical kit" of base class "MedKit". const result = itemHelper.isOfBaseclass("590c657e86f77412b013051d", "5448f39d4bdc2d0a728b4568"); expect(result).toBe(true); }); - it("should return false when item does not have the given base class", () => - { + it("should return false when item does not have the given base class", () => { // ID 590c657e86f77412b013051d is a "Grizzly medical kit" not of base class "Knife". const result = itemHelper.isOfBaseclass("590c657e86f77412b013051d", "5447e1d04bdc2dff2f8b4567"); expect(result).toBe(false); }); }); - describe("isOfBaseclasses", () => - { - it("should return true when item has the given base class", () => - { + describe("isOfBaseclasses", () => { + it("should return true when item has the given base class", () => { // ID 590c657e86f77412b013051d is a "Grizzly medical kit" of base class "MedKit". const result = itemHelper.isOfBaseclasses("590c657e86f77412b013051d", ["5448f39d4bdc2d0a728b4568"]); expect(result).toBe(true); }); - it("should return false when item does not have the given base class", () => - { + it("should return false when item does not have the given base class", () => { // ID 590c657e86f77412b013051d is a "Grizzly medical kit" not of base class "Knife". const result = itemHelper.isOfBaseclasses("590c657e86f77412b013051d", ["5447e1d04bdc2dff2f8b4567"]); expect(result).toBe(false); }); }); - describe("getItemPrice", () => - { - it("should return static price when it is greater than or equal to 1", () => - { + describe("getItemPrice", () => { + it("should return static price when it is greater than or equal to 1", () => { const staticPrice = 1; const tpl = "590c657e86f77412b013051d"; @@ -112,8 +94,7 @@ describe("ItemHelper", () => expect(result).toBe(staticPrice); }); - it("should return dynamic price when static price is less than 1", () => - { + it("should return dynamic price when static price is less than 1", () => { const staticPrice = 0; const dynamicPrice = 42069; const tpl = "590c657e86f77412b013051d"; @@ -127,8 +108,7 @@ describe("ItemHelper", () => expect(result).toBe(dynamicPrice); }); - it("should return 0 when neither handbook nor dynamic price is available", () => - { + it("should return 0 when neither handbook nor dynamic price is available", () => { const tpl = "590c657e86f77412b013051d"; vi.spyOn(itemHelper, "getStaticItemPrice").mockReturnValue(0); @@ -141,10 +121,8 @@ describe("ItemHelper", () => }); }); - describe("getItemMaxPrice", () => - { - it("should return static price when it is higher", () => - { + describe("getItemMaxPrice", () => { + it("should return static price when it is higher", () => { const staticPrice = 420; const dynamicPrice = 69; const tpl = "590c657e86f77412b013051d"; @@ -157,8 +135,7 @@ describe("ItemHelper", () => expect(result).toBe(staticPrice); }); - it("should return dynamic price when it is higher", () => - { + it("should return dynamic price when it is higher", () => { const staticPrice = 69; const dynamicPrice = 420; const tpl = "590c657e86f77412b013051d"; @@ -171,8 +148,7 @@ describe("ItemHelper", () => expect(result).toBe(dynamicPrice); }); - it("should return either when both prices are equal", () => - { + it("should return either when both prices are equal", () => { const price = 42069; const tpl = "590c657e86f77412b013051d"; @@ -184,8 +160,7 @@ describe("ItemHelper", () => expect(result).toBe(price); }); - it("should return 0 when item does not exist", () => - { + it("should return 0 when item does not exist", () => { const tpl = "non-existent-item"; const result = itemHelper.getItemMaxPrice(tpl); @@ -195,10 +170,8 @@ describe("ItemHelper", () => }); }); - describe("getStaticItemPrice", () => - { - it("should return handbook price when it is greater than or equal to 1", () => - { + describe("getStaticItemPrice", () => { + it("should return handbook price when it is greater than or equal to 1", () => { const price = 42069; const tpl = "590c657e86f77412b013051d"; @@ -210,8 +183,7 @@ describe("ItemHelper", () => expect(result).toBe(price); }); - it("should return 0 when handbook price is less than 1", () => - { + it("should return 0 when handbook price is less than 1", () => { const price = 0; const tpl = "590c657e86f77412b013051d"; // "Grizzly medical kit" @@ -224,10 +196,8 @@ describe("ItemHelper", () => }); }); - describe("getDynamicItemPrice", () => - { - it("should return the correct dynamic price when it exists", () => - { + describe("getDynamicItemPrice", () => { + it("should return the correct dynamic price when it exists", () => { const tpl = "590c657e86f77412b013051d"; // "Grizzly medical kit" const result = itemHelper.getDynamicItemPrice(tpl); @@ -235,8 +205,7 @@ describe("ItemHelper", () => expect(result).toBeGreaterThanOrEqual(1); }); - it("should return 0 when the dynamic price does not exist", () => - { + it("should return 0 when the dynamic price does not exist", () => { const tpl = "non-existent-item"; const result = itemHelper.getDynamicItemPrice(tpl); @@ -245,10 +214,8 @@ describe("ItemHelper", () => }); }); - describe("fixItemStackCount", () => - { - it("should set upd.StackObjectsCount to 1 if upd is undefined", () => - { + describe("fixItemStackCount", () => { + it("should set upd.StackObjectsCount to 1 if upd is undefined", () => { const initialItem: Item = { _id: "", _tpl: "" }; const fixedItem = itemHelper.fixItemStackCount(initialItem); @@ -256,8 +223,7 @@ describe("ItemHelper", () => expect(fixedItem.upd?.StackObjectsCount).toBe(1); }); - it("should set upd.StackObjectsCount to 1 if upd.StackObjectsCount is undefined", () => - { + it("should set upd.StackObjectsCount to 1 if upd.StackObjectsCount is undefined", () => { const initialItem: Item = { _id: "", _tpl: "", upd: {} }; const fixedItem = itemHelper.fixItemStackCount(initialItem); @@ -265,8 +231,7 @@ describe("ItemHelper", () => expect(fixedItem.upd?.StackObjectsCount).toBe(1); }); - it("should not change upd.StackObjectsCount if it is already defined", () => - { + it("should not change upd.StackObjectsCount if it is already defined", () => { const initialItem: Item = { _id: "", _tpl: "", upd: { StackObjectsCount: 5 } }; const fixedItem = itemHelper.fixItemStackCount(initialItem); @@ -275,10 +240,8 @@ describe("ItemHelper", () => }); }); - describe("getItems", () => - { - it("should call databaseService.getItems() and jsonUtil.clone() methods", () => - { + describe("getItems", () => { + it("should call databaseService.getItems() and jsonUtil.clone() methods", () => { const databaseServerGetTablesSpy = vi.spyOn((itemHelper as any).databaseService, "getItems"); const clonerSpy = vi.spyOn((itemHelper as any).cloner, "clone"); @@ -288,8 +251,7 @@ describe("ItemHelper", () => expect(clonerSpy).toHaveBeenCalled(); }); - it("should return a new array, not a reference to the original", () => - { + it("should return a new array, not a reference to the original", () => { const tables = container.resolve("DatabaseServer").getTables(); const originalItems = Object.values(tables.templates.items); @@ -303,10 +265,8 @@ describe("ItemHelper", () => }); }); - describe("getItem", () => - { - it("should return true and the item if the tpl exists", () => - { + describe("getItem", () => { + it("should return true and the item if the tpl exists", () => { // ID 590c657e86f77412b013051d is a "Grizzly medical kit". const tpl = "590c657e86f77412b013051d"; const tables = container.resolve("DatabaseServer").getTables(); @@ -318,8 +278,7 @@ describe("ItemHelper", () => expect(returnedItem).toBe(item); }); - it("should return false and undefined if the tpl does not exist", () => - { + it("should return false and undefined if the tpl does not exist", () => { const tpl = "non-existent-item"; const [isValid, returnedItem] = itemHelper.getItem(tpl); @@ -329,10 +288,8 @@ describe("ItemHelper", () => }); }); - describe("isItemInDb", () => - { - it("should return true if getItem returns true as the first element", () => - { + describe("isItemInDb", () => { + it("should return true if getItem returns true as the first element", () => { const tpl = "590c657e86f77412b013051d"; // "Grizzly medical kit" const result = itemHelper.isItemInDb(tpl); @@ -340,8 +297,7 @@ describe("ItemHelper", () => expect(result).toBe(true); }); - it("should return false if getItem returns false as the first element", () => - { + it("should return false if getItem returns false as the first element", () => { const tpl = "non-existent-item"; const result = itemHelper.isItemInDb(tpl); @@ -349,8 +305,7 @@ describe("ItemHelper", () => expect(result).toBe(false); }); - it("should call getItem with the provided tpl", () => - { + it("should call getItem with the provided tpl", () => { const itemHelperSpy = vi.spyOn(itemHelper, "getItem"); const tpl = "590c657e86f77412b013051d"; // "Grizzly medical kit" @@ -361,10 +316,8 @@ describe("ItemHelper", () => }); }); - describe("getItemQualityModifier", () => - { - it("should return 1 for an item with no upd", () => - { + describe("getItemQualityModifier", () => { + it("should return 1 for an item with no upd", () => { const itemId = container.resolve("HashUtil").generate(); const item: Item = { _id: itemId, @@ -376,8 +329,7 @@ describe("ItemHelper", () => expect(result).toBe(1); }); - it("should return 1 for an item with upd but no relevant fields", () => - { + it("should return 1 for an item with upd but no relevant fields", () => { const itemId = container.resolve("HashUtil").generate(); const item: Item = { _id: itemId, @@ -390,8 +342,7 @@ describe("ItemHelper", () => expect(result).toBe(1); }); - it("should return correct value for a medkit", () => - { + it("should return correct value for a medkit", () => { const itemId = container.resolve("HashUtil").generate(); const item: Item = { _id: itemId, @@ -408,8 +359,7 @@ describe("ItemHelper", () => expect(result).toBe(0.5); }); - it("should return correct value for a repairable helmet", () => - { + it("should return correct value for a repairable helmet", () => { const itemId = container.resolve("HashUtil").generate(); const item: Item = { _id: itemId, @@ -417,7 +367,8 @@ describe("ItemHelper", () => upd: { Repairable: { Durability: 19, MaxDurability: 38 } }, }; - const getRepairableItemQualityValueSpt = vi.spyOn(itemHelper as any, "getRepairableItemQualityValue") + const getRepairableItemQualityValueSpt = vi + .spyOn(itemHelper as any, "getRepairableItemQualityValue") .mockReturnValue(0.5); const result = itemHelper.getItemQualityModifier(item); @@ -426,8 +377,7 @@ describe("ItemHelper", () => expect(result).toBe(0.5); }); - it("should return correct value for a reparable weapon", () => - { + it("should return correct value for a reparable weapon", () => { const itemId = container.resolve("HashUtil").generate(); const item: Item = { _id: itemId, @@ -440,8 +390,7 @@ describe("ItemHelper", () => expect(result).toBeCloseTo(0.447); }); - it("should return correct value for a food or drink item", () => - { + it("should return correct value for a food or drink item", () => { const itemId = container.resolve("HashUtil").generate(); const item: Item = { _id: itemId, @@ -458,8 +407,7 @@ describe("ItemHelper", () => expect(result).toBe(0.5); }); - it("should return correct value for a key item", () => - { + it("should return correct value for a key item", () => { const itemId = container.resolve("HashUtil").generate(); const item: Item = { _id: itemId, @@ -472,8 +420,7 @@ describe("ItemHelper", () => expect(result).toBe(0.5); }); - it("should return correct value for a resource item", () => - { + it("should return correct value for a resource item", () => { const itemId = container.resolve("HashUtil").generate(); const item: Item = { _id: itemId, @@ -491,8 +438,7 @@ describe("ItemHelper", () => expect(result).toBe(0.5); }); - it("should return correct value for a repair kit item", () => - { + it("should return correct value for a repair kit item", () => { const itemId = container.resolve("HashUtil").generate(); const item: Item = { _id: itemId, @@ -505,8 +451,7 @@ describe("ItemHelper", () => expect(result).toBe(0.5); }); - it("should return 0.01 for an item with upd but all relevant fields are 0", () => - { + it("should return 0.01 for an item with upd but all relevant fields are 0", () => { const itemId = container.resolve("HashUtil").generate(); const item: Item = { _id: itemId, @@ -520,10 +465,8 @@ describe("ItemHelper", () => }); }); - describe("getRepairableItemQualityValue", () => - { - it("should return the correct quality value", () => - { + describe("getRepairableItemQualityValue", () => { + it("should return the correct quality value", () => { const weapon = itemHelper.getItem("5a38e6bac4a2826c6e06d79b")[1]; // "TOZ-106 20ga bolt-action shotgun" const repairable: Repairable = { Durability: 50, MaxDurability: 100 }; const item: Item = { _id: "", _tpl: "" }; @@ -534,8 +477,7 @@ describe("ItemHelper", () => expect(result).toBe(Math.sqrt(0.5)); }); - it("should fall back to using Repairable MaxDurability", () => - { + it("should fall back to using Repairable MaxDurability", () => { const weapon = itemHelper.getItem("5a38e6bac4a2826c6e06d79b")[1]; // "TOZ-106 20ga bolt-action shotgun" weapon._props.MaxDurability = undefined; // Remove the MaxDurability property. const repairable: Repairable = { @@ -550,8 +492,7 @@ describe("ItemHelper", () => expect(result).toBe(Math.sqrt(0.25)); }); - it("should return 1 if durability value is invalid", () => - { + it("should return 1 if durability value is invalid", () => { const weapon = itemHelper.getItem("5a38e6bac4a2826c6e06d79b")[1]; // "TOZ-106 20ga bolt-action shotgun" weapon._props.MaxDurability = undefined; // Remove the MaxDurability property. const repairable: Repairable = { @@ -561,8 +502,7 @@ describe("ItemHelper", () => const item: Item = { _id: "", _tpl: "" }; // Mock the logger's error method to prevent it from being actually called. - const loggerErrorSpy = vi.spyOn((itemHelper as any).logger, "error").mockImplementation(() => - {}); + const loggerErrorSpy = vi.spyOn((itemHelper as any).logger, "error").mockImplementation(() => {}); // Cast the method to any to allow access to private/protected method. const result = (itemHelper as any).getRepairableItemQualityValue(weapon, repairable, item); @@ -571,8 +511,7 @@ describe("ItemHelper", () => expect(result).toBe(1); }); - it("should not divide by zero", () => - { + it("should not divide by zero", () => { const weapon = itemHelper.getItem("5a38e6bac4a2826c6e06d79b")[1]; // "TOZ-106 20ga bolt-action shotgun" weapon._props.MaxDurability = undefined; // Remove the MaxDurability property. const repairable: Repairable = { @@ -587,8 +526,7 @@ describe("ItemHelper", () => expect(result).toBe(1); }); - it("should log an error if durability is invalid", () => - { + it("should log an error if durability is invalid", () => { const weapon = itemHelper.getItem("5a38e6bac4a2826c6e06d79b")[1]; // "TOZ-106 20ga bolt-action shotgun" weapon._props.MaxDurability = undefined; // Remove the MaxDurability property. const repairable: Repairable = { @@ -606,53 +544,62 @@ describe("ItemHelper", () => }); }); - describe("findAndReturnChildrenByItems", () => - { - it("should return an array containing only the parent ID when no children are found", () => - { - const items: Item[] = [{ _id: "1", _tpl: "", parentId: null }, { _id: "2", _tpl: "", parentId: null }, { - _id: "3", - _tpl: "", - parentId: "2", - }]; + describe("findAndReturnChildrenByItems", () => { + it("should return an array containing only the parent ID when no children are found", () => { + const items: Item[] = [ + { _id: "1", _tpl: "", parentId: null }, + { _id: "2", _tpl: "", parentId: null }, + { + _id: "3", + _tpl: "", + parentId: "2", + }, + ]; const result = itemHelper.findAndReturnChildrenByItems(items, "1"); expect(result).toEqual(["1"]); }); - it("should return array of child IDs when single-level children are found", () => - { - const items: Item[] = [{ _id: "1", _tpl: "", parentId: null }, { _id: "2", _tpl: "", parentId: "1" }, { - _id: "3", - _tpl: "", - parentId: "1", - }]; + it("should return array of child IDs when single-level children are found", () => { + const items: Item[] = [ + { _id: "1", _tpl: "", parentId: null }, + { _id: "2", _tpl: "", parentId: "1" }, + { + _id: "3", + _tpl: "", + parentId: "1", + }, + ]; const result = itemHelper.findAndReturnChildrenByItems(items, "1"); expect(result).toEqual(["2", "3", "1"]); }); - it("should return array of child IDs when multi-level children are found", () => - { - const items: Item[] = [{ _id: "1", _tpl: "", parentId: null }, { _id: "2", _tpl: "", parentId: "1" }, { - _id: "3", - _tpl: "", - parentId: "2", - }, { _id: "4", _tpl: "", parentId: "3" }]; + it("should return array of child IDs when multi-level children are found", () => { + const items: Item[] = [ + { _id: "1", _tpl: "", parentId: null }, + { _id: "2", _tpl: "", parentId: "1" }, + { + _id: "3", + _tpl: "", + parentId: "2", + }, + { _id: "4", _tpl: "", parentId: "3" }, + ]; const result = itemHelper.findAndReturnChildrenByItems(items, "1"); expect(result).toEqual(["4", "3", "2", "1"]); }); - it("should return an array containing only the parent ID when parent ID does not exist in items", () => - { - const items: Item[] = [{ _id: "1", _tpl: "", parentId: null }, { _id: "2", _tpl: "", parentId: "1" }]; + it("should return an array containing only the parent ID when parent ID does not exist in items", () => { + const items: Item[] = [ + { _id: "1", _tpl: "", parentId: null }, + { _id: "2", _tpl: "", parentId: "1" }, + ]; const result = itemHelper.findAndReturnChildrenByItems(items, "3"); expect(result).toEqual(["3"]); }); }); - describe("getItemStackSize", () => - { - it("should return 1 when item has no existing stack size", () => - { + describe("getItemStackSize", () => { + it("should return 1 when item has no existing stack size", () => { const itemId = container.resolve("HashUtil").generate(); const item: Item = { _id: itemId, @@ -663,8 +610,7 @@ describe("ItemHelper", () => expect(result).toBe(1); }); - it("should return 1 when item has no upd property", () => - { + it("should return 1 when item has no upd property", () => { const itemId = container.resolve("HashUtil").generate(); const item: Item = { _id: itemId, @@ -674,8 +620,7 @@ describe("ItemHelper", () => expect(result).toBe(1); }); - it("should return 5 when item has existing stack size of 5", () => - { + it("should return 5 when item has existing stack size of 5", () => { const itemId = container.resolve("HashUtil").generate(); const item: Item = { _id: itemId, @@ -687,10 +632,8 @@ describe("ItemHelper", () => }); }); - describe("hasBuyRestrictions", () => - { - it("should return true when item has buy restriction current and max properties", () => - { + describe("hasBuyRestrictions", () => { + it("should return true when item has buy restriction current and max properties", () => { const itemId = container.resolve("HashUtil").generate(); const item: Item = { _id: itemId, @@ -701,8 +644,7 @@ describe("ItemHelper", () => expect(result).toBe(true); }); - it("should return false when item has no buy restriction current or max properties but does have upd property", () => - { + it("should return false when item has no buy restriction current or max properties but does have upd property", () => { const itemId = container.resolve("HashUtil").generate(); const item: Item = { _id: itemId, @@ -713,8 +655,7 @@ describe("ItemHelper", () => expect(result).toBe(false); }); - it("should return false when item has no buy restriction current, max or upd properties", () => - { + it("should return false when item has no buy restriction current, max or upd properties", () => { const itemId = container.resolve("HashUtil").generate(); const item: Item = { _id: itemId, @@ -725,36 +666,32 @@ describe("ItemHelper", () => }); }); - describe("isDogtag", () => - { - it("should return true when tpl is a dogtag", () => - { + describe("isDogtag", () => { + it("should return true when tpl is a dogtag", () => { const result = itemHelper.isDogtag("59f32bb586f774757e1e8442"); // "Bear dogtag" expect(result).toBe(true); }); - it("should return false when tpl is not a dogtag", () => - { + it("should return false when tpl is not a dogtag", () => { const result = itemHelper.isDogtag("591094e086f7747caa7bb2ef"); // "Body armor repair kit" expect(result).toBe(false); }); - it("should return false when tpl is invalid", () => - { + it("should return false when tpl is invalid", () => { const result = itemHelper.isDogtag("invalidTpl"); expect(result).toBe(false); }); }); - describe("addCartridgesToAmmoBox", () => - { - it("should return an array with 1x ammoBox and 1x cartridge item", () => - { + describe("addCartridgesToAmmoBox", () => { + it("should return an array with 1x ammoBox and 1x cartridge item", () => { const itemId = container.resolve("HashUtil").generate(); - const ammoBox: Item[] = [{ - _id: itemId, - _tpl: "5c12619186f7743f871c8a32", // "9x39mm SPP gs ammo pack (8 pcs)" - }]; + const ammoBox: Item[] = [ + { + _id: itemId, + _tpl: "5c12619186f7743f871c8a32", // "9x39mm SPP gs ammo pack (8 pcs)" + }, + ]; const databaseServer = container.resolve("DatabaseServer"); const ammoBoxDetails = databaseServer.getTables().templates.items["5c12619186f7743f871c8a32"]; @@ -764,13 +701,14 @@ describe("ItemHelper", () => expect(ammoBox[1].upd.StackObjectsCount).toBe(8); }); - it("should return an array with 1x ammoBox and 2x cartridge items", () => - { + it("should return an array with 1x ammoBox and 2x cartridge items", () => { const itemId = container.resolve("HashUtil").generate(); - const ammoBox: Item[] = [{ - _id: itemId, - _tpl: "5737292724597765e5728562", // "5.45x39mm BP gs ammo pack (120 pcs)"" - }]; + const ammoBox: Item[] = [ + { + _id: itemId, + _tpl: "5737292724597765e5728562", // "5.45x39mm BP gs ammo pack (120 pcs)"" + }, + ]; const databaseServer = container.resolve("DatabaseServer"); const ammoBoxDetails = databaseServer.getTables().templates.items["5737292724597765e5728562"]; @@ -781,13 +719,14 @@ describe("ItemHelper", () => expect(ammoBox[2].upd.StackObjectsCount).toBe(60); }); - it("should keep original ammo box provided", () => - { + it("should keep original ammo box provided", () => { const itemId = container.resolve("HashUtil").generate(); - const ammoBox: Item[] = [{ - _id: itemId, - _tpl: "5737292724597765e5728562", // "5.45x39mm BP gs ammo pack (120 pcs)"" - }]; + const ammoBox: Item[] = [ + { + _id: itemId, + _tpl: "5737292724597765e5728562", // "5.45x39mm BP gs ammo pack (120 pcs)"" + }, + ]; const databaseServer = container.resolve("DatabaseServer"); const ammoBoxDetails = databaseServer.getTables().templates.items["5737292724597765e5728562"]; @@ -796,13 +735,14 @@ describe("ItemHelper", () => expect(ammoBox[0]._tpl).toBe("5737292724597765e5728562"); }); - it("should return specific cartridge type for the given ammo box provided", () => - { + it("should return specific cartridge type for the given ammo box provided", () => { const itemId = container.resolve("HashUtil").generate(); - const ammoBox: Item[] = [{ - _id: itemId, - _tpl: "5737292724597765e5728562", // "5.45x39mm BP gs ammo pack (120 pcs)"" - }]; + const ammoBox: Item[] = [ + { + _id: itemId, + _tpl: "5737292724597765e5728562", // "5.45x39mm BP gs ammo pack (120 pcs)"" + }, + ]; const databaseServer = container.resolve("DatabaseServer"); const ammoBoxDetails = databaseServer.getTables().templates.items["5737292724597765e5728562"]; @@ -812,48 +752,40 @@ describe("ItemHelper", () => }); }); - describe("isItemTplStackable", () => - { - it("should return true for a stackable item", () => - { + describe("isItemTplStackable", () => { + it("should return true for a stackable item", () => { const result = itemHelper.isItemTplStackable("5449016a4bdc2d6f028b456f"); // Roubles expect(result).toBe(true); }); - it("should return false for an unstackable item", () => - { + it("should return false for an unstackable item", () => { const result = itemHelper.isItemTplStackable("591094e086f7747caa7bb2ef"); // "Body armor repair kit" expect(result).toBe(false); }); - it("should return undefined for an unknown item", () => - { + it("should return undefined for an unknown item", () => { const result = itemHelper.isItemTplStackable("fakeTpl"); expect(result).toBe(undefined); }); - it("should return undefined for an empty input", () => - { + it("should return undefined for an empty input", () => { const result = itemHelper.isItemTplStackable(""); expect(result).toBe(undefined); }); }); - describe("getItemName", () => - { - it("should return item name for a valid item", () => - { + describe("getItemName", () => { + it("should return item name for a valid item", () => { const result = itemHelper.getItemName("5449016a4bdc2d6f028b456f"); // "Roubles" expect(result).toBe("Roubles"); }); - it("should return item short name for a valid item with empty full name", () => - { + it("should return item short name for a valid item with empty full name", () => { const databaseServer = container.resolve("DatabaseServer"); databaseServer.getTables().locales.global.en["5449016a4bdc2d6f028b456f Name"] = ""; const result = itemHelper.getItemName("5449016a4bdc2d6f028b456f"); // "Roubles" @@ -861,8 +793,7 @@ describe("ItemHelper", () => expect(result).toBe("RUB"); }); - it("should return item short name for a valid item with undefined full name", () => - { + it("should return item short name for a valid item with undefined full name", () => { const databaseServer = container.resolve("DatabaseServer"); databaseServer.getTables().locales.global.en["5449016a4bdc2d6f028b456f Name"] = undefined; const result = itemHelper.getItemName("5449016a4bdc2d6f028b456f"); // "Roubles" @@ -870,32 +801,27 @@ describe("ItemHelper", () => expect(result).toBe("RUB"); }); - it("should return undefined for invalid item", () => - { + it("should return undefined for invalid item", () => { const result = itemHelper.getItemName("fake tpl"); expect(result).toBe(undefined); }); - it("should return undefined for empty string", () => - { + it("should return undefined for empty string", () => { const result = itemHelper.getItemName(""); expect(result).toBe(undefined); }); - it("should return undefined for undefined", () => - { + it("should return undefined for undefined", () => { const result = itemHelper.getItemName(undefined); expect(result).toBe(undefined); }); }); - describe("adoptOrphanedItems", () => - { - it("should adopt orphaned items by resetting them as base-level items", () => - { + describe("adoptOrphanedItems", () => { + it("should adopt orphaned items by resetting them as base-level items", () => { const rootId = "root-id"; const items = [ { _id: "first-id", _tpl: "anything1", parentId: "does-not-exist", slotId: "main" }, @@ -919,8 +845,7 @@ describe("ItemHelper", () => expect(orphanedItem.slotId).toBe("hideout"); }); - it("should not adopt items that are not orphaned", () => - { + it("should not adopt items that are not orphaned", () => { const rootId = "root-id"; const items = [ { _id: "first-id", _tpl: "anything1", parentId: rootId, slotId: "hideout" }, @@ -936,8 +861,7 @@ describe("ItemHelper", () => expect(adopted).toStrictEqual(items); }); - it("should remove location data from adopted items", () => - { + it("should remove location data from adopted items", () => { const rootId = "root-id"; const items = [ { @@ -960,10 +884,8 @@ describe("ItemHelper", () => }); }); - describe("splitStack", () => - { - it("should return array of two items when provided item over its natural stack size limit", () => - { + describe("splitStack", () => { + it("should return array of two items when provided item over its natural stack size limit", () => { const stackableItem: Item = { _id: container.resolve("HashUtil").generate(), _tpl: "59e690b686f7746c9f75e848", // m995 @@ -976,8 +898,7 @@ describe("ItemHelper", () => expect(result.length).toBe(2); }); - it("should return same count of items passed in when provided is natural stack size limit", () => - { + it("should return same count of items passed in when provided is natural stack size limit", () => { const stackableItem: Item = { _id: container.resolve("HashUtil").generate(), _tpl: "59e690b686f7746c9f75e848", // m995 @@ -990,8 +911,7 @@ describe("ItemHelper", () => expect(itemCount).toBe(80); }); - it("should return same item if below max stack size", () => - { + it("should return same item if below max stack size", () => { const stackableItem: Item = { _id: container.resolve("HashUtil").generate(), _tpl: "59e690b686f7746c9f75e848", // m995 @@ -1005,8 +925,7 @@ describe("ItemHelper", () => expect(result.length).toBe(1); }); - it("should return same item if item has no StackObjectsCount property", () => - { + it("should return same item if item has no StackObjectsCount property", () => { const stackableItem: Item = { _id: container.resolve("HashUtil").generate(), _tpl: "59e690b686f7746c9f75e848", // m995 @@ -1016,8 +935,7 @@ describe("ItemHelper", () => expect(result.length).toBe(1); }); - it("should return same item if item has no upd object", () => - { + it("should return same item if item has no upd object", () => { const stackableItem: Item = { _id: container.resolve("HashUtil").generate(), _tpl: "59e690b686f7746c9f75e848", // m995 @@ -1027,10 +945,8 @@ describe("ItemHelper", () => }); }); - describe("getRandomCompatibleCaliberTemplateId", () => - { - it("should return an item from the passed template's cartridge filter array", () => - { + describe("getRandomCompatibleCaliberTemplateId", () => { + it("should return an item from the passed template's cartridge filter array", () => { const validAmmoItems = [ "5735ff5c245977640e39ba7e", "573601b42459776410737435", @@ -1053,23 +969,20 @@ describe("ItemHelper", () => expect(validAmmoItems).toContain(result); }); - it("should return null when passed template has empty cartridge property", () => - { + it("should return null when passed template has empty cartridge property", () => { const fakeTemplateItem = { _props: { Cartridges: [{}] } }; const result = itemHelper.getRandomCompatibleCaliberTemplateId(fakeTemplateItem as ITemplateItem); expect(result).toBe(undefined); }); - it("should return null when undefined passed in", () => - { + it("should return null when undefined passed in", () => { const result = itemHelper.getRandomCompatibleCaliberTemplateId(undefined as ITemplateItem); expect(result).toBe(undefined); }); - it("should log a warning when the template cartridge can not be found", () => - { + it("should log a warning when the template cartridge can not be found", () => { const mockLoggerWarning = vi.spyOn((itemHelper as any).logger, "warning"); itemHelper.getRandomCompatibleCaliberTemplateId(undefined as ITemplateItem); diff --git a/project/tests/services/ItemBaseClassService.test.ts b/project/tests/services/ItemBaseClassService.test.ts index e911f446..5cca242a 100644 --- a/project/tests/services/ItemBaseClassService.test.ts +++ b/project/tests/services/ItemBaseClassService.test.ts @@ -1,26 +1,21 @@ import "reflect-metadata"; +import { ItemBaseClassService } from "@spt/services/ItemBaseClassService"; import { container } from "tsyringe"; import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; -import { ItemBaseClassService } from "@spt/services/ItemBaseClassService"; -describe("ItemBaseClassService", () => -{ +describe("ItemBaseClassService", () => { let itemBaseClassService: any; - beforeEach(() => - { + beforeEach(() => { itemBaseClassService = container.resolve("ItemBaseClassService"); }); - afterEach(() => - { + afterEach(() => { vi.restoreAllMocks(); }); - describe("hydrateItemBaseClassCache", () => - { - it("should hydrate itemBaseClassesCache dictionary property", () => - { + describe("hydrateItemBaseClassCache", () => { + it("should hydrate itemBaseClassesCache dictionary property", () => { itemBaseClassService.cacheGenerated = false; itemBaseClassService.itemBaseClassesCache = {}; itemBaseClassService.hydrateItemBaseClassCache(); @@ -29,25 +24,21 @@ describe("ItemBaseClassService", () => }); }); - describe("itemHasBaseClass", () => - { - it("should return false when undefined is passed in", () => - { + describe("itemHasBaseClass", () => { + it("should return false when undefined is passed in", () => { const result = itemBaseClassService.itemHasBaseClass(undefined, []); expect(result).toBe(false); }); - it("should return false when the base item type is passed in", () => - { + it("should return false when the base item type is passed in", () => { // Remove item from base cache const result = itemBaseClassService.itemHasBaseClass("54009119af1c881c07000029", []); expect(result).toBe(false); }); - it("should return true when a med item is passed in with the meds base class", () => - { + it("should return true when a med item is passed in with the meds base class", () => { const salewaTpl = "544fb45d4bdc2dee738b4568"; // Remove item from base cache @@ -57,8 +48,7 @@ describe("ItemBaseClassService", () => expect(result).toBe(true); }); - it("should return true when an item and two matching base classes are passed in", () => - { + it("should return true when an item and two matching base classes are passed in", () => { const salewaTpl = "544fb45d4bdc2dee738b4568"; // Remove item from base cache @@ -71,8 +61,7 @@ describe("ItemBaseClassService", () => expect(result).toBe(true); }); - it("should return true when an item is passed in and cache has not been generated", () => - { + it("should return true when an item is passed in and cache has not been generated", () => { // Set cache to false itemBaseClassService.cacheGenerated = false; @@ -89,8 +78,7 @@ describe("ItemBaseClassService", () => expect(hydrateItemBaseClassCacheSpy).toHaveBeenCalled(); }); - it("should return false for any item template ID that does not exist", () => - { + it("should return false for any item template ID that does not exist", () => { const result = itemBaseClassService.itemHasBaseClass("not-a-valid-template-id", [ "543be5664bdc2dd4348b4569", ]); @@ -98,8 +86,7 @@ describe("ItemBaseClassService", () => expect(result).toBe(false); }); - it("should return false for any item template ID without the Item type ", () => - { + it("should return false for any item template ID without the Item type ", () => { const result = itemBaseClassService.itemHasBaseClass("54009119af1c881c07000029", [ "543be5664bdc2dd4348b4569", ]); @@ -108,25 +95,21 @@ describe("ItemBaseClassService", () => }); }); - describe("getItemBaseClasses", () => - { - it("should return empty array when undefined is passed in", () => - { + describe("getItemBaseClasses", () => { + it("should return empty array when undefined is passed in", () => { const result = itemBaseClassService.getItemBaseClasses(undefined); expect(result).toStrictEqual([]); }); - it("should return empty array when the base item type is passed in", () => - { + it("should return empty array when the base item type is passed in", () => { // Remove item from base cache const result = itemBaseClassService.getItemBaseClasses("54009119af1c881c07000029"); expect(result).toStrictEqual([]); }); - it("should return array of 3 items when an item is passed in", () => - { + it("should return array of 3 items when an item is passed in", () => { const salewaTpl = "544fb45d4bdc2dee738b4568"; const result = itemBaseClassService.getItemBaseClasses(salewaTpl); @@ -134,8 +117,7 @@ describe("ItemBaseClassService", () => expect(result.length).toBe(3); }); - it("should return array of 3 items when an item is passed in and cache has not been generated", () => - { + it("should return array of 3 items when an item is passed in and cache has not been generated", () => { itemBaseClassService.cacheGenerated = false; const hydrateItemBaseClassCacheSpy = vi.spyOn(itemBaseClassService, "hydrateItemBaseClassCache"); @@ -146,8 +128,7 @@ describe("ItemBaseClassService", () => expect(hydrateItemBaseClassCacheSpy).toHaveBeenCalled(); }); - it("should return base item type when an item is passed in", () => - { + it("should return base item type when an item is passed in", () => { const salewaTpl = "544fb45d4bdc2dee738b4568"; const result = itemBaseClassService.getItemBaseClasses(salewaTpl); @@ -155,8 +136,7 @@ describe("ItemBaseClassService", () => expect(result).toContain("5448f39d4bdc2d0a728b4568"); }); - it("should return empty array when an invalid item is passed in", () => - { + it("should return empty array when an invalid item is passed in", () => { const result = itemBaseClassService.getItemBaseClasses("fakeTpl"); expect(result).toStrictEqual([]); }); diff --git a/project/tests/services/LocaleService.test.ts b/project/tests/services/LocaleService.test.ts index 8fd94a0f..4333be4d 100644 --- a/project/tests/services/LocaleService.test.ts +++ b/project/tests/services/LocaleService.test.ts @@ -1,26 +1,21 @@ +import type { LocaleService } from "@spt/services/LocaleService"; import { container } from "tsyringe"; import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; -import type { LocaleService } from "@spt/services/LocaleService"; -describe("LocaleService", () => -{ +describe("LocaleService", () => { // biome-ignore lint/suspicious/noExplicitAny: let localeService: any; // Using "any" to access private/protected methods without type errors. - beforeEach(() => - { + beforeEach(() => { localeService = container.resolve("LocaleService"); }); - afterEach(() => - { + afterEach(() => { vi.restoreAllMocks(); }); - describe("getLocaleDb", () => - { - it("should return 'en' globals data when no desired locale found and display warning'", () => - { + describe("getLocaleDb", () => { + it("should return 'en' globals data when no desired locale found and display warning'", () => { vi.spyOn(localeService, "getDesiredGameLocale").mockReturnValue({ undefined, }); @@ -34,21 +29,16 @@ describe("LocaleService", () => }); }); - describe("getDesiredGameLocale", () => - { - it("should return gameLocale property from config when value is not 'system''", () => - { + describe("getDesiredGameLocale", () => { + it("should return gameLocale property from config when value is not 'system''", () => { localeService.localeConfig.gameLocale = "test"; expect(localeService.getDesiredGameLocale()).toBe("test"); }); - it("should return desired value when gameLocale property from config is 'system'", () => - { + it("should return desired value when gameLocale property from config is 'system'", () => { // Override the get locale so we control what the input is - vi.spyOn(localeService, "getPlatformForClientLocale").mockReturnValue( - "desiredLocale", - ); + vi.spyOn(localeService, "getPlatformForClientLocale").mockReturnValue("desiredLocale"); localeService.localeConfig.gameLocale = "system"; @@ -56,21 +46,16 @@ describe("LocaleService", () => }); }); - describe("getDesiredServerLocale", () => - { - it("should return serverLocale property from config when value is not 'system''", () => - { + describe("getDesiredServerLocale", () => { + it("should return serverLocale property from config when value is not 'system''", () => { localeService.localeConfig.serverLocale = "test"; expect(localeService.getDesiredServerLocale()).toBe("test"); }); - it("should return desired value when serverLocale property from config is 'system'", () => - { + it("should return desired value when serverLocale property from config is 'system'", () => { // Override the get locale so we control what the input is - vi.spyOn(localeService, "getPlatformForServerLocale").mockReturnValue( - "desiredLocale", - ); + vi.spyOn(localeService, "getPlatformForServerLocale").mockReturnValue("desiredLocale"); localeService.localeConfig.serverLocale = "system"; @@ -78,14 +63,10 @@ describe("LocaleService", () => }); }); - describe("getPlatformForServerLocale", () => - { - it("should return 'en' when no system locale found and display warning'", () => - { + describe("getPlatformForServerLocale", () => { + it("should return 'en' when no system locale found and display warning'", () => { // Override the get locale so we control what the input is - vi.spyOn(localeService, "getPlatformLocale").mockReturnValue( - undefined, - ); + vi.spyOn(localeService, "getPlatformLocale").mockReturnValue(undefined); const warningLogSpy = vi.spyOn(localeService.logger, "warning"); @@ -93,12 +74,12 @@ describe("LocaleService", () => expect(warningLogSpy).toHaveBeenCalledTimes(1); }); - it("should return 'en' when unsupported system local encountered and display warning'", () => - { + it("should return 'en' when unsupported system local encountered and display warning'", () => { // Override the get locale so we control what the input is - vi.spyOn(localeService, "getPlatformLocale").mockReturnValue( - { baseName: "test_locale_that_doesnt_exist", language: "test_language" }, - ); + vi.spyOn(localeService, "getPlatformLocale").mockReturnValue({ + baseName: "test_locale_that_doesnt_exist", + language: "test_language", + }); const warningLogSpy = vi.spyOn(localeService.logger, "warning"); @@ -107,25 +88,19 @@ describe("LocaleService", () => }); }); - describe("getPlatformForClientLocale", () => - { - it("should return 'en' when no platform locale found and display warning'", () => - { + describe("getPlatformForClientLocale", () => { + it("should return 'en' when no platform locale found and display warning'", () => { // Override the get locale so we control what the input is - vi.spyOn(localeService, "getPlatformLocale").mockReturnValue( - undefined, - ); + vi.spyOn(localeService, "getPlatformLocale").mockReturnValue(undefined); const warningLogSpy = vi.spyOn(localeService.logger, "warning"); expect(localeService.getPlatformForClientLocale()).toBe("en"); expect(warningLogSpy).toHaveBeenCalledTimes(1); }); - it("should return 'en' when unsupported platform local encountered and display warning'", () => - { + it("should return 'en' when unsupported platform local encountered and display warning'", () => { // Override the get locale so we control what the input is - localeService.getPlatformLocale = () => - { + localeService.getPlatformLocale = () => { return { baseName: "test_locale_that_doesnt_exist", language: "test_language" }; }; @@ -136,97 +111,68 @@ describe("LocaleService", () => }); }); - describe("ValidateServerLocale", () => - { - it("should return 'en' for 'en-US'", () => - { + describe("ValidateServerLocale", () => { + it("should return 'en' for 'en-US'", () => { // Override the get locale so we control what the input is - vi.spyOn(localeService, "getPlatformLocale").mockReturnValue( - new Intl.Locale("en-US"), - ); + vi.spyOn(localeService, "getPlatformLocale").mockReturnValue(new Intl.Locale("en-US")); expect(localeService.getPlatformForServerLocale()).toBe("en"); }); - it("should return 'ko' for 'ko-KR'", () => - { + it("should return 'ko' for 'ko-KR'", () => { // Override the get locale so we control what the input is - vi.spyOn(localeService, "getPlatformLocale").mockReturnValue( - new Intl.Locale("ko-KR"), - ); + vi.spyOn(localeService, "getPlatformLocale").mockReturnValue(new Intl.Locale("ko-KR")); expect(localeService.getPlatformForServerLocale()).toBe("ko"); }); - it("should return 'pt-pt' for 'pt-PT'", () => - { + it("should return 'pt-pt' for 'pt-PT'", () => { // Override the get locale so we control what the input is - vi.spyOn(localeService, "getPlatformLocale").mockReturnValue( - new Intl.Locale("pt-PT"), - ); + vi.spyOn(localeService, "getPlatformLocale").mockReturnValue(new Intl.Locale("pt-PT")); expect(localeService.getPlatformForServerLocale()).toBe("pt-pt"); }); - it("should return 'pt-br' for 'pt-BR'", () => - { + it("should return 'pt-br' for 'pt-BR'", () => { // Override the get locale so we control what the input is - vi.spyOn(localeService, "getPlatformLocale").mockReturnValue( - new Intl.Locale("pt-BR"), - ); + vi.spyOn(localeService, "getPlatformLocale").mockReturnValue(new Intl.Locale("pt-BR")); expect(localeService.getPlatformForServerLocale()).toBe("pt-br"); }); }); - describe("ValidateClientLocale", () => - { - it("should return 'en' for 'en-US'", () => - { + describe("ValidateClientLocale", () => { + it("should return 'en' for 'en-US'", () => { // Override the get locale so we control what the input is - vi.spyOn(localeService, "getPlatformLocale").mockReturnValue( - new Intl.Locale("en-US"), - ); + vi.spyOn(localeService, "getPlatformLocale").mockReturnValue(new Intl.Locale("en-US")); expect(localeService.getPlatformForClientLocale()).toBe("en"); }); - it("should return 'kr' for 'ko-KR'", () => - { + it("should return 'kr' for 'ko-KR'", () => { // Override the get locale so we control what the input is - vi.spyOn(localeService, "getPlatformLocale").mockReturnValue( - new Intl.Locale("ko-KR"), - ); + vi.spyOn(localeService, "getPlatformLocale").mockReturnValue(new Intl.Locale("ko-KR")); expect(localeService.getPlatformForClientLocale()).toBe("kr"); }); - it("should return 'es-mx' for 'es-MX'", () => - { + it("should return 'es-mx' for 'es-MX'", () => { // Override the get locale so we control what the input is - vi.spyOn(localeService, "getPlatformLocale").mockReturnValue( - new Intl.Locale("es-MX"), - ); + vi.spyOn(localeService, "getPlatformLocale").mockReturnValue(new Intl.Locale("es-MX")); expect(localeService.getPlatformForClientLocale()).toBe("es-mx"); }); - it("should return 'cz' for 'cs-CZ'", () => - { + it("should return 'cz' for 'cs-CZ'", () => { // Override the get locale so we control what the input is - vi.spyOn(localeService, "getPlatformLocale").mockReturnValue( - new Intl.Locale("cs-CZ"), - ); + vi.spyOn(localeService, "getPlatformLocale").mockReturnValue(new Intl.Locale("cs-CZ")); expect(localeService.getPlatformForClientLocale()).toBe("cz"); }); - it("should return 'ge' for 'de-DE'", () => - { + it("should return 'ge' for 'de-DE'", () => { // Override the get locale so we control what the input is - vi.spyOn(localeService, "getPlatformLocale").mockReturnValue( - new Intl.Locale("de-DE"), - ); + vi.spyOn(localeService, "getPlatformLocale").mockReturnValue(new Intl.Locale("de-DE")); expect(localeService.getPlatformForClientLocale()).toBe("ge"); }); diff --git a/project/tests/services/PaymentService.test.ts b/project/tests/services/PaymentService.test.ts index 420fdba6..b7457b4f 100644 --- a/project/tests/services/PaymentService.test.ts +++ b/project/tests/services/PaymentService.test.ts @@ -1,7 +1,5 @@ import "reflect-metadata"; -import { container } from "tsyringe"; -import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import { IPmcData } from "@spt/models/eft/common/IPmcData"; import { Item } from "@spt/models/eft/common/tables/IItem"; import { ITraderBase } from "@spt/models/eft/common/tables/ITrader"; @@ -9,25 +7,22 @@ import { IItemEventRouterResponse } from "@spt/models/eft/itemEvent/IItemEventRo import { IProcessBuyTradeRequestData } from "@spt/models/eft/trade/IProcessBuyTradeRequestData"; import { PaymentService } from "@spt/services/PaymentService"; import { HashUtil } from "@spt/utils/HashUtil"; +import { container } from "tsyringe"; +import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; -describe("PaymentService", () => -{ +describe("PaymentService", () => { let paymentService: any; // Using "any" to access private/protected methods without type errors. - beforeEach(() => - { + beforeEach(() => { paymentService = container.resolve("PaymentService"); }); - afterEach(() => - { + afterEach(() => { vi.restoreAllMocks(); }); - describe("payMoney", () => - { - it("should output a currency change when a single non-barter item is purchased from a trader", () => - { + describe("payMoney", () => { + it("should output a currency change when a single non-barter item is purchased from a trader", () => { const hashUtil = container.resolve("HashUtil"); const traderId = "54cb57776803fa99248b456e"; // Therapist @@ -76,24 +71,25 @@ describe("PaymentService", () => vi.spyOn((paymentService as any).logger, "debug").mockResolvedValue(undefined); // Mock the trader helper to return a trader with the currency of Roubles. - const getTraderSpy = vi.spyOn((paymentService as any).traderHelper, "getTrader").mockReturnValue( - { tid: traderId, currency: "RUB" } as unknown as ITraderBase, - ); + const getTraderSpy = vi + .spyOn((paymentService as any).traderHelper, "getTrader") + .mockReturnValue({ tid: traderId, currency: "RUB" } as unknown as ITraderBase); // Mock the addPaymentToOutput method to subtract the item cost from the money stack. - const addPaymentToOutputSpy = vi.spyOn(paymentService as any, "addPaymentToOutput").mockImplementation( - ( - pmcData: IPmcData, - currencyTpl: string, - amountToPay: number, - sessionIdentifier: string, - output: IItemEventRouterResponse, - ) => - { - moneyItem.upd.StackObjectsCount -= costAmount; - output.profileChanges[sessionIdentifier].items.change.push(moneyItem); - }, - ); + const addPaymentToOutputSpy = vi + .spyOn(paymentService as any, "addPaymentToOutput") + .mockImplementation( + ( + pmcData: IPmcData, + currencyTpl: string, + amountToPay: number, + sessionIdentifier: string, + output: IItemEventRouterResponse, + ) => { + moneyItem.upd.StackObjectsCount -= costAmount; + output.profileChanges[sessionIdentifier].items.change.push(moneyItem); + }, + ); // Mock the traderHelper lvlUp method to return void. const lvlUpSpy = vi.spyOn((paymentService as any).traderHelper, "lvlUp").mockResolvedValue(undefined); @@ -124,10 +120,8 @@ describe("PaymentService", () => }); }); - describe("isInStash", () => - { - it("should return true when item is direct parent of stash", () => - { + describe("isInStash", () => { + it("should return true when item is direct parent of stash", () => { const hashUtil = container.resolve("HashUtil"); const stashItem: Item = { _id: "stashid", @@ -147,8 +141,7 @@ describe("PaymentService", () => expect(result).toBe(true); }); - it("should return true when item is indirect parent of inventory", () => - { + it("should return true when item is indirect parent of inventory", () => { const hashUtil = container.resolve("HashUtil"); const stashItem: Item = { _id: "stashId", @@ -174,8 +167,7 @@ describe("PaymentService", () => expect(result).toBe(true); }); - it("should return false when desired item is not in inventory", () => - { + it("should return false when desired item is not in inventory", () => { const hashUtil = container.resolve("HashUtil"); const stashItem: Item = { _id: "stashId", @@ -195,8 +187,7 @@ describe("PaymentService", () => expect(result).toBe(false); }); - it("should return false when player inventory array has no inventory item", () => - { + it("should return false when player inventory array has no inventory item", () => { const hashUtil = container.resolve("HashUtil"); const stashItem: Item = { _id: "stashId", diff --git a/project/tests/services/PlayerService.test.ts b/project/tests/services/PlayerService.test.ts index 22ca696b..50c0fd3c 100644 --- a/project/tests/services/PlayerService.test.ts +++ b/project/tests/services/PlayerService.test.ts @@ -1,27 +1,22 @@ import "reflect-metadata"; -import { container } from "tsyringe"; -import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import { IPmcData } from "@spt/models/eft/common/IPmcData"; import { PlayerService } from "@spt/services/PlayerService"; +import { container } from "tsyringe"; +import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; -describe("PlayerService", () => -{ +describe("PlayerService", () => { let playerService: PlayerService; - beforeEach(() => - { + beforeEach(() => { playerService = container.resolve("PlayerService"); }); - afterEach(() => - { + afterEach(() => { vi.restoreAllMocks(); }); - describe("calculateLevel", () => - { - it("should return 1 when player xp is 0", () => - { + describe("calculateLevel", () => { + it("should return 1 when player xp is 0", () => { const playerProfile = { Info: { Experience: 0, // Via wiki: https://escapefromtarkov.fandom.com/wiki/Character_skills#Levels @@ -33,8 +28,7 @@ describe("PlayerService", () => expect(result).toBe(1); }); - it("should return 1 when player xp is 999", () => - { + it("should return 1 when player xp is 999", () => { const playerProfile = { Info: { Experience: 999, // Via wiki: https://escapefromtarkov.fandom.com/wiki/Character_skills#Levels @@ -46,8 +40,7 @@ describe("PlayerService", () => expect(result).toBe(1); }); - it("should return 25 when player xp is 609,066", () => - { + it("should return 25 when player xp is 609,066", () => { const playerProfile = { Info: { Experience: 609066, // Via wiki: https://escapefromtarkov.fandom.com/wiki/Character_skills#Levels @@ -59,8 +52,7 @@ describe("PlayerService", () => expect(result).toBe(25); }); - it("should return 79 when player xp is 81,126,895", () => - { + it("should return 79 when player xp is 81,126,895", () => { const playerProfile = { Info: { Experience: 81126895, // Via wiki: https://escapefromtarkov.fandom.com/wiki/Character_skills#Levels diff --git a/project/tests/services/ProfileFixerService.test.ts b/project/tests/services/ProfileFixerService.test.ts index e4e8352d..c0a75805 100644 --- a/project/tests/services/ProfileFixerService.test.ts +++ b/project/tests/services/ProfileFixerService.test.ts @@ -1,25 +1,20 @@ +import { ProfileFixerService } from "@spt/services/ProfileFixerService"; import { container } from "tsyringe"; import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; -import { ProfileFixerService } from "@spt/services/ProfileFixerService"; -describe("ProfileFixerService", () => -{ +describe("ProfileFixerService", () => { let profileFixerService: any; // Using "any" to access private/protected methods without type errors. - beforeEach(() => - { + beforeEach(() => { profileFixerService = container.resolve("ProfileFixerService"); }); - afterEach(() => - { + afterEach(() => { vi.restoreAllMocks(); }); - describe("FixPmcProfileIssues", () => - { - it("should reset nextResupply to 0 when it is undefined", () => - { + describe("FixPmcProfileIssues", () => { + it("should reset nextResupply to 0 when it is undefined", () => { const pmcProfile = { TradersInfo: { traderId: { nextResupply: undefined } } }; profileFixerService.fixNullTraderNextResupply(pmcProfile); @@ -27,8 +22,7 @@ describe("ProfileFixerService", () => expect(pmcProfile.TradersInfo.traderId.nextResupply).toBe(0); }); - it("should not reset nextResupply to 0 when it is not undefined", () => - { + it("should not reset nextResupply to 0 when it is not undefined", () => { const pmcProfile = { TradersInfo: { traderId: { nextResupply: 1234 } } }; profileFixerService.fixNullTraderNextResupply(pmcProfile); diff --git a/project/tests/services/RagfairPriceService.test.ts b/project/tests/services/RagfairPriceService.test.ts index 057af445..fc3dab04 100644 --- a/project/tests/services/RagfairPriceService.test.ts +++ b/project/tests/services/RagfairPriceService.test.ts @@ -1,27 +1,22 @@ import "reflect-metadata"; -import { container } from "tsyringe"; -import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import { Money } from "@spt/models/enums/Money"; import { RagfairPriceService } from "@spt/services/RagfairPriceService"; +import { container } from "tsyringe"; +import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; -describe("RagfairPriceService", () => -{ +describe("RagfairPriceService", () => { let ragfairPriceService: any; // Using "any" to access private/protected methods without type errors. - beforeEach(() => - { + beforeEach(() => { ragfairPriceService = container.resolve("RagfairPriceService"); }); - afterEach(() => - { + afterEach(() => { vi.restoreAllMocks(); }); - describe("getDynamicOfferPriceForOffer", () => - { - it("should return zero when empty offerItems array is passed", () => - { + describe("getDynamicOfferPriceForOffer", () => { + it("should return zero when empty offerItems array is passed", () => { const offerItems = []; const desiredCurrency = Money.ROUBLES; const isPackOffer = false; @@ -31,14 +26,15 @@ describe("RagfairPriceService", () => expect(price).toEqual(0); }); - it("should return non-zero number when valid item is passed", () => - { - const offerItems = [{ - _id: "d445ea263cdfc5f278334264", - _tpl: "57e3dba62459770f0c32322b", - parentId: "631abbff398cc0170cbd3089", - slotId: "mod_pistol_grip", - }]; + it("should return non-zero number when valid item is passed", () => { + const offerItems = [ + { + _id: "d445ea263cdfc5f278334264", + _tpl: "57e3dba62459770f0c32322b", + parentId: "631abbff398cc0170cbd3089", + slotId: "mod_pistol_grip", + }, + ]; const desiredCurrency = Money.ROUBLES; const isPackOffer = false; const expectedPrice = 42069; @@ -51,14 +47,15 @@ describe("RagfairPriceService", () => expect(price).toBe(expectedPrice); }); - it("should always return a whole number", () => - { - const offerItems = [{ - _id: "d445ea263cdfc5f278334264", - _tpl: "57e3dba62459770f0c32322b", - parentId: "631abbff398cc0170cbd3089", - slotId: "mod_pistol_grip", - }]; + it("should always return a whole number", () => { + const offerItems = [ + { + _id: "d445ea263cdfc5f278334264", + _tpl: "57e3dba62459770f0c32322b", + parentId: "631abbff398cc0170cbd3089", + slotId: "mod_pistol_grip", + }, + ]; const desiredCurrency = Money.ROUBLES; const isPackOffer = false; const originalPrice = 42069.999999999; @@ -72,14 +69,15 @@ describe("RagfairPriceService", () => expect(price).toBe(Math.round(originalPrice)); }); - it("should skip prices for soft armour inserts", () => - { - const offerItems = [{ - _id: "d445ea263cdfc5f278334264", - _tpl: "657080a212755ae0d907ad04", - parentId: "631abbff398cc0170cbd3089", - slotId: "Soft_armor_front", - }]; + it("should skip prices for soft armour inserts", () => { + const offerItems = [ + { + _id: "d445ea263cdfc5f278334264", + _tpl: "657080a212755ae0d907ad04", + parentId: "631abbff398cc0170cbd3089", + slotId: "Soft_armor_front", + }, + ]; const desiredCurrency = Money.ROUBLES; const isPackOffer = false; @@ -92,46 +90,51 @@ describe("RagfairPriceService", () => expect(getDynamicItemPriceSpy).not.toHaveBeenCalled(); }); - it("should not add value of mods to weapon preset", () => - { - const offerItems = [{ - _id: "344d02bbf2102ce4e145bf35", - _tpl: "579204f224597773d619e051", - upd: { - StackObjectsCount: 1, - UnlimitedCount: true, - sptPresetId: "5841499024597759f825ff3e", - Repairable: { Durability: 90, MaxDurability: 90 }, + it("should not add value of mods to weapon preset", () => { + const offerItems = [ + { + _id: "344d02bbf2102ce4e145bf35", + _tpl: "579204f224597773d619e051", + upd: { + StackObjectsCount: 1, + UnlimitedCount: true, + sptPresetId: "5841499024597759f825ff3e", + Repairable: { Durability: 90, MaxDurability: 90 }, + }, }, - }, { - _id: "59c6897a59ed48f1ca02f659", - _tpl: "5448c12b4bdc2d02308b456f", - parentId: "344d02bbf2102ce4e145bf35", - slotId: "mod_magazine", - }, { - _id: "7e8062d4bc57b56927c2d117", - _tpl: "6374a822e629013b9c0645c8", - parentId: "344d02bbf2102ce4e145bf35", - slotId: "mod_reciever", - }, { - _id: "3b09149e8b7833dc5fdd32a4", - _tpl: "63c6adcfb4ba094317063742", - parentId: "7e8062d4bc57b56927c2d117", - slotId: "mod_sight_rear", - }, { - _id: "e833a5c26af29870df9cdd2e", - _tpl: "6374a7e7417239a7bf00f042", - parentId: "344d02bbf2102ce4e145bf35", - slotId: "mod_pistolgrip", - }]; + { + _id: "59c6897a59ed48f1ca02f659", + _tpl: "5448c12b4bdc2d02308b456f", + parentId: "344d02bbf2102ce4e145bf35", + slotId: "mod_magazine", + }, + { + _id: "7e8062d4bc57b56927c2d117", + _tpl: "6374a822e629013b9c0645c8", + parentId: "344d02bbf2102ce4e145bf35", + slotId: "mod_reciever", + }, + { + _id: "3b09149e8b7833dc5fdd32a4", + _tpl: "63c6adcfb4ba094317063742", + parentId: "7e8062d4bc57b56927c2d117", + slotId: "mod_sight_rear", + }, + { + _id: "e833a5c26af29870df9cdd2e", + _tpl: "6374a7e7417239a7bf00f042", + parentId: "344d02bbf2102ce4e145bf35", + slotId: "mod_pistolgrip", + }, + ]; const desiredCurrency = Money.ROUBLES; const isPackOffer = false; const expectedPrice = 10000; // Mock the getDynamicItemPrice method to return a static price. - const getDynamicItemPriceSpy = vi.spyOn(ragfairPriceService, "getDynamicItemPrice").mockReturnValue( - expectedPrice, - ); + const getDynamicItemPriceSpy = vi + .spyOn(ragfairPriceService, "getDynamicItemPrice") + .mockReturnValue(expectedPrice); const price = ragfairPriceService.getDynamicOfferPriceForOffer(offerItems, desiredCurrency, isPackOffer); @@ -139,37 +142,41 @@ describe("RagfairPriceService", () => expect(getDynamicItemPriceSpy).toHaveBeenCalledTimes(1); }); - it("should sum value of all offer items", () => - { - const offerItems = [{ - _id: "59c6897a59ed48f1ca02f659", - _tpl: "5448c12b4bdc2d02308b456f", - parentId: "344d02bbf2102ce4e145bf35", - slotId: "mod_magazine", - }, { - _id: "7e8062d4bc57b56927c2d117", - _tpl: "6374a822e629013b9c0645c8", - parentId: "344d02bbf2102ce4e145bf35", - slotId: "mod_reciever", - }, { - _id: "3b09149e8b7833dc5fdd32a4", - _tpl: "63c6adcfb4ba094317063742", - parentId: "7e8062d4bc57b56927c2d117", - slotId: "mod_sight_rear", - }, { - _id: "e833a5c26af29870df9cdd2e", - _tpl: "6374a7e7417239a7bf00f042", - parentId: "344d02bbf2102ce4e145bf35", - slotId: "mod_pistolgrip", - }]; + it("should sum value of all offer items", () => { + const offerItems = [ + { + _id: "59c6897a59ed48f1ca02f659", + _tpl: "5448c12b4bdc2d02308b456f", + parentId: "344d02bbf2102ce4e145bf35", + slotId: "mod_magazine", + }, + { + _id: "7e8062d4bc57b56927c2d117", + _tpl: "6374a822e629013b9c0645c8", + parentId: "344d02bbf2102ce4e145bf35", + slotId: "mod_reciever", + }, + { + _id: "3b09149e8b7833dc5fdd32a4", + _tpl: "63c6adcfb4ba094317063742", + parentId: "7e8062d4bc57b56927c2d117", + slotId: "mod_sight_rear", + }, + { + _id: "e833a5c26af29870df9cdd2e", + _tpl: "6374a7e7417239a7bf00f042", + parentId: "344d02bbf2102ce4e145bf35", + slotId: "mod_pistolgrip", + }, + ]; const desiredCurrency = Money.ROUBLES; const isPackOffer = false; const expectedPrice = 10000; // Mock the getDynamicItemPrice method to return a static price. - const getDynamicItemPriceSpy = vi.spyOn(ragfairPriceService, "getDynamicItemPrice").mockReturnValue( - expectedPrice, - ); + const getDynamicItemPriceSpy = vi + .spyOn(ragfairPriceService, "getDynamicItemPrice") + .mockReturnValue(expectedPrice); const price = ragfairPriceService.getDynamicOfferPriceForOffer(offerItems, desiredCurrency, isPackOffer); @@ -178,10 +185,8 @@ describe("RagfairPriceService", () => }); }); - describe("getDynamicItemPrice", () => - { - it("should not return zero for a valid template ID", () => - { + describe("getDynamicItemPrice", () => { + it("should not return zero for a valid template ID", () => { const itemTemplateId = "5e54f6af86f7742199090bf3"; const desiredCurrency = Money.ROUBLES; @@ -190,8 +195,7 @@ describe("RagfairPriceService", () => expect(price).not.toBe(0); }); - it("should use trader price if it is higher than flea price and configuration allows it", () => - { + it("should use trader price if it is higher than flea price and configuration allows it", () => { const itemTemplateId = "5e54f6af86f7742199090bf3"; const desiredCurrency = Money.ROUBLES; const mockTraderPrice = 20000; @@ -220,8 +224,7 @@ describe("RagfairPriceService", () => expect(price).toBe(mockTraderPrice); }); - it("should adjust flea price when below handbook price and configuration allows it", () => - { + it("should adjust flea price when below handbook price and configuration allows it", () => { const itemTemplateId = "5e54f6af86f7742199090bf3"; const desiredCurrency = Money.ROUBLES; const mockFleaPrice = 1; @@ -239,8 +242,7 @@ describe("RagfairPriceService", () => // Mock the adjustPriceIfBelowHandbook method to simulate price adjustment. vi.spyOn(ragfairPriceService, "adjustPriceIfBelowHandbook").mockImplementation( - (price: number, templateId) => - { + (price: number, templateId) => { return price < handbookPrice ? adjustedPrice : price; }, ); @@ -255,27 +257,29 @@ describe("RagfairPriceService", () => expect(price).toBe(adjustedPrice); }); - it("should handle weapon preset prices correctly", () => - { + it("should handle weapon preset prices correctly", () => { const itemTemplateId = "579204f224597773d619e051"; const desiredCurrency = Money.ROUBLES; const mockPresetPrice = 25000; const getOfferTypeRangeValues = { max: 1, min: 1 }; - const offerItems = [{ - _id: "344d02bbf2102ce4e145bf35", - _tpl: "579204f224597773d619e051", - upd: { - StackObjectsCount: 1, - UnlimitedCount: true, - sptPresetId: "5841499024597759f825ff3e", - Repairable: { Durability: 90, MaxDurability: 90 }, + const offerItems = [ + { + _id: "344d02bbf2102ce4e145bf35", + _tpl: "579204f224597773d619e051", + upd: { + StackObjectsCount: 1, + UnlimitedCount: true, + sptPresetId: "5841499024597759f825ff3e", + Repairable: { Durability: 90, MaxDurability: 90 }, + }, }, - }, { - _id: "7e8062d4bc57b56927c2d117", - _tpl: "6374a822e629013b9c0645c8", - parentId: "344d02bbf2102ce4e145bf35", - slotId: "mod_reciever", - }]; + { + _id: "7e8062d4bc57b56927c2d117", + _tpl: "6374a822e629013b9c0645c8", + parentId: "344d02bbf2102ce4e145bf35", + slotId: "mod_reciever", + }, + ]; const item = offerItems[0]; // Disable other adjustments for isolation. @@ -290,9 +294,9 @@ describe("RagfairPriceService", () => vi.spyOn((ragfairPriceService as any).presetHelper, "isPresetBaseClass").mockReturnValue(true); // Mock the getWeaponPresetPrice method to return a specific preset price - const getWeaponPresetPriceSpy = vi.spyOn(ragfairPriceService, "getWeaponPresetPrice").mockReturnValue( - mockPresetPrice, - ); + const getWeaponPresetPriceSpy = vi + .spyOn(ragfairPriceService, "getWeaponPresetPrice") + .mockReturnValue(mockPresetPrice); // Mock the getOfferTypeRangeValues method to return a static minMax. vi.spyOn(ragfairPriceService, "getOfferTypeRangeValues").mockReturnValue(getOfferTypeRangeValues); @@ -310,8 +314,7 @@ describe("RagfairPriceService", () => expect(getWeaponPresetPriceSpy).toHaveBeenCalledWith(item, offerItems, expect.any(Number)); }); - it("should update price based on the ragfair config item price multiplier values", () => - { + it("should update price based on the ragfair config item price multiplier values", () => { const itemTemplateId = "5e54f6af86f7742199090bf3"; const desiredCurrency = Money.ROUBLES; const mockFleaPrice = 20000; @@ -335,28 +338,30 @@ describe("RagfairPriceService", () => expect(price).toBe(mockFleaPrice * itemPriceMultiplier); }); - it("should adjust price when durability is not perfect", () => - { + it("should adjust price when durability is not perfect", () => { const itemTemplateId = "579204f224597773d619e051"; const desiredCurrency = Money.ROUBLES; const mockPrice = 25000; const mockDurabilityMulti = 0.5; const getOfferTypeRangeValues = { max: 1, min: 1 }; - const offerItems = [{ - _id: "344d02bbf2102ce4e145bf35", - _tpl: "579204f224597773d619e051", - upd: { - StackObjectsCount: 1, - UnlimitedCount: true, - sptPresetId: "5841499024597759f825ff3e", - Repairable: { Durability: 40, MaxDurability: 90 }, + const offerItems = [ + { + _id: "344d02bbf2102ce4e145bf35", + _tpl: "579204f224597773d619e051", + upd: { + StackObjectsCount: 1, + UnlimitedCount: true, + sptPresetId: "5841499024597759f825ff3e", + Repairable: { Durability: 40, MaxDurability: 90 }, + }, }, - }, { - _id: "7e8062d4bc57b56927c2d117", - _tpl: "6374a822e629013b9c0645c8", - parentId: "344d02bbf2102ce4e145bf35", - slotId: "mod_reciever", - }]; + { + _id: "7e8062d4bc57b56927c2d117", + _tpl: "6374a822e629013b9c0645c8", + parentId: "344d02bbf2102ce4e145bf35", + slotId: "mod_reciever", + }, + ]; const item = offerItems[0]; // Disable other adjustments for isolation. @@ -377,10 +382,9 @@ describe("RagfairPriceService", () => vi.spyOn(ragfairPriceService, "getOfferTypeRangeValues").mockReturnValue(getOfferTypeRangeValues); // Mock the getItemQualityModifier method to return 1 (no change) - const getItemQualityModifierSpy = vi.spyOn( - (ragfairPriceService as any).itemHelper, - "getItemQualityModifier", - ).mockReturnValue(mockDurabilityMulti); + const getItemQualityModifierSpy = vi + .spyOn((ragfairPriceService as any).itemHelper, "getItemQualityModifier") + .mockReturnValue(mockDurabilityMulti); // Call the method. const price = ragfairPriceService.getDynamicItemPrice(itemTemplateId, desiredCurrency, item, offerItems); @@ -389,8 +393,7 @@ describe("RagfairPriceService", () => expect(price).toBe(mockPrice * mockDurabilityMulti); }); - it("should adjust unreasonable prices based on ragfair config unreasonable price values", () => - { + it("should adjust unreasonable prices based on ragfair config unreasonable price values", () => { const itemTemplateId = "5c052f6886f7746b1e3db148"; const desiredCurrency = Money.ROUBLES; const mockFleaPrice = 9999999; @@ -404,8 +407,8 @@ describe("RagfairPriceService", () => }; // Mock the Disable unreasonableModPrices config. Disable other adjustments for isolation. - ragfairPriceService.ragfairConfig.dynamic.unreasonableModPrices[mockBaseClassTemplateId] - = mockUnreasonableModPrices; + ragfairPriceService.ragfairConfig.dynamic.unreasonableModPrices[mockBaseClassTemplateId] = + mockUnreasonableModPrices; ragfairPriceService.ragfairConfig.dynamic.offerAdjustment.adjustPriceWhenBelowHandbookPrice = false; ragfairPriceService.ragfairConfig.dynamic.useTraderPriceForOffersIfHigher = false; ragfairPriceService.ragfairConfig.dynamic.itemPriceMultiplier[itemTemplateId] = null; @@ -414,9 +417,9 @@ describe("RagfairPriceService", () => vi.spyOn(ragfairPriceService, "getFleaPriceForItem").mockReturnValue(mockFleaPrice); // Mock isOfBaseclass to ensure that the item is always of the base class - const isOfBaseclassSpy = vi.spyOn((ragfairPriceService as any).itemHelper, "isOfBaseclass").mockReturnValue( - true, - ); + const isOfBaseclassSpy = vi + .spyOn((ragfairPriceService as any).itemHelper, "isOfBaseclass") + .mockReturnValue(true); // Mock the adjustUnreasonablePrice method to ensure it was called const adjustUnreasonablePriceSpy = vi.spyOn(ragfairPriceService, "adjustUnreasonablePrice"); @@ -432,8 +435,7 @@ describe("RagfairPriceService", () => expect(price).toBeLessThan(mockFleaPrice); }); - it("should vary the price within a random range", () => - { + it("should vary the price within a random range", () => { const itemTemplateId = "5e54f6af86f7742199090bf3"; const desiredCurrency = Money.ROUBLES; const mockFleaPrice = 10000; @@ -451,9 +453,9 @@ describe("RagfairPriceService", () => vi.spyOn((ragfairPriceService as any).presetHelper, "isPresetBaseClass").mockReturnValue(false); // Mock the randomiseOfferPrice method to have a simplified implementation - const randomiseOfferPriceSpy = vi.spyOn(ragfairPriceService, "randomiseOfferPrice").mockReturnValue( - mockRandomiseOfferPrice, - ); + const randomiseOfferPriceSpy = vi + .spyOn(ragfairPriceService, "randomiseOfferPrice") + .mockReturnValue(mockRandomiseOfferPrice); // Call the method. const price = ragfairPriceService.getDynamicItemPrice(itemTemplateId, desiredCurrency); @@ -462,8 +464,7 @@ describe("RagfairPriceService", () => expect(price).toBe(mockRandomiseOfferPrice); }); - it("should convert currency", () => - { + it("should convert currency", () => { const itemTemplateId = "5e54f6af86f7742199090bf3"; const desiredCurrency = Money.DOLLARS; const mockRoublePrice = 10000; @@ -482,9 +483,9 @@ describe("RagfairPriceService", () => vi.spyOn(ragfairPriceService, "getOfferTypeRangeValues").mockReturnValue(getOfferTypeRangeValues); // Mock the fromRUB method to convert the price to a different currency - const fromRUBSpy = vi.spyOn((ragfairPriceService as any).handbookHelper, "fromRUB").mockReturnValue( - mockDollarPrice, - ); + const fromRUBSpy = vi + .spyOn((ragfairPriceService as any).handbookHelper, "fromRUB") + .mockReturnValue(mockDollarPrice); // Call the method. const price = ragfairPriceService.getDynamicItemPrice(itemTemplateId, desiredCurrency); diff --git a/project/tests/utils/TimeUtil.test.ts b/project/tests/utils/TimeUtil.test.ts index d5d079a3..5dd4c687 100644 --- a/project/tests/utils/TimeUtil.test.ts +++ b/project/tests/utils/TimeUtil.test.ts @@ -1,15 +1,13 @@ import "reflect-metadata"; +import { TimeUtil } from "@spt/utils/TimeUtil"; import { container } from "tsyringe"; import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; -import { TimeUtil } from "@spt/utils/TimeUtil"; -describe("TimeUtil", () => -{ +describe("TimeUtil", () => { let timeUtil: TimeUtil; let mockedCurrentDate: Date; - beforeEach(() => - { + beforeEach(() => { timeUtil = container.resolve("TimeUtil"); mockedCurrentDate = new Date("2023-01-01T00:00:00Z"); @@ -17,102 +15,81 @@ describe("TimeUtil", () => vi.setSystemTime(mockedCurrentDate); }); - afterEach(() => - { + afterEach(() => { vi.useRealTimers(); vi.restoreAllMocks(); }); - describe("pad", () => - { - it("should pad a number with a leading zero if it is less than 10", () => - { + describe("pad", () => { + it("should pad a number with a leading zero if it is less than 10", () => { const paddedNumber = (timeUtil as any).pad(1); expect(paddedNumber).toBe("01"); }); - it("should not pad a number larger than 10", () => - { + it("should not pad a number larger than 10", () => { const paddedNumber = (timeUtil as any).pad(69); expect(paddedNumber).toBe("69"); }); - it("should not pad a number in the hundreds", () => - { + it("should not pad a number in the hundreds", () => { const paddedNumber = (timeUtil as any).pad(420); expect(paddedNumber).toBe("420"); }); }); - describe("formatTime", () => - { - it("should format the time part of a date as \"HH-MM-SS\"", () => - { + describe("formatTime", () => { + it('should format the time part of a date as "HH-MM-SS"', () => { const date = new Date("2023-01-01T12:34:56Z"); const formattedTime = timeUtil.formatTime(date); expect(formattedTime).toBe("12-34-56"); }); }); - describe("formatDate", () => - { - it("should format the date part of a date as \"YYYY-MM-DD\"", () => - { + describe("formatDate", () => { + it('should format the date part of a date as "YYYY-MM-DD"', () => { const date = new Date("2023-01-01T12:34:56Z"); const formattedDate = timeUtil.formatDate(date); expect(formattedDate).toBe("2023-01-01"); }); }); - describe("getDate", () => - { - it("should get the current date as a formatted UTC string", () => - { + describe("getDate", () => { + it("should get the current date as a formatted UTC string", () => { const currentDate = timeUtil.getDate(); expect(currentDate).toBe("2023-01-01"); }); }); - describe("getTime", () => - { - it("should get the current time as a formatted UTC string", () => - { + describe("getTime", () => { + it("should get the current time as a formatted UTC string", () => { const currentTime = timeUtil.getTime(); expect(currentTime).toBe("00-00-00"); // The mocked date is at midnight UTC. }); }); - describe("getTimestamp", () => - { - it("should get the current timestamp in seconds in UTC", () => - { + describe("getTimestamp", () => { + it("should get the current timestamp in seconds in UTC", () => { const timestamp = timeUtil.getTimestamp(); expect(timestamp).toBe(Math.floor(mockedCurrentDate.getTime() / 1000)); }); }); - describe("getTimeMailFormat", () => - { - it("should get the current time in UTC in a format suitable for mail in EFT", () => - { + describe("getTimeMailFormat", () => { + it("should get the current time in UTC in a format suitable for mail in EFT", () => { const timeMailFormat = timeUtil.getTimeMailFormat(); expect(timeMailFormat).toBe("00:00"); // The mocked date is at midnight UTC. }); }); - describe("getDateMailFormat", () => - { - it("should get the current date in UTC in a format suitable for emails in EFT", () => - { + describe("getDateMailFormat", () => { + it("should get the current date in UTC in a format suitable for emails in EFT", () => { const dateMailFormat = timeUtil.getDateMailFormat(); expect(dateMailFormat).toBe("01.01.2023"); }); }); - describe("getHoursAsSeconds", () => - { - it("should convert a number of hours into seconds", () => - { + describe("getHoursAsSeconds", () => { + it("should convert a number of hours into seconds", () => { const hours = 5; const seconds = timeUtil.getHoursAsSeconds(hours); expect(seconds).toBe(5 * 3600); diff --git a/project/tests/utils/collections/lists/LinkedList.test.ts b/project/tests/utils/collections/lists/LinkedList.test.ts index c193de29..d6ea6274 100644 --- a/project/tests/utils/collections/lists/LinkedList.test.ts +++ b/project/tests/utils/collections/lists/LinkedList.test.ts @@ -1,47 +1,39 @@ import "reflect-metadata"; -import { describe, expect, it } from "vitest"; import { LinkedList } from "@spt/utils/collections/lists/LinkedList"; +import { describe, expect, it } from "vitest"; -describe("LinkedList", () => -{ - describe("prepend", () => - { +describe("LinkedList", () => { + describe("prepend", () => { const list = new LinkedList(); list.prepend(420); list.prepend(69); list.prepend(8008135); list.prepend(1337); - it("adds elements to the begining of the list", () => - { + it("adds elements to the begining of the list", () => { expect(list.getHead()).toEqual(1337); expect(list.length).toEqual(4); }); }); - describe("append", () => - { + describe("append", () => { const list = new LinkedList(); list.append(420); list.append(69); list.append(8008135); list.append(1337); - it("adds elements to the end of the list", () => - { + it("adds elements to the end of the list", () => { expect(list.getHead()).toEqual(420); expect(list.length).toEqual(4); }); }); - describe("insertAt", () => - { - describe("empty list", () => - { + describe("insertAt", () => { + describe("empty list", () => { const list = new LinkedList(); - it("should allow insertions at index 0 only", () => - { + it("should allow insertions at index 0 only", () => { list.insertAt(420, 1); expect(list.length).toEqual(0); @@ -50,16 +42,14 @@ describe("LinkedList", () => }); }); - describe("filled list", () => - { + describe("filled list", () => { const list = new LinkedList(); list.append(420); list.append(69); list.append(8008135); list.append(1337); - it("shouldn't insert if index is < 0 and > length", () => - { + it("shouldn't insert if index is < 0 and > length", () => { list.insertAt(10100111001, -1); expect(list.length).toEqual(4); @@ -67,8 +57,7 @@ describe("LinkedList", () => expect(list.length).toEqual(4); }); - it("should insert if index is between 0 and length", () => - { + it("should insert if index is between 0 and length", () => { list.insertAt(10100111001, 0); expect(list.length).toEqual(5); @@ -81,17 +70,14 @@ describe("LinkedList", () => }); }); - describe("getHead/getTail", () => - { - it("should return undefined if the list is empty", () => - { + describe("getHead/getTail", () => { + it("should return undefined if the list is empty", () => { const list = new LinkedList(); expect(list.getHead()).toEqual(undefined); expect(list.getTail()).toEqual(undefined); }); - it("should return the head and the tail values if the list has 1 or more elements", () => - { + it("should return the head and the tail values if the list has 1 or more elements", () => { const list = new LinkedList(); list.append(420); list.append(69); @@ -102,35 +88,29 @@ describe("LinkedList", () => }); }); - describe("get", () => - { - describe("empty list", () => - { + describe("get", () => { + describe("empty list", () => { const list = new LinkedList(); - it("should return undefined", () => - { + it("should return undefined", () => { expect(list.get(0)).toEqual(undefined); expect(list.get(1)).toEqual(undefined); }); }); - describe("filled list", () => - { + describe("filled list", () => { const list = new LinkedList(); list.append(420); list.append(69); list.append(8008135); list.append(1337); - it("should return undefined if index is < 0 or >= length", () => - { + it("should return undefined if index is < 0 or >= length", () => { expect(list.get(-1)).toEqual(undefined); expect(list.get(list.length)).toEqual(undefined); }); - it("should return the value if the index is between 0 and length - 1", () => - { + it("should return the value if the index is between 0 and length - 1", () => { expect(list.get(0)).toEqual(420); expect(list.get(1)).toEqual(69); expect(list.get(list.length - 1)).toEqual(1337); @@ -138,22 +118,19 @@ describe("LinkedList", () => }); }); - describe("remove", () => - { + describe("remove", () => { const list = new LinkedList(); list.append(420); list.append(69); list.append(8008135); list.append(1337); - it("should return undefined if it doesn't find any element with the same value", () => - { + it("should return undefined if it doesn't find any element with the same value", () => { expect(list.remove(10100111001)).toEqual(undefined); expect(list.length).toEqual(4); }); - it("should remove an element and return it's value if one is found with the same value", () => - { + it("should remove an element and return it's value if one is found with the same value", () => { expect(list.remove(420)).toEqual(420); expect(list.length).toEqual(3); @@ -168,27 +145,22 @@ describe("LinkedList", () => }); }); - describe("shift", () => - { - describe("empty list", () => - { + describe("shift", () => { + describe("empty list", () => { const list = new LinkedList(); - it("shouldn't change the list and should return undefined if list is empty", () => - { + it("shouldn't change the list and should return undefined if list is empty", () => { expect(list.shift()).toEqual(undefined); expect(list.length).toEqual(0); }); }); - describe("filled list", () => - { + describe("filled list", () => { const list = new LinkedList(); list.append(420); list.append(1337); - it("should remove the first element and return it's value", () => - { + it("should remove the first element and return it's value", () => { expect(list.shift()).toEqual(420); expect(list.length).toEqual(1); @@ -198,27 +170,22 @@ describe("LinkedList", () => }); }); - describe("pop", () => - { - describe("empty list", () => - { + describe("pop", () => { + describe("empty list", () => { const list = new LinkedList(); - it("shouldn't change the list and should return undefined if list is empty", () => - { + it("shouldn't change the list and should return undefined if list is empty", () => { expect(list.pop()).toEqual(undefined); expect(list.length).toEqual(0); }); }); - describe("filled list", () => - { + describe("filled list", () => { const list = new LinkedList(); list.append(420); list.append(1337); - it("should remove the first element and return it's value", () => - { + it("should remove the first element and return it's value", () => { expect(list.pop()).toEqual(1337); expect(list.length).toEqual(1); @@ -228,8 +195,7 @@ describe("LinkedList", () => }); }); - describe("removeAt", () => - { + describe("removeAt", () => { const list = new LinkedList(); list.append(420); list.append(69); @@ -237,14 +203,12 @@ describe("LinkedList", () => list.append(1337); list.append(10100111001); - it("should return undefined if index is < 0 or >= length", () => - { + it("should return undefined if index is < 0 or >= length", () => { expect(list.removeAt(-1)).toEqual(undefined); expect(list.removeAt(list.length)).toEqual(undefined); }); - it("should remove an element and return it's value if index is between 0 and length - 1", () => - { + it("should remove an element and return it's value if index is between 0 and length - 1", () => { expect(list.removeAt(0)).toEqual(420); expect(list.length).toEqual(4); diff --git a/project/tests/utils/collections/queue/Queue.test.ts b/project/tests/utils/collections/queue/Queue.test.ts index 46f7972c..02688880 100644 --- a/project/tests/utils/collections/queue/Queue.test.ts +++ b/project/tests/utils/collections/queue/Queue.test.ts @@ -1,43 +1,36 @@ import "reflect-metadata"; -import { describe, expect, it } from "vitest"; import { Queue } from "@spt/utils/collections/queue/Queue"; +import { describe, expect, it } from "vitest"; -describe("LinkedList", () => -{ - describe("enqueue", () => - { +describe("LinkedList", () => { + describe("enqueue", () => { const queue = new Queue(); queue.enqueue(420); queue.enqueue(69); queue.enqueue(8008135); queue.enqueue(1337); - it("adds elements to the end of the queue", () => - { + it("adds elements to the end of the queue", () => { expect(queue.peek()).toEqual(420); expect(queue.length).toEqual(4); }); }); - describe("enqueueAll", () => - { + describe("enqueueAll", () => { const queue = new Queue(); queue.enqueueAll([420, 69, 8008135, 1337]); - it("iterates the array and adds each element to the end of the queue", () => - { + it("iterates the array and adds each element to the end of the queue", () => { expect(queue.peek()).toEqual(420); expect(queue.length).toEqual(4); }); }); - describe("dequeue", () => - { + describe("dequeue", () => { const queue = new Queue(); queue.enqueueAll([420, 69, 8008135, 1337]); - it("removes the first element and return it's value", () => - { + it("removes the first element and return it's value", () => { expect(queue.dequeue()).toEqual(420); expect(queue.peek()).toEqual(69); expect(queue.length).toEqual(3); diff --git a/project/tsconfig.base.json b/project/tsconfig.base.json index 8326a5d6..69d43f73 100644 --- a/project/tsconfig.base.json +++ b/project/tsconfig.base.json @@ -11,16 +11,9 @@ "emitDecoratorMetadata": true, "baseUrl": ".", "paths": { - "@spt/*": [ - "src/*" - ], - "@tests/*": [ - "tests/*" - ] + "@spt/*": ["src/*"], + "@tests/*": ["tests/*"] } }, - "include": [ - "src/*", - "src/**/*" - ] + "include": ["src/*", "src/**/*"] } diff --git a/project/tsconfig.json b/project/tsconfig.json index f92b43f2..8c20917d 100644 --- a/project/tsconfig.json +++ b/project/tsconfig.json @@ -5,13 +5,6 @@ "outDir": "obj", "declaration": true }, - "include": [ - "./src/**/*", - "./tests/**/*", - "./types/**/*", - "./user/mods/**/*" - ], - "exclude": [ - "./user/mods/**/*" - ] + "include": ["./src/**/*", "./tests/**/*", "./types/**/*", "./user/mods/**/*"], + "exclude": ["./user/mods/**/*"] } diff --git a/project/tsconfig.typedef.json b/project/tsconfig.typedef.json index 235104aa..41e90e7b 100644 --- a/project/tsconfig.typedef.json +++ b/project/tsconfig.typedef.json @@ -5,7 +5,5 @@ "declaration": true, "declarationDir": "./types" }, - "exclude": [ - "./types/**/*" - ] + "exclude": ["./types/**/*"] }