diff --git a/mods/Borkel's Realistic Night Vision Goggles/BepInEx/plugins/BorkelRNVG/LensTextures/lens_anvis.png b/mods/Borkel's Realistic Night Vision Goggles/BepInEx/plugins/BorkelRNVG/Assets/LensTextures/lens_anvis.png similarity index 100% rename from mods/Borkel's Realistic Night Vision Goggles/BepInEx/plugins/BorkelRNVG/LensTextures/lens_anvis.png rename to mods/Borkel's Realistic Night Vision Goggles/BepInEx/plugins/BorkelRNVG/Assets/LensTextures/lens_anvis.png diff --git a/mods/Borkel's Realistic Night Vision Goggles/BepInEx/plugins/BorkelRNVG/LensTextures/lens_binocular.png b/mods/Borkel's Realistic Night Vision Goggles/BepInEx/plugins/BorkelRNVG/Assets/LensTextures/lens_binocular.png similarity index 100% rename from mods/Borkel's Realistic Night Vision Goggles/BepInEx/plugins/BorkelRNVG/LensTextures/lens_binocular.png rename to mods/Borkel's Realistic Night Vision Goggles/BepInEx/plugins/BorkelRNVG/Assets/LensTextures/lens_binocular.png diff --git a/mods/Borkel's Realistic Night Vision Goggles/BepInEx/plugins/BorkelRNVG/LensTextures/lens_old_monocular.png b/mods/Borkel's Realistic Night Vision Goggles/BepInEx/plugins/BorkelRNVG/Assets/LensTextures/lens_old_monocular.png similarity index 100% rename from mods/Borkel's Realistic Night Vision Goggles/BepInEx/plugins/BorkelRNVG/LensTextures/lens_old_monocular.png rename to mods/Borkel's Realistic Night Vision Goggles/BepInEx/plugins/BorkelRNVG/Assets/LensTextures/lens_old_monocular.png diff --git a/mods/Borkel's Realistic Night Vision Goggles/BepInEx/plugins/BorkelRNVG/LensTextures/lens_pnv.png b/mods/Borkel's Realistic Night Vision Goggles/BepInEx/plugins/BorkelRNVG/Assets/LensTextures/lens_pnv.png similarity index 100% rename from mods/Borkel's Realistic Night Vision Goggles/BepInEx/plugins/BorkelRNVG/LensTextures/lens_pnv.png rename to mods/Borkel's Realistic Night Vision Goggles/BepInEx/plugins/BorkelRNVG/Assets/LensTextures/lens_pnv.png diff --git a/mods/Borkel's Realistic Night Vision Goggles/BepInEx/plugins/BorkelRNVG/MaskTextures/Noise.png b/mods/Borkel's Realistic Night Vision Goggles/BepInEx/plugins/BorkelRNVG/Assets/MaskTextures/Noise.png similarity index 100% rename from mods/Borkel's Realistic Night Vision Goggles/BepInEx/plugins/BorkelRNVG/MaskTextures/Noise.png rename to mods/Borkel's Realistic Night Vision Goggles/BepInEx/plugins/BorkelRNVG/Assets/MaskTextures/Noise.png diff --git a/mods/Borkel's Realistic Night Vision Goggles/BepInEx/plugins/BorkelRNVG/MaskTextures/OPTIONAL - Old thermal mask/mask_thermal.png b/mods/Borkel's Realistic Night Vision Goggles/BepInEx/plugins/BorkelRNVG/Assets/MaskTextures/OPTIONAL - Old thermal mask/mask_thermal.png similarity index 100% rename from mods/Borkel's Realistic Night Vision Goggles/BepInEx/plugins/BorkelRNVG/MaskTextures/OPTIONAL - Old thermal mask/mask_thermal.png rename to mods/Borkel's Realistic Night Vision Goggles/BepInEx/plugins/BorkelRNVG/Assets/MaskTextures/OPTIONAL - Old thermal mask/mask_thermal.png diff --git a/mods/Borkel's Realistic Night Vision Goggles/BepInEx/plugins/BorkelRNVG/MaskTextures/OPTIONAL Textures - Extra-blurry/mask_anvis.png b/mods/Borkel's Realistic Night Vision Goggles/BepInEx/plugins/BorkelRNVG/Assets/MaskTextures/OPTIONAL Textures - Extra-blurry/mask_anvis.png similarity index 100% rename from mods/Borkel's Realistic Night Vision Goggles/BepInEx/plugins/BorkelRNVG/MaskTextures/OPTIONAL Textures - Extra-blurry/mask_anvis.png rename to mods/Borkel's Realistic Night Vision Goggles/BepInEx/plugins/BorkelRNVG/Assets/MaskTextures/OPTIONAL Textures - Extra-blurry/mask_anvis.png diff --git a/mods/Borkel's Realistic Night Vision Goggles/BepInEx/plugins/BorkelRNVG/MaskTextures/OPTIONAL Textures - Extra-blurry/mask_binocular.png b/mods/Borkel's Realistic Night Vision Goggles/BepInEx/plugins/BorkelRNVG/Assets/MaskTextures/OPTIONAL Textures - Extra-blurry/mask_binocular.png similarity index 100% rename from mods/Borkel's Realistic Night Vision Goggles/BepInEx/plugins/BorkelRNVG/MaskTextures/OPTIONAL Textures - Extra-blurry/mask_binocular.png rename to mods/Borkel's Realistic Night Vision Goggles/BepInEx/plugins/BorkelRNVG/Assets/MaskTextures/OPTIONAL Textures - Extra-blurry/mask_binocular.png diff --git a/mods/Borkel's Realistic Night Vision Goggles/BepInEx/plugins/BorkelRNVG/MaskTextures/OPTIONAL Textures - Extra-blurry/mask_old_monocular.png b/mods/Borkel's Realistic Night Vision Goggles/BepInEx/plugins/BorkelRNVG/Assets/MaskTextures/OPTIONAL Textures - Extra-blurry/mask_old_monocular.png similarity index 100% rename from mods/Borkel's Realistic Night Vision Goggles/BepInEx/plugins/BorkelRNVG/MaskTextures/OPTIONAL Textures - Extra-blurry/mask_old_monocular.png rename to mods/Borkel's Realistic Night Vision Goggles/BepInEx/plugins/BorkelRNVG/Assets/MaskTextures/OPTIONAL Textures - Extra-blurry/mask_old_monocular.png diff --git a/mods/Borkel's Realistic Night Vision Goggles/BepInEx/plugins/BorkelRNVG/MaskTextures/OPTIONAL Textures - Extra-blurry/mask_pnv.png b/mods/Borkel's Realistic Night Vision Goggles/BepInEx/plugins/BorkelRNVG/Assets/MaskTextures/OPTIONAL Textures - Extra-blurry/mask_pnv.png similarity index 100% rename from mods/Borkel's Realistic Night Vision Goggles/BepInEx/plugins/BorkelRNVG/MaskTextures/OPTIONAL Textures - Extra-blurry/mask_pnv.png rename to mods/Borkel's Realistic Night Vision Goggles/BepInEx/plugins/BorkelRNVG/Assets/MaskTextures/OPTIONAL Textures - Extra-blurry/mask_pnv.png diff --git a/mods/Borkel's Realistic Night Vision Goggles/BepInEx/plugins/BorkelRNVG/MaskTextures/OPTIONAL Textures - Tubes Only/mask_anvis.png b/mods/Borkel's Realistic Night Vision Goggles/BepInEx/plugins/BorkelRNVG/Assets/MaskTextures/OPTIONAL Textures - Tubes Only/mask_anvis.png similarity index 100% rename from mods/Borkel's Realistic Night Vision Goggles/BepInEx/plugins/BorkelRNVG/MaskTextures/OPTIONAL Textures - Tubes Only/mask_anvis.png rename to mods/Borkel's Realistic Night Vision Goggles/BepInEx/plugins/BorkelRNVG/Assets/MaskTextures/OPTIONAL Textures - Tubes Only/mask_anvis.png diff --git a/mods/Borkel's Realistic Night Vision Goggles/BepInEx/plugins/BorkelRNVG/MaskTextures/OPTIONAL Textures - Tubes Only/mask_binocular.png b/mods/Borkel's Realistic Night Vision Goggles/BepInEx/plugins/BorkelRNVG/Assets/MaskTextures/OPTIONAL Textures - Tubes Only/mask_binocular.png similarity index 100% rename from mods/Borkel's Realistic Night Vision Goggles/BepInEx/plugins/BorkelRNVG/MaskTextures/OPTIONAL Textures - Tubes Only/mask_binocular.png rename to mods/Borkel's Realistic Night Vision Goggles/BepInEx/plugins/BorkelRNVG/Assets/MaskTextures/OPTIONAL Textures - Tubes Only/mask_binocular.png diff --git a/mods/Borkel's Realistic Night Vision Goggles/BepInEx/plugins/BorkelRNVG/MaskTextures/OPTIONAL Textures - Tubes Only/mask_old_monocular.png b/mods/Borkel's Realistic Night Vision Goggles/BepInEx/plugins/BorkelRNVG/Assets/MaskTextures/OPTIONAL Textures - Tubes Only/mask_old_monocular.png similarity index 100% rename from mods/Borkel's Realistic Night Vision Goggles/BepInEx/plugins/BorkelRNVG/MaskTextures/OPTIONAL Textures - Tubes Only/mask_old_monocular.png rename to mods/Borkel's Realistic Night Vision Goggles/BepInEx/plugins/BorkelRNVG/Assets/MaskTextures/OPTIONAL Textures - Tubes Only/mask_old_monocular.png diff --git a/mods/Borkel's Realistic Night Vision Goggles/BepInEx/plugins/BorkelRNVG/MaskTextures/OPTIONAL Textures - Tubes Only/mask_pnv.png b/mods/Borkel's Realistic Night Vision Goggles/BepInEx/plugins/BorkelRNVG/Assets/MaskTextures/OPTIONAL Textures - Tubes Only/mask_pnv.png similarity index 100% rename from mods/Borkel's Realistic Night Vision Goggles/BepInEx/plugins/BorkelRNVG/MaskTextures/OPTIONAL Textures - Tubes Only/mask_pnv.png rename to mods/Borkel's Realistic Night Vision Goggles/BepInEx/plugins/BorkelRNVG/Assets/MaskTextures/OPTIONAL Textures - Tubes Only/mask_pnv.png diff --git a/mods/Borkel's Realistic Night Vision Goggles/BepInEx/plugins/BorkelRNVG/MaskTextures/mask_anvis.png b/mods/Borkel's Realistic Night Vision Goggles/BepInEx/plugins/BorkelRNVG/Assets/MaskTextures/mask_anvis.png similarity index 100% rename from mods/Borkel's Realistic Night Vision Goggles/BepInEx/plugins/BorkelRNVG/MaskTextures/mask_anvis.png rename to mods/Borkel's Realistic Night Vision Goggles/BepInEx/plugins/BorkelRNVG/Assets/MaskTextures/mask_anvis.png diff --git a/mods/Borkel's Realistic Night Vision Goggles/BepInEx/plugins/BorkelRNVG/MaskTextures/mask_binocular.png b/mods/Borkel's Realistic Night Vision Goggles/BepInEx/plugins/BorkelRNVG/Assets/MaskTextures/mask_binocular.png similarity index 100% rename from mods/Borkel's Realistic Night Vision Goggles/BepInEx/plugins/BorkelRNVG/MaskTextures/mask_binocular.png rename to mods/Borkel's Realistic Night Vision Goggles/BepInEx/plugins/BorkelRNVG/Assets/MaskTextures/mask_binocular.png diff --git a/mods/Borkel's Realistic Night Vision Goggles/BepInEx/plugins/BorkelRNVG/MaskTextures/mask_old_monocular.png b/mods/Borkel's Realistic Night Vision Goggles/BepInEx/plugins/BorkelRNVG/Assets/MaskTextures/mask_old_monocular.png similarity index 100% rename from mods/Borkel's Realistic Night Vision Goggles/BepInEx/plugins/BorkelRNVG/MaskTextures/mask_old_monocular.png rename to mods/Borkel's Realistic Night Vision Goggles/BepInEx/plugins/BorkelRNVG/Assets/MaskTextures/mask_old_monocular.png diff --git a/mods/Borkel's Realistic Night Vision Goggles/BepInEx/plugins/BorkelRNVG/MaskTextures/mask_pnv.png b/mods/Borkel's Realistic Night Vision Goggles/BepInEx/plugins/BorkelRNVG/Assets/MaskTextures/mask_pnv.png similarity index 100% rename from mods/Borkel's Realistic Night Vision Goggles/BepInEx/plugins/BorkelRNVG/MaskTextures/mask_pnv.png rename to mods/Borkel's Realistic Night Vision Goggles/BepInEx/plugins/BorkelRNVG/Assets/MaskTextures/mask_pnv.png diff --git a/mods/Borkel's Realistic Night Vision Goggles/BepInEx/plugins/BorkelRNVG/MaskTextures/mask_thermal.png b/mods/Borkel's Realistic Night Vision Goggles/BepInEx/plugins/BorkelRNVG/Assets/MaskTextures/mask_thermal.png similarity index 100% rename from mods/Borkel's Realistic Night Vision Goggles/BepInEx/plugins/BorkelRNVG/MaskTextures/mask_thermal.png rename to mods/Borkel's Realistic Night Vision Goggles/BepInEx/plugins/BorkelRNVG/Assets/MaskTextures/mask_thermal.png diff --git a/mods/Borkel's Realistic Night Vision Goggles/BepInEx/plugins/BorkelRNVG/MaskTextures/pixel_mask1.png b/mods/Borkel's Realistic Night Vision Goggles/BepInEx/plugins/BorkelRNVG/Assets/MaskTextures/pixel_mask1.png similarity index 100% rename from mods/Borkel's Realistic Night Vision Goggles/BepInEx/plugins/BorkelRNVG/MaskTextures/pixel_mask1.png rename to mods/Borkel's Realistic Night Vision Goggles/BepInEx/plugins/BorkelRNVG/Assets/MaskTextures/pixel_mask1.png diff --git a/mods/Borkel's Realistic Night Vision Goggles/BepInEx/plugins/BorkelRNVG/borkel_realisticnvg_shaders b/mods/Borkel's Realistic Night Vision Goggles/BepInEx/plugins/BorkelRNVG/Assets/Shaders/borkel_realisticnvg_shaders similarity index 100% rename from mods/Borkel's Realistic Night Vision Goggles/BepInEx/plugins/BorkelRNVG/borkel_realisticnvg_shaders rename to mods/Borkel's Realistic Night Vision Goggles/BepInEx/plugins/BorkelRNVG/Assets/Shaders/borkel_realisticnvg_shaders diff --git a/mods/Borkel's Realistic Night Vision Goggles/BepInEx/plugins/BorkelRNVG/Sounds/gatingKnob.wav b/mods/Borkel's Realistic Night Vision Goggles/BepInEx/plugins/BorkelRNVG/Assets/Sounds/gatingKnob.wav similarity index 100% rename from mods/Borkel's Realistic Night Vision Goggles/BepInEx/plugins/BorkelRNVG/Sounds/gatingKnob.wav rename to mods/Borkel's Realistic Night Vision Goggles/BepInEx/plugins/BorkelRNVG/Assets/Sounds/gatingKnob.wav diff --git a/mods/Borkel's Realistic Night Vision Goggles/BepInEx/plugins/BorkelRNVG/Sounds/gatingKnob_alt.wav b/mods/Borkel's Realistic Night Vision Goggles/BepInEx/plugins/BorkelRNVG/Assets/Sounds/gatingKnob_alt.wav similarity index 100% rename from mods/Borkel's Realistic Night Vision Goggles/BepInEx/plugins/BorkelRNVG/Sounds/gatingKnob_alt.wav rename to mods/Borkel's Realistic Night Vision Goggles/BepInEx/plugins/BorkelRNVG/Assets/Sounds/gatingKnob_alt.wav diff --git a/mods/Borkel's Realistic Night Vision Goggles/BepInEx/plugins/BorkelRNVG/BorkelRNVG.dll b/mods/Borkel's Realistic Night Vision Goggles/BepInEx/plugins/BorkelRNVG/BorkelRNVG.dll index fdf1a59..2ef04ca 100644 Binary files a/mods/Borkel's Realistic Night Vision Goggles/BepInEx/plugins/BorkelRNVG/BorkelRNVG.dll and b/mods/Borkel's Realistic Night Vision Goggles/BepInEx/plugins/BorkelRNVG/BorkelRNVG.dll differ diff --git a/mods/Borkel's Realistic Night Vision Goggles/meta.ini b/mods/Borkel's Realistic Night Vision Goggles/meta.ini index 405393a..632da7b 100644 --- a/mods/Borkel's Realistic Night Vision Goggles/meta.ini +++ b/mods/Borkel's Realistic Night Vision Goggles/meta.ini @@ -5,7 +5,7 @@ version=d2025.1.12.0 newestVersion= category="1," nexusFileStatus=1 -installationFile=BRNVG-1.5.9.zip +installationFile=BRNVG-1.6.0.zip repository=Nexus ignoredVersion= comments= diff --git a/mods/Borkel's Realistic Night Vision Goggles_backup/BepInEx/plugins/BorkelRNVG/BorkelRNVG.dll b/mods/Borkel's Realistic Night Vision Goggles_backup/BepInEx/plugins/BorkelRNVG/BorkelRNVG.dll new file mode 100644 index 0000000..fdf1a59 Binary files /dev/null and b/mods/Borkel's Realistic Night Vision Goggles_backup/BepInEx/plugins/BorkelRNVG/BorkelRNVG.dll differ diff --git a/mods/Borkel's Realistic Night Vision Goggles_backup/BepInEx/plugins/BorkelRNVG/LensTextures/lens_anvis.png b/mods/Borkel's Realistic Night Vision Goggles_backup/BepInEx/plugins/BorkelRNVG/LensTextures/lens_anvis.png new file mode 100644 index 0000000..42bf7e4 Binary files /dev/null and b/mods/Borkel's Realistic Night Vision Goggles_backup/BepInEx/plugins/BorkelRNVG/LensTextures/lens_anvis.png differ diff --git a/mods/Borkel's Realistic Night Vision Goggles_backup/BepInEx/plugins/BorkelRNVG/LensTextures/lens_binocular.png b/mods/Borkel's Realistic Night Vision Goggles_backup/BepInEx/plugins/BorkelRNVG/LensTextures/lens_binocular.png new file mode 100644 index 0000000..1b483c3 Binary files /dev/null and b/mods/Borkel's Realistic Night Vision Goggles_backup/BepInEx/plugins/BorkelRNVG/LensTextures/lens_binocular.png differ diff --git a/mods/Borkel's Realistic Night Vision Goggles_backup/BepInEx/plugins/BorkelRNVG/LensTextures/lens_old_monocular.png b/mods/Borkel's Realistic Night Vision Goggles_backup/BepInEx/plugins/BorkelRNVG/LensTextures/lens_old_monocular.png new file mode 100644 index 0000000..207ea55 Binary files /dev/null and b/mods/Borkel's Realistic Night Vision Goggles_backup/BepInEx/plugins/BorkelRNVG/LensTextures/lens_old_monocular.png differ diff --git a/mods/Borkel's Realistic Night Vision Goggles_backup/BepInEx/plugins/BorkelRNVG/LensTextures/lens_pnv.png b/mods/Borkel's Realistic Night Vision Goggles_backup/BepInEx/plugins/BorkelRNVG/LensTextures/lens_pnv.png new file mode 100644 index 0000000..e5b894b Binary files /dev/null and b/mods/Borkel's Realistic Night Vision Goggles_backup/BepInEx/plugins/BorkelRNVG/LensTextures/lens_pnv.png differ diff --git a/mods/Borkel's Realistic Night Vision Goggles_backup/BepInEx/plugins/BorkelRNVG/MaskTextures/Noise.png b/mods/Borkel's Realistic Night Vision Goggles_backup/BepInEx/plugins/BorkelRNVG/MaskTextures/Noise.png new file mode 100644 index 0000000..218b138 Binary files /dev/null and b/mods/Borkel's Realistic Night Vision Goggles_backup/BepInEx/plugins/BorkelRNVG/MaskTextures/Noise.png differ diff --git a/mods/Borkel's Realistic Night Vision Goggles_backup/BepInEx/plugins/BorkelRNVG/MaskTextures/OPTIONAL - Old thermal mask/mask_thermal.png b/mods/Borkel's Realistic Night Vision Goggles_backup/BepInEx/plugins/BorkelRNVG/MaskTextures/OPTIONAL - Old thermal mask/mask_thermal.png new file mode 100644 index 0000000..9c03e42 Binary files /dev/null and b/mods/Borkel's Realistic Night Vision Goggles_backup/BepInEx/plugins/BorkelRNVG/MaskTextures/OPTIONAL - Old thermal mask/mask_thermal.png differ diff --git a/mods/Borkel's Realistic Night Vision Goggles_backup/BepInEx/plugins/BorkelRNVG/MaskTextures/OPTIONAL Textures - Extra-blurry/mask_anvis.png b/mods/Borkel's Realistic Night Vision Goggles_backup/BepInEx/plugins/BorkelRNVG/MaskTextures/OPTIONAL Textures - Extra-blurry/mask_anvis.png new file mode 100644 index 0000000..92eee3d Binary files /dev/null and b/mods/Borkel's Realistic Night Vision Goggles_backup/BepInEx/plugins/BorkelRNVG/MaskTextures/OPTIONAL Textures - Extra-blurry/mask_anvis.png differ diff --git a/mods/Borkel's Realistic Night Vision Goggles_backup/BepInEx/plugins/BorkelRNVG/MaskTextures/OPTIONAL Textures - Extra-blurry/mask_binocular.png b/mods/Borkel's Realistic Night Vision Goggles_backup/BepInEx/plugins/BorkelRNVG/MaskTextures/OPTIONAL Textures - Extra-blurry/mask_binocular.png new file mode 100644 index 0000000..839a8b7 Binary files /dev/null and b/mods/Borkel's Realistic Night Vision Goggles_backup/BepInEx/plugins/BorkelRNVG/MaskTextures/OPTIONAL Textures - Extra-blurry/mask_binocular.png differ diff --git a/mods/Borkel's Realistic Night Vision Goggles_backup/BepInEx/plugins/BorkelRNVG/MaskTextures/OPTIONAL Textures - Extra-blurry/mask_old_monocular.png b/mods/Borkel's Realistic Night Vision Goggles_backup/BepInEx/plugins/BorkelRNVG/MaskTextures/OPTIONAL Textures - Extra-blurry/mask_old_monocular.png new file mode 100644 index 0000000..3978532 Binary files /dev/null and b/mods/Borkel's Realistic Night Vision Goggles_backup/BepInEx/plugins/BorkelRNVG/MaskTextures/OPTIONAL Textures - Extra-blurry/mask_old_monocular.png differ diff --git a/mods/Borkel's Realistic Night Vision Goggles_backup/BepInEx/plugins/BorkelRNVG/MaskTextures/OPTIONAL Textures - Extra-blurry/mask_pnv.png b/mods/Borkel's Realistic Night Vision Goggles_backup/BepInEx/plugins/BorkelRNVG/MaskTextures/OPTIONAL Textures - Extra-blurry/mask_pnv.png new file mode 100644 index 0000000..b2bf390 Binary files /dev/null and b/mods/Borkel's Realistic Night Vision Goggles_backup/BepInEx/plugins/BorkelRNVG/MaskTextures/OPTIONAL Textures - Extra-blurry/mask_pnv.png differ diff --git a/mods/Borkel's Realistic Night Vision Goggles_backup/BepInEx/plugins/BorkelRNVG/MaskTextures/OPTIONAL Textures - Tubes Only/mask_anvis.png b/mods/Borkel's Realistic Night Vision Goggles_backup/BepInEx/plugins/BorkelRNVG/MaskTextures/OPTIONAL Textures - Tubes Only/mask_anvis.png new file mode 100644 index 0000000..cd30c53 Binary files /dev/null and b/mods/Borkel's Realistic Night Vision Goggles_backup/BepInEx/plugins/BorkelRNVG/MaskTextures/OPTIONAL Textures - Tubes Only/mask_anvis.png differ diff --git a/mods/Borkel's Realistic Night Vision Goggles_backup/BepInEx/plugins/BorkelRNVG/MaskTextures/OPTIONAL Textures - Tubes Only/mask_binocular.png b/mods/Borkel's Realistic Night Vision Goggles_backup/BepInEx/plugins/BorkelRNVG/MaskTextures/OPTIONAL Textures - Tubes Only/mask_binocular.png new file mode 100644 index 0000000..bb1d520 Binary files /dev/null and b/mods/Borkel's Realistic Night Vision Goggles_backup/BepInEx/plugins/BorkelRNVG/MaskTextures/OPTIONAL Textures - Tubes Only/mask_binocular.png differ diff --git a/mods/Borkel's Realistic Night Vision Goggles_backup/BepInEx/plugins/BorkelRNVG/MaskTextures/OPTIONAL Textures - Tubes Only/mask_old_monocular.png b/mods/Borkel's Realistic Night Vision Goggles_backup/BepInEx/plugins/BorkelRNVG/MaskTextures/OPTIONAL Textures - Tubes Only/mask_old_monocular.png new file mode 100644 index 0000000..89f092d Binary files /dev/null and b/mods/Borkel's Realistic Night Vision Goggles_backup/BepInEx/plugins/BorkelRNVG/MaskTextures/OPTIONAL Textures - Tubes Only/mask_old_monocular.png differ diff --git a/mods/Borkel's Realistic Night Vision Goggles_backup/BepInEx/plugins/BorkelRNVG/MaskTextures/OPTIONAL Textures - Tubes Only/mask_pnv.png b/mods/Borkel's Realistic Night Vision Goggles_backup/BepInEx/plugins/BorkelRNVG/MaskTextures/OPTIONAL Textures - Tubes Only/mask_pnv.png new file mode 100644 index 0000000..4fb470f Binary files /dev/null and b/mods/Borkel's Realistic Night Vision Goggles_backup/BepInEx/plugins/BorkelRNVG/MaskTextures/OPTIONAL Textures - Tubes Only/mask_pnv.png differ diff --git a/mods/Borkel's Realistic Night Vision Goggles_backup/BepInEx/plugins/BorkelRNVG/MaskTextures/mask_anvis.png b/mods/Borkel's Realistic Night Vision Goggles_backup/BepInEx/plugins/BorkelRNVG/MaskTextures/mask_anvis.png new file mode 100644 index 0000000..26bfe53 Binary files /dev/null and b/mods/Borkel's Realistic Night Vision Goggles_backup/BepInEx/plugins/BorkelRNVG/MaskTextures/mask_anvis.png differ diff --git a/mods/Borkel's Realistic Night Vision Goggles_backup/BepInEx/plugins/BorkelRNVG/MaskTextures/mask_binocular.png b/mods/Borkel's Realistic Night Vision Goggles_backup/BepInEx/plugins/BorkelRNVG/MaskTextures/mask_binocular.png new file mode 100644 index 0000000..6fb7fe3 Binary files /dev/null and b/mods/Borkel's Realistic Night Vision Goggles_backup/BepInEx/plugins/BorkelRNVG/MaskTextures/mask_binocular.png differ diff --git a/mods/Borkel's Realistic Night Vision Goggles_backup/BepInEx/plugins/BorkelRNVG/MaskTextures/mask_old_monocular.png b/mods/Borkel's Realistic Night Vision Goggles_backup/BepInEx/plugins/BorkelRNVG/MaskTextures/mask_old_monocular.png new file mode 100644 index 0000000..6773512 Binary files /dev/null and b/mods/Borkel's Realistic Night Vision Goggles_backup/BepInEx/plugins/BorkelRNVG/MaskTextures/mask_old_monocular.png differ diff --git a/mods/Borkel's Realistic Night Vision Goggles_backup/BepInEx/plugins/BorkelRNVG/MaskTextures/mask_pnv.png b/mods/Borkel's Realistic Night Vision Goggles_backup/BepInEx/plugins/BorkelRNVG/MaskTextures/mask_pnv.png new file mode 100644 index 0000000..71e0e11 Binary files /dev/null and b/mods/Borkel's Realistic Night Vision Goggles_backup/BepInEx/plugins/BorkelRNVG/MaskTextures/mask_pnv.png differ diff --git a/mods/Borkel's Realistic Night Vision Goggles_backup/BepInEx/plugins/BorkelRNVG/MaskTextures/mask_thermal.png b/mods/Borkel's Realistic Night Vision Goggles_backup/BepInEx/plugins/BorkelRNVG/MaskTextures/mask_thermal.png new file mode 100644 index 0000000..c1fac87 Binary files /dev/null and b/mods/Borkel's Realistic Night Vision Goggles_backup/BepInEx/plugins/BorkelRNVG/MaskTextures/mask_thermal.png differ diff --git a/mods/Borkel's Realistic Night Vision Goggles_backup/BepInEx/plugins/BorkelRNVG/MaskTextures/pixel_mask1.png b/mods/Borkel's Realistic Night Vision Goggles_backup/BepInEx/plugins/BorkelRNVG/MaskTextures/pixel_mask1.png new file mode 100644 index 0000000..4aff48f Binary files /dev/null and b/mods/Borkel's Realistic Night Vision Goggles_backup/BepInEx/plugins/BorkelRNVG/MaskTextures/pixel_mask1.png differ diff --git a/mods/Borkel's Realistic Night Vision Goggles_backup/BepInEx/plugins/BorkelRNVG/README.txt b/mods/Borkel's Realistic Night Vision Goggles_backup/BepInEx/plugins/BorkelRNVG/README.txt new file mode 100644 index 0000000..7650fca --- /dev/null +++ b/mods/Borkel's Realistic Night Vision Goggles_backup/BepInEx/plugins/BorkelRNVG/README.txt @@ -0,0 +1,3 @@ +Place any textures you want to use as masks in MaskTextures, just make sure they are PNGs and have the name of the NVG mask you want to replace. +If you want to change the area where the NVG effect is applied, you have to change the textures in LensTextures +Each LensTexture has to be the same size as its corresponding MaskTexture \ No newline at end of file diff --git a/mods/Borkel's Realistic Night Vision Goggles_backup/BepInEx/plugins/BorkelRNVG/Sounds/gatingKnob.wav b/mods/Borkel's Realistic Night Vision Goggles_backup/BepInEx/plugins/BorkelRNVG/Sounds/gatingKnob.wav new file mode 100644 index 0000000..a93089d Binary files /dev/null and b/mods/Borkel's Realistic Night Vision Goggles_backup/BepInEx/plugins/BorkelRNVG/Sounds/gatingKnob.wav differ diff --git a/mods/Borkel's Realistic Night Vision Goggles_backup/BepInEx/plugins/BorkelRNVG/Sounds/gatingKnob_alt.wav b/mods/Borkel's Realistic Night Vision Goggles_backup/BepInEx/plugins/BorkelRNVG/Sounds/gatingKnob_alt.wav new file mode 100644 index 0000000..34e4163 Binary files /dev/null and b/mods/Borkel's Realistic Night Vision Goggles_backup/BepInEx/plugins/BorkelRNVG/Sounds/gatingKnob_alt.wav differ diff --git a/mods/Borkel's Realistic Night Vision Goggles_backup/BepInEx/plugins/BorkelRNVG/WindowsInput.dll b/mods/Borkel's Realistic Night Vision Goggles_backup/BepInEx/plugins/BorkelRNVG/WindowsInput.dll new file mode 100644 index 0000000..cc45349 Binary files /dev/null and b/mods/Borkel's Realistic Night Vision Goggles_backup/BepInEx/plugins/BorkelRNVG/WindowsInput.dll differ diff --git a/mods/Borkel's Realistic Night Vision Goggles_backup/BepInEx/plugins/BorkelRNVG/borkel_realisticnvg_shaders b/mods/Borkel's Realistic Night Vision Goggles_backup/BepInEx/plugins/BorkelRNVG/borkel_realisticnvg_shaders new file mode 100644 index 0000000..67f9d61 Binary files /dev/null and b/mods/Borkel's Realistic Night Vision Goggles_backup/BepInEx/plugins/BorkelRNVG/borkel_realisticnvg_shaders differ diff --git a/mods/Borkel's Realistic Night Vision Goggles_backup/meta.ini b/mods/Borkel's Realistic Night Vision Goggles_backup/meta.ini new file mode 100644 index 0000000..405393a --- /dev/null +++ b/mods/Borkel's Realistic Night Vision Goggles_backup/meta.ini @@ -0,0 +1,28 @@ +[General] +gameName=spt +modid=0 +version=d2025.1.12.0 +newestVersion= +category="1," +nexusFileStatus=1 +installationFile=BRNVG-1.5.9.zip +repository=Nexus +ignoredVersion= +comments= +notes= +nexusDescription= +url= +hasCustomURL=false +lastNexusQuery= +lastNexusUpdate= +nexusLastModified=2025-01-12T11:47:39Z +nexusCategory=0 +converted=false +validated=false +color=@Variant(\0\0\0\x43\0\xff\xff\0\0\0\0\0\0\0\0) +tracked=0 + +[installedFiles] +1\modid=0 +1\fileid=0 +size=1 diff --git a/mods/Borkel's Realistic Night Vision Goggles_backup/user/mods/BRNVG_N-15Adapter/LICENSE b/mods/Borkel's Realistic Night Vision Goggles_backup/user/mods/BRNVG_N-15Adapter/LICENSE new file mode 100644 index 0000000..5dc6909 --- /dev/null +++ b/mods/Borkel's Realistic Night Vision Goggles_backup/user/mods/BRNVG_N-15Adapter/LICENSE @@ -0,0 +1,34 @@ +University of Illinois/NCSA Open Source License + +Copyright (c) 2021 . All rights reserved. + +Developed by: SPT-Aki + + https://www.offline-tarkov.com + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation files +(the "Software"), to deal with the Software without restriction, +including without limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of the Software, +and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +* Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimers. + +* Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimers in the + documentation and/or other materials provided with the distribution. + +* Neither the names of , SPT-Aki nor the names of its + contributors may be used to endorse or promote products derived from + this Software without specific prior written permission. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH +THE SOFTWARE. \ No newline at end of file diff --git a/mods/Borkel's Realistic Night Vision Goggles_backup/user/mods/BRNVG_N-15Adapter/bundles.json b/mods/Borkel's Realistic Night Vision Goggles_backup/user/mods/BRNVG_N-15Adapter/bundles.json new file mode 100644 index 0000000..bd2fa59 --- /dev/null +++ b/mods/Borkel's Realistic Night Vision Goggles_backup/user/mods/BRNVG_N-15Adapter/bundles.json @@ -0,0 +1,24 @@ +{ + "manifest": [ + { + "key": "assets/content/items/equipment/customizable/gpnvg/nvg_l3_gpnvg-18_anvis.bundle", + "dependencyKeys": [] + }, + { + "key": "assets/content/items/equipment/nvg_pvs14/pvs14_textures.bundle", + "dependencyKeys": [] + }, + { + "key": "assets/content/items/equipment/customizable/pvs_14/nvg_pvs_14.bundle", + "dependencyKeys": [] + }, + { + "key": "assets/content/items/equipment/customizable/nvg_armasight_n-15/nvg_armasight_n-15.bundle", + "dependencyKeys": [] + }, + { + "key": "assets/content/items/equipment/customizable/nvg_alfa_pnv-10t/nvg_alfa_pnv-10t.bundle", + "dependencyKeys": [] + } + ] +} \ No newline at end of file diff --git a/mods/Borkel's Realistic Night Vision Goggles_backup/user/mods/BRNVG_N-15Adapter/bundles/assets/content/items/equipment/customizable/gpnvg/nvg_l3_gpnvg-18_anvis.bundle b/mods/Borkel's Realistic Night Vision Goggles_backup/user/mods/BRNVG_N-15Adapter/bundles/assets/content/items/equipment/customizable/gpnvg/nvg_l3_gpnvg-18_anvis.bundle new file mode 100644 index 0000000..13caf2b --- /dev/null +++ b/mods/Borkel's Realistic Night Vision Goggles_backup/user/mods/BRNVG_N-15Adapter/bundles/assets/content/items/equipment/customizable/gpnvg/nvg_l3_gpnvg-18_anvis.bundle @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:87e10871b499a49208710abee6f04d4f7b540b4fa06568f5f974f7fee5da2e0f +size 5485561 diff --git a/mods/Borkel's Realistic Night Vision Goggles_backup/user/mods/BRNVG_N-15Adapter/bundles/assets/content/items/equipment/customizable/nvg_alfa_pnv-10t/nvg_alfa_pnv-10t.bundle b/mods/Borkel's Realistic Night Vision Goggles_backup/user/mods/BRNVG_N-15Adapter/bundles/assets/content/items/equipment/customizable/nvg_alfa_pnv-10t/nvg_alfa_pnv-10t.bundle new file mode 100644 index 0000000..3be8b3a --- /dev/null +++ b/mods/Borkel's Realistic Night Vision Goggles_backup/user/mods/BRNVG_N-15Adapter/bundles/assets/content/items/equipment/customizable/nvg_alfa_pnv-10t/nvg_alfa_pnv-10t.bundle @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:35d4efcc35d35f15aeafdf269d0df1fcec4e4548e5142e0e8a6938ac89447191 +size 5398309 diff --git a/mods/Borkel's Realistic Night Vision Goggles_backup/user/mods/BRNVG_N-15Adapter/bundles/assets/content/items/equipment/customizable/nvg_armasight_n-15/nvg_armasight_n-15.bundle b/mods/Borkel's Realistic Night Vision Goggles_backup/user/mods/BRNVG_N-15Adapter/bundles/assets/content/items/equipment/customizable/nvg_armasight_n-15/nvg_armasight_n-15.bundle new file mode 100644 index 0000000..8c76678 --- /dev/null +++ b/mods/Borkel's Realistic Night Vision Goggles_backup/user/mods/BRNVG_N-15Adapter/bundles/assets/content/items/equipment/customizable/nvg_armasight_n-15/nvg_armasight_n-15.bundle @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3cf34cce8c00ea6ed8841ff960ba99a2d2e2089e7fce3a28f288b90d2b5e490c +size 9497565 diff --git a/mods/Borkel's Realistic Night Vision Goggles_backup/user/mods/BRNVG_N-15Adapter/bundles/assets/content/items/equipment/customizable/pvs_14/nvg_pvs_14.bundle b/mods/Borkel's Realistic Night Vision Goggles_backup/user/mods/BRNVG_N-15Adapter/bundles/assets/content/items/equipment/customizable/pvs_14/nvg_pvs_14.bundle new file mode 100644 index 0000000..145314e --- /dev/null +++ b/mods/Borkel's Realistic Night Vision Goggles_backup/user/mods/BRNVG_N-15Adapter/bundles/assets/content/items/equipment/customizable/pvs_14/nvg_pvs_14.bundle @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e7c5dd5cd52209657350eb134fe07e222f15c23ea54973140f4346a3e31ced96 +size 369579 diff --git a/mods/Borkel's Realistic Night Vision Goggles_backup/user/mods/BRNVG_N-15Adapter/bundles/assets/content/items/equipment/nvg_pvs14/pvs14_textures.bundle b/mods/Borkel's Realistic Night Vision Goggles_backup/user/mods/BRNVG_N-15Adapter/bundles/assets/content/items/equipment/nvg_pvs14/pvs14_textures.bundle new file mode 100644 index 0000000..7a6fda7 --- /dev/null +++ b/mods/Borkel's Realistic Night Vision Goggles_backup/user/mods/BRNVG_N-15Adapter/bundles/assets/content/items/equipment/nvg_pvs14/pvs14_textures.bundle @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:eef96e228f294b53c6b1a2a9da93c609354b716e3d37f2bc56c26460d3f68a3c +size 5073401 diff --git a/mods/Borkel's Realistic Night Vision Goggles_backup/user/mods/BRNVG_N-15Adapter/optional black GPNVG-18/INSTALLATION.txt b/mods/Borkel's Realistic Night Vision Goggles_backup/user/mods/BRNVG_N-15Adapter/optional black GPNVG-18/INSTALLATION.txt new file mode 100644 index 0000000..0d60cc0 --- /dev/null +++ b/mods/Borkel's Realistic Night Vision Goggles_backup/user/mods/BRNVG_N-15Adapter/optional black GPNVG-18/INSTALLATION.txt @@ -0,0 +1 @@ +place in "BRNVG_N-15Adapter\bundles\assets\content\items\equipment\customizable\gpnvg" \ No newline at end of file diff --git a/mods/Borkel's Realistic Night Vision Goggles_backup/user/mods/BRNVG_N-15Adapter/optional black GPNVG-18/nvg_l3_gpnvg-18_anvis.bundle b/mods/Borkel's Realistic Night Vision Goggles_backup/user/mods/BRNVG_N-15Adapter/optional black GPNVG-18/nvg_l3_gpnvg-18_anvis.bundle new file mode 100644 index 0000000..b7614ec --- /dev/null +++ b/mods/Borkel's Realistic Night Vision Goggles_backup/user/mods/BRNVG_N-15Adapter/optional black GPNVG-18/nvg_l3_gpnvg-18_anvis.bundle @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:adb3e30152b26df06fc0b8307a7e400d73e4d1816181dc50281423e9ad3e6b19 +size 5485561 diff --git a/mods/Borkel's Realistic Night Vision Goggles_backup/user/mods/BRNVG_N-15Adapter/package.json b/mods/Borkel's Realistic Night Vision Goggles_backup/user/mods/BRNVG_N-15Adapter/package.json new file mode 100644 index 0000000..1774add --- /dev/null +++ b/mods/Borkel's Realistic Night Vision Goggles_backup/user/mods/BRNVG_N-15Adapter/package.json @@ -0,0 +1,24 @@ +{ + "name": "BRNVG - N-15 Adapter", + "version": "1.0.1", + "main": "src/ModularNVG.js", + "license": "CC BY-NC-SA 3.0", + "author": "Borkel", + "sptVersion": "~3.10", + "scripts": { + "setup": "npm i", + "build": "node ./packageBuild.ts" + }, + "isBundleMod": true, + "devDependencies": { + "@types/node": "16.18.10", + "@typescript-eslint/eslint-plugin": "5.46.1", + "@typescript-eslint/parser": "5.46.1", + "bestzip": "2.2.1", + "eslint": "8.30.0", + "fs-extra": "11.1.0", + "glob": "8.0.3", + "tsyringe": "4.7.0", + "typescript": "4.9.4" + } +} \ No newline at end of file diff --git a/mods/Borkel's Realistic Night Vision Goggles_backup/user/mods/BRNVG_N-15Adapter/src/ModularNVG.js b/mods/Borkel's Realistic Night Vision Goggles_backup/user/mods/BRNVG_N-15Adapter/src/ModularNVG.js new file mode 100644 index 0000000..f6408bc --- /dev/null +++ b/mods/Borkel's Realistic Night Vision Goggles_backup/user/mods/BRNVG_N-15Adapter/src/ModularNVG.js @@ -0,0 +1,19 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +class ModularNVG { + postDBLoad(container) { + const Logger = container.resolve("WinstonLogger"); + const DB = container.resolve("DatabaseServer").getTables(); + const database = DB.templates.items; + for (let file in database) { + let fileData = database[file]; + //N-15 Adapter PNV-10T dovetail adapter + if (fileData._id === "5c0695860db834001b735461") { + fileData._props.Slots[0]._props.filters[0].Filter.push("5c066e3a0db834001b7353f0"); + Logger.info("[SBNV]: Your N-15s can also be mounted on helmets now!"); + } + } + } +} +module.exports = { mod: new ModularNVG }; +//# sourceMappingURL=ModularNVG.js.map \ No newline at end of file diff --git a/mods/Borkel's Realistic Night Vision Goggles_backup/user/mods/BRNVG_N-15Adapter/src/ModularNVG.js.map b/mods/Borkel's Realistic Night Vision Goggles_backup/user/mods/BRNVG_N-15Adapter/src/ModularNVG.js.map new file mode 100644 index 0000000..b0dd8df --- /dev/null +++ b/mods/Borkel's Realistic Night Vision Goggles_backup/user/mods/BRNVG_N-15Adapter/src/ModularNVG.js.map @@ -0,0 +1 @@ +{"version":3,"file":"ModularNVG.js","sourceRoot":"","sources":["ModularNVG.ts"],"names":[],"mappings":";;AAOA,MAAM,UAAU;IAEZ,UAAU,CAAC,SAA8B;QAErC,MAAM,MAAM,GAAG,SAAS,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC;QAClD,MAAM,EAAE,GAAG,SAAS,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC,SAAS,EAAE,CAAC;QAC3D,MAAM,QAAQ,GAAG,EAAE,CAAC,SAAS,CAAC,KAAK,CAAC;QAEpC,KAAK,IAAI,IAAI,IAAI,QAAQ,EAAE,CAAC;YACxB,IAAI,QAAQ,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;YACvC,uCAAuC;YACvC,IAAI,QAAQ,CAAC,GAAG,KAAK,0BAA0B,EAAE,CAAC;gBACrC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,0BAA0B,CAAC,CAAC;gBAC/F,MAAM,CAAC,IAAI,CAAC,wDAAwD,CAAC,CAAC;YAC9D,CAAC;QACL,CAAC;IACL,CAAC;CACJ;AACD,MAAM,CAAC,OAAO,GAAG,EAAC,GAAG,EAAE,IAAI,UAAU,EAAC,CAAC"} \ No newline at end of file diff --git a/mods/Borkel's Realistic Night Vision Goggles_backup/user/mods/BRNVG_N-15Adapter/src/ModularNVG.ts b/mods/Borkel's Realistic Night Vision Goggles_backup/user/mods/BRNVG_N-15Adapter/src/ModularNVG.ts new file mode 100644 index 0000000..99a22fb --- /dev/null +++ b/mods/Borkel's Realistic Night Vision Goggles_backup/user/mods/BRNVG_N-15Adapter/src/ModularNVG.ts @@ -0,0 +1,26 @@ + +import { DependencyContainer } from "tsyringe"; +import {IPostDBLoadMod} from "@spt/models/external/IPostDBLoadMod"; +import { DatabaseServer } from "@spt/servers/DatabaseServer"; +import { ILogger } from "@spt/models/spt/utils/ILogger"; + + +class ModularNVG implements IPostDBLoadMod +{ + postDBLoad(container: DependencyContainer) + { + const Logger = container.resolve("WinstonLogger"); + const DB = container.resolve("DatabaseServer").getTables(); + const database = DB.templates.items; + + for (let file in database) { + let fileData = database[file]; + //N-15 Adapter PNV-10T dovetail adapter + if (fileData._id === "5c0695860db834001b735461") { + fileData._props.Slots[0]._props.filters[0].Filter.push("5c066e3a0db834001b7353f0"); + Logger.info("[SBNV]: Your N-15s can also be mounted on helmets now!"); + } + } + } +} +module.exports = {mod: new ModularNVG}; \ No newline at end of file diff --git a/mods/Borkel's Realistic Night Vision Goggles_backup/user/mods/BRNVG_N-15Adapter/tsconfig.json b/mods/Borkel's Realistic Night Vision Goggles_backup/user/mods/BRNVG_N-15Adapter/tsconfig.json new file mode 100644 index 0000000..8151310 --- /dev/null +++ b/mods/Borkel's Realistic Night Vision Goggles_backup/user/mods/BRNVG_N-15Adapter/tsconfig.json @@ -0,0 +1,25 @@ +{ + "compilerOptions": { + "allowJs": true, + "module": "CommonJS", + "target": "es2020", + "moduleResolution": "node", + "esModuleInterop": true, + "downlevelIteration": true, + "experimentalDecorators": true, + "emitDecoratorMetadata": true, + "resolveJsonModule": true, + "outDir": "tmp", + "baseUrl": ".", + "paths": { + "@spt-aki/*": ["./types/*"] + } + }, + "lib": [ + "es2020" + ], + "include": [ + "src/*", + "src/**/*" + ] +} \ No newline at end of file diff --git a/mods/Server Value Modifier/User/Mods/[SVM] Server Value Modifier/Greed.exe b/mods/Server Value Modifier/User/Mods/[SVM] Server Value Modifier/Greed.exe index 9707908..6333fe0 100644 Binary files a/mods/Server Value Modifier/User/Mods/[SVM] Server Value Modifier/Greed.exe and b/mods/Server Value Modifier/User/Mods/[SVM] Server Value Modifier/Greed.exe differ diff --git a/mods/Server Value Modifier/User/Mods/[SVM] Server Value Modifier/LICENSE b/mods/Server Value Modifier/User/Mods/[SVM] Server Value Modifier/LICENSE index 0a37488..8d21db0 100644 --- a/mods/Server Value Modifier/User/Mods/[SVM] Server Value Modifier/LICENSE +++ b/mods/Server Value Modifier/User/Mods/[SVM] Server Value Modifier/LICENSE @@ -1,7 +1,7 @@ Personal Use Source License (PUSL) Version 1.0 -Copyright © 2024, GhostFenixx +Copyright © 2025, GhostFenixx Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to use the Software for personal, non-commercial purposes only, subject to the following conditions: diff --git a/mods/Server Value Modifier/User/Mods/[SVM] Server Value Modifier/Loader/loader.json b/mods/Server Value Modifier/User/Mods/[SVM] Server Value Modifier/Loader/loader.json index a1b632c..9951fdb 100644 --- a/mods/Server Value Modifier/User/Mods/[SVM] Server Value Modifier/Loader/loader.json +++ b/mods/Server Value Modifier/User/Mods/[SVM] Server Value Modifier/Loader/loader.json @@ -1,3 +1,3 @@ { -"CurrentlySelectedPreset":"Default" +"CurrentlySelectedPreset":"null" } \ No newline at end of file diff --git a/mods/Server Value Modifier/User/Mods/[SVM] Server Value Modifier/package.json b/mods/Server Value Modifier/User/Mods/[SVM] Server Value Modifier/package.json index d151a8d..aeee86b 100644 --- a/mods/Server Value Modifier/User/Mods/[SVM] Server Value Modifier/package.json +++ b/mods/Server Value Modifier/User/Mods/[SVM] Server Value Modifier/package.json @@ -1,7 +1,7 @@ { "name": "SVM", "author": "GhostFenixx", - "version": "1.10.0", + "version": "1.10.1", "sptVersion": "3.10.x", "license": "PUSL", "devdependencies": {}, diff --git a/mods/Server Value Modifier/User/Mods/[SVM] Server Value Modifier/src/Arrays.json b/mods/Server Value Modifier/User/Mods/[SVM] Server Value Modifier/src/Arrays.json index 2752bbe..ec7ee77 100644 --- a/mods/Server Value Modifier/User/Mods/[SVM] Server Value Modifier/src/Arrays.json +++ b/mods/Server Value Modifier/User/Mods/[SVM] Server Value Modifier/src/Arrays.json @@ -5,7 +5,7 @@ "MRifle":["762x51", "68x51", "762х54R", "762x54r", "86x70", "127x55", "277", "BMG"], "MarkedKeys":["5780cf7f2459777de4559322", "5d80c60f86f77440373c4ece", "5d80c62a86f7744036212b3f", "5ede7a8229445733cb4c18e2", "63a3a93f8a56922e82001f5d", "64ccc25f95763a1ae376e447", "62987dfc402c7f69bf010923"], "traderArray": ["54cb50c76803fa8b248b4571", "54cb57776803fa99248b456e", "58330581ace78e27b8b10cee", "5935c25fb3acc3127c3d8cd9", "5a7c2eca46aef81a7ca2145d", "5ac3b934156ae10c4430e83c", "5c0647fdd443bc2504c2d371"], - "CasesID":["59fb016586f7746d0d4b423a","5783c43d2459774bbe137486","60b0f6c058e0b0481a09ad11","5e2af55f86f7746d4159f07c","59fb042886f7746c5005a7b2","59fb023c86f7746d0d4b423c","5b7c710788a4506dec015957","5aafbde786f774389d0cbc0f","5c127c4486f7745625356c13","5c093e3486f77430cb02e593","5aafbcd986f7745e590fff23","5c0a840b86f7742ffa4f2482","5b6d9ce188a4501afc1b2b25","5d235bb686f77443f4331278","59fafd4b86f7745ca07e1232","590c60fc86f77412b13fddcf","567143bf4bdc2d1a0f8b4567","5c093db286f7740a1b2617e3","619cbf7d23893217ec30b689","619cbf9e0a7c3a1a2731940a","62a09d3bcf4a99369e262447"], + "CasesID":["59fb016586f7746d0d4b423a","5783c43d2459774bbe137486","60b0f6c058e0b0481a09ad11","5e2af55f86f7746d4159f07c","59fb042886f7746c5005a7b2","59fb023c86f7746d0d4b423c","5b7c710788a4506dec015957","5aafbde786f774389d0cbc0f","5c127c4486f7745625356c13","5c093e3486f77430cb02e593","5aafbcd986f7745e590fff23","5c0a840b86f7742ffa4f2482","5b6d9ce188a4501afc1b2b25","5d235bb686f77443f4331278","59fafd4b86f7745ca07e1232","590c60fc86f77412b13fddcf","567143bf4bdc2d1a0f8b4567","5c093db286f7740a1b2617e3","619cbf7d23893217ec30b689","619cbf9e0a7c3a1a2731940a","62a09d3bcf4a99369e262447","66bc98a01a47be227a5e956e"], "SecConID":["544a11ac4bdc2d470e8b456a","5c093ca986f7740a1867ab12","5857a8b324597729ab0a0e7d","59db794186f77448bc595262","5857a8bc2459772bad15db29","665ee77ccf2d642e98220bca","5732ee6a24597719ae0c0281","64f6f4c5911bcdfe8b03b0dc"], "AIAmount":["AsOnline","Low","Medium","High","Horde","NoBots"], "AIDifficulty":["AsOnline","Easy","Medium","Hard","Impossible","Random"], diff --git a/mods/Server Value Modifier/User/Mods/[SVM] Server Value Modifier/src/Misc.json b/mods/Server Value Modifier/User/Mods/[SVM] Server Value Modifier/src/Misc.json index ca63ab8..76119f4 100644 --- a/mods/Server Value Modifier/User/Mods/[SVM] Server Value Modifier/src/Misc.json +++ b/mods/Server Value Modifier/User/Mods/[SVM] Server Value Modifier/src/Misc.json @@ -58,7 +58,7 @@ "Stay Hydrated", "Have you tried Gray Zone Warfare? :D", "Still filled with bugs, don't worry", - "Pls leave a like an subscribe, don't forget to click a bell button", + "Pls leave a like and subscribe, don't forget to click a bell button", "Google Clearly doesn't like me ;-;", "Name of your PMC is disgusting, please revaluate your life choices", "Why do you want to carry 2000 rounds in one slot?", @@ -79,14 +79,12 @@ "What?", "Really, stop looking here, play the game already >:C", "Someday I'll paste whole Bee movie script here", - "Seriously, Roseheart, stop posting those on r/sptarkov.", "They added a Deagle in the game...Makes me miss KMC once again", "Swedish siesta is fun ngl", "Yep, people still seem to fail to install this mod", "3.9.8 huh? SPT lads do stack those numbers high", "Cats are still superior than dogs, CWX.", "Someday the war will be over and world won't be the same...", - "Damn, Stalker 2 footage is juicy", "Do yourself a favor, stop shitposting", "If SPT can go 3.10, so is SVM can go 1.10", "Show must go on!", @@ -116,5 +114,14 @@ "Want some music recommendation? Check Imminence.", "Want some music recommendation? Check Cantervice.", "You better not forget to take splint with you this time", + "More music? Fine: Saint Asonia, Alesti, Memphis May Fire", + "Not really hyped for 2025 ngl", + "Four letters is better than three", + "No, these messages is not made by ChatGPT", + "I finally tried stalker 2, could've been better", + "Unironically gonna listen to C418", + "Want some DnB? Celldweller, Raizer, Blue Stahli", + "I hate winter", + "Astrobot being GOTY is a joke", "You cannot Escape From -REDACTED BY LICENSE VIOLATION-"] } \ No newline at end of file diff --git a/mods/Server Value Modifier/User/Mods/[SVM] Server Value Modifier/src/SVM.js b/mods/Server Value Modifier/User/Mods/[SVM] Server Value Modifier/src/SVM.js index 13b0a60..5987015 100644 --- a/mods/Server Value Modifier/User/Mods/[SVM] Server Value Modifier/src/SVM.js +++ b/mods/Server Value Modifier/User/Mods/[SVM] Server Value Modifier/src/SVM.js @@ -1,2407 +1,2577 @@ "use strict"; class MainSVM { - preSptLoad(container) { - const Logger = container.resolve("WinstonLogger"); - try { //Checking for loader.json, if doesn't exist - throw a message, disable the mod. - const PresetLoader = require('../Loader/loader.json'); - if (PresetLoader.CurrentlySelectedPreset == null || PresetLoader.CurrentlySelectedPreset == "null") { - Logger.warning("[SVM] Null Preset detected, SVM is disabled, Most likely you're running this mod for the first time, head to the SVM mod folder and run the Greed.exe"); - return - } - const Config = require('../Presets/' + PresetLoader.CurrentlySelectedPreset + '.json'); - } - catch (e) { - const Logger = container.resolve("WinstonLogger"); - Logger.warning("\n[SVM] SVM is lacking loader file or there is an error, mod is disabled\n" + - "Most likely you're running this mod for the first time, head to the SVM mod folder and run the Greed.exe\n" + - "Don't forget to apply your changes...Really, hit that Apply button, it will create loader file\n" + - "[SVM] If it's Syntax error, edit it manually in loader.json or/and edit values with UIs properly\n" + - "Exception message below may help you distinguish what went wrong:\n"); - Logger.error(e.message + "\n"); - return - } - - const PresetLoader = require('../Loader/loader.json'); - const Config = require('../Presets/' + PresetLoader.CurrentlySelectedPreset + '.json'); - const StaticRouterModService = container.resolve("StaticRouterModService"); - const HttpResponse = container.resolve("HttpResponseUtil"); - const repeatableQuestController = container.resolve("RepeatableQuestController"); - - //PRE LOAD - QUESTS SECTION - if (Config.Quests.EnableQuests && Config.Quests.EnableQuestsMisc)//Horrible, as usual - { - try { - container.afterResolution("QuestCallbacks", (_t, result) => { - result.activityPeriods = (url, info, sessionID) => { - let Edited = repeatableQuestController.getClientRepeatableQuests(sessionID); - for (let quests in Edited) { - for (let act in Edited[quests].activeQuests) {//this needs to be trimmed as well, eventually. - if (Edited[quests].activeQuests[act].changeCost[0].count !== undefined) { - Edited[quests].activeQuests[act].changeCost[0].count = 5000 * Config.Quests.QuestCostMult; - } - if (Config.Quests.QuestRepToZero) { - Edited[quests].activeQuests[act].changeStandingCost = 0; - } - } - for (let inact in Edited[quests].inactiveQuests) { - if (Edited[quests].inactiveQuests[inact].changeCost[0].count !== undefined) { - Edited[quests].inactiveQuests[inact].changeCost[0].count = 5000 * Config.Quests.QuestCostMult; - } - if (Config.Quests.QuestRepToZero) { - Edited[quests].inactiveQuests[inact].changeStandingCost = 0; - } - } - for (let req in Edited[quests].changeRequirement) { - Edited[quests].changeRequirement[req].changeCost[0].count = 5000 * Config.Quests.QuestCostMult; - if (Config.Quests.QuestRepToZero) { - Edited[quests].changeRequirement[req].changeStandingCost = 0; - } - } + preSptLoad(container) { + const Logger = container.resolve("WinstonLogger"); + try { //Checking for loader.json, if doesn't exist - throw a message, disable the mod. + const PresetLoader = require('../Loader/loader.json'); + if (PresetLoader.CurrentlySelectedPreset == null || PresetLoader.CurrentlySelectedPreset == "null") { + Logger.warning("[SVM] Null Preset detected, SVM is disabled, Most likely you're running this mod for the first time, head to the SVM mod folder and run the Greed.exe"); + return } - return HttpResponse.getBody(Edited); - } - }, { frequency: "Always" }); - - container.afterResolution("QuestCallbacks", (_t, result) => { - result.changeRepeatableQuest = (pmcData, body, sessionID) => { - //const repeatableQuestController = container.resolve("RepeatableQuestController"); - let Edited = repeatableQuestController.changeRepeatableQuest(pmcData, body, sessionID); - for (let quests in Edited.profileChanges) { - for (let test in Edited.profileChanges[quests].repeatableQuests[0].changeRequirement) { - Edited.profileChanges[quests].repeatableQuests[0].changeRequirement[test].changeCost[0].count = 5000 * Config.Quests.QuestCostMult; - if (Config.Quests.QuestRepToZero) { - Edited.profileChanges[quests].repeatableQuests[0].changeRequirement[test].changeStandingCost = 0; - } - } - } - return Edited; - } - }, { frequency: "Always" }); - } - catch (e) { - Logger.error("[SVM] REPEATABLE QUEST HANDLED EXCEPTION - Something wrong attempting to change quest reroll price\n" + e.message + "\n"); - } - } - //PRE LOAD - RAIDS SECTION - if (Config.Raids.RaidEvents.Halloween || Config.Raids.RaidEvents.Christmas)//Extra check, just in case - { - StaticRouterModService.registerStaticRouter("EventOverride", - [ - { - url: "/client/game/version/validate", - action: (url, info, sessionID) => { - const DB = container.resolve("DatabaseService"); - const globalConfig = DB.getGlobals().config; - const configServer = container.resolve("ConfigServer"); - const SeasonalEventService = container.resolve("SeasonalEventService"); - const Events = configServer.getConfig("spt-seasonalevents"); - - //let event = []; - if (Config.Raids.RaidEvents.Christmas) { - SeasonalEventService.updateGlobalEvents(globalConfig, Events.events[1]); - } - if (Config.Raids.RaidEvents.Halloween) { - SeasonalEventService.updateGlobalEvents(globalConfig, Events.events[0]); - } - return HttpResponse.nullResponse(); - } - } - ], "spt"); - } - if (Config.Hideout.EnableHideout) { - if (Config.Hideout.Regeneration.OfflineRegen) { - container.afterResolution("GameController", (_t, result) => { - result.updateProfileHealthValues = (url, info, sessionID) => { - } - }, { frequency: "Always" }); - } - } - - if (Config.Raids.SafeExit) { - container.afterResolution("MatchCallbacks", (_t, result) => { - result.endLocalRaid = (url, info, sessionID) => { - if (info.results.result == "Left") { - info.results.result = "Runner" - } - const MatchController = container.resolve("MatchController"); - MatchController.endLocalRaid(sessionID, info); - return HttpResponse.nullResponse(); - } - }, { frequency: "Always" }); - } - if (Config.Raids.SaveGearAfterDeath) { - container.afterResolution("MatchCallbacks", (_t, result) => { - result.endLocalRaid = (url, info, sessionID) => { - if (info.results.result !== "Survived") { - info.results.result = "Runner" - } - const MatchController = container.resolve("MatchController"); - MatchController.endLocalRaid(sessionID, info); - return HttpResponse.nullResponse(); - } - }, { frequency: "Always" }); - } - //PRE LOAD - CSM SECTION - //Attempt to fix pockets if custom is not present - StaticRouterModService.registerStaticRouter("Revive Pockets", - [ - { - url: "/client/game/version/validate", - action: (url, info, sessionID) => { - let pmcData = container.resolve("ProfileHelper").getPmcProfile(sessionID); - let pockets; - try { - if (pmcData.Info.GameVersion == "unheard_edition") { - pockets = "65e080be269cbd5c5005e529"; - } - else { - pockets = "627a4e6b255f7527fb05a0f6"; - } - pmcData.Inventory.items.forEach((item) => { - if (item.slotId == "Pockets" && item._tpl == "a8edfb0bce53d103d3f62b9b") { - item._tpl = pockets; - } - }) - return HttpResponse.nullResponse(); - } - catch (e) { - Logger.error("[SVM] CSM CUSTOM POCKETS - New profile detected, Cancelling function, restart the game to fix it.\n" + e.message) - return HttpResponse.nullResponse(); - } - } - }], "spt"); - if (Config.CSM.EnableCSM && Config.CSM.CustomPocket) { - StaticRouterModService.registerStaticRouter("CustomPocket", - [ - { - url: "/client/game/version/validate", - action: (url, info, sessionID) => { - let pmcData = container.resolve("ProfileHelper").getPmcProfile(sessionID); - try { - pmcData.Inventory.items.forEach((item) => { - if (item.slotId == "Pockets") { - item._tpl = "a8edfb0bce53d103d3f62b9b"; - } - }) - return HttpResponse.nullResponse(); - } - catch (e) { - Logger.error("[SVM] CSM CUSTOM POCKETS - New profile detected, Cancelling function, restart the game to fix it.\n" + e.message) - return HttpResponse.nullResponse(); - } - } - }], "spt"); - } - //HEALTH + SCAV FUNCTIONS - if (Config.Player.EnableHealth || Config.Scav.EnableScavHealth || Config.Scav.ScavCustomPockets || Config.Player.EnableStats || Config.Scav.EnableStats) //TO OVERRIDE HEALTH, STATS + CURRENT SCAV HEALTH, STATS AND POCKETS BEFORE RAID - { - StaticRouterModService.registerStaticRouter("EditHealth", - [ - { - url: "/client/game/version/validate", - action: (url, info, sessionID) => { - try { - let pmcData = container.resolve("ProfileHelper").getPmcProfile(sessionID); - let scavData = container.resolve("ProfileHelper").getScavProfile(sessionID); - if (Config.Player.EnableStats) { - pmcData.Health.Energy.Maximum = Config.Player.PMCStats.MaxEnergy; - pmcData.Health.Hydration.Maximum = Config.Player.PMCStats.MaxHydration; - } - if (Config.Scav.EnableStats) { - scavData.Health.Energy.Maximum = Config.Scav.ScavStats.MaxEnergy; - scavData.Health.Hydration.Maximum = Config.Scav.ScavStats.MaxHydration; - } - if (Config.Player.EnableHealth) { - HealthEdit(pmcData, Config.Player.Health.Head, Config.Player.Health.Chest, Config.Player.Health.Stomach, Config.Player.Health.LeftArm, Config.Player.Health.LeftLeg, Config.Player.Health.RightArm, Config.Player.Health.RightLeg, "Maximum"); - } - if (Config.Scav.EnableScavHealth) { - HealthEdit(scavData, Config.Scav.Health.Head, Config.Scav.Health.Chest, Config.Scav.Health.Stomach, Config.Scav.Health.LeftArm, Config.Scav.Health.LeftLeg, Config.Scav.Health.RightArm, Config.Scav.Health.RightLeg, "Current"); - HealthEdit(scavData, Config.Scav.Health.Head, Config.Scav.Health.Chest, Config.Scav.Health.Stomach, Config.Scav.Health.LeftArm, Config.Scav.Health.LeftLeg, Config.Scav.Health.RightArm, Config.Scav.Health.RightLeg, "Maximum"); - } - if (Config.Scav.ScavCustomPockets) { - scavData.Inventory.items.forEach((item) => { - if (item.slotId == "Pockets") { - item._tpl = "a8edfb0bce53d103d3f6219b"; - } - }) - } - return HttpResponse.nullResponse(); - } - catch (e) { - Logger.error("[SVM] PMC/SCAV HEALTH/STATS - Didn't manage to apply settings, new profile?\n" + e) - return HttpResponse.nullResponse(); - } - } - }], "spt"); - } - if (Config.Scav.EnableScavHealth || Config.Scav.ScavCustomPockets) { // TO OVERRIDE NEXT SCAVS HEALTH + POCKETS - //May Omnissiah save our souls, have to use both because register affects deaths and resolution affects extracts. Don't ask - container.afterResolution("ProfileController", (_t, result) => { - result.generatePlayerScav = (sessionID) => { - const playerScavGenerator = container.resolve("PlayerScavGenerator"); - const scavData = playerScavGenerator.generate(sessionID); - if (Config.Scav.EnableStats) { - scavData.Health.Energy.Maximum = Config.Scav.ScavStats.MaxEnergy; - scavData.Health.Hydration.Maximum = Config.Scav.ScavStats.MaxHydration; - } - HealthEdit(scavData, Config.Scav.Health.Head, Config.Scav.Health.Chest, Config.Scav.Health.Stomach, Config.Scav.Health.LeftArm, Config.Scav.Health.LeftLeg, Config.Scav.Health.RightArm, Config.Scav.Health.RightLeg, "Current"); - HealthEdit(scavData, Config.Scav.Health.Head, Config.Scav.Health.Chest, Config.Scav.Health.Stomach, Config.Scav.Health.LeftArm, Config.Scav.Health.LeftLeg, Config.Scav.Health.RightArm, Config.Scav.Health.RightLeg, "Maximum"); - if (Config.Scav.ScavCustomPockets) { - scavData.Inventory.items.forEach((item) => { - if (item.slotId == "Pockets") { - item._tpl = "a8edfb0bce53d103d3f6219b"; - } - }) - } - return scavData; - } - }, { frequency: "Always" }); - - StaticRouterModService.registerStaticRouter("EditHealthv2", - [ - { - url: "/raid/profile/save", - action: (url, info, sessionID) => { - if (info.exit !== "survived" && info.exit !== "runner" && info.isPlayerScav) // 3.9.0 If statement for avoiding rerolling survived SCAV, biggest issue of 1.8.3 - { - const saveServer = container.resolve("SaveServer"); - const playerScavGenerator = container.resolve("PlayerScavGenerator"); - const scavData = playerScavGenerator.generate(sessionID); - HealthEdit(scavData, Config.Scav.Health.Head, Config.Scav.Health.Chest, Config.Scav.Health.Stomach, Config.Scav.Health.LeftArm, Config.Scav.Health.LeftLeg, Config.Scav.Health.RightArm, Config.Scav.Health.RightLeg, "Current"); - HealthEdit(scavData, Config.Scav.Health.Head, Config.Scav.Health.Chest, Config.Scav.Health.Stomach, Config.Scav.Health.LeftArm, Config.Scav.Health.LeftLeg, Config.Scav.Health.RightArm, Config.Scav.Health.RightLeg, "Maximum"); - if (Config.Scav.ScavCustomPockets) { - scavData.Inventory.items.forEach((item) => { - if (item.slotId == "Pockets") { - item._tpl = "a8edfb0bce53d103d3f6219b"; - } - }) - } - saveServer.getProfile(sessionID).characters.scav = scavData; - } - return HttpResponse.nullResponse(); - } - }], "spt"); - } - function HealthEdit(Data, Head, Chest, Stomach, LeftArm, LeftLeg, RightArm, RightLeg, CurMax) { - try { - Data.Health.BodyParts["Head"].Health[CurMax] = Head - Data.Health.BodyParts["Chest"].Health[CurMax] = Chest - Data.Health.BodyParts["Stomach"].Health[CurMax] = Stomach - Data.Health.BodyParts["LeftArm"].Health[CurMax] = LeftArm - Data.Health.BodyParts["LeftLeg"].Health[CurMax] = LeftLeg - Data.Health.BodyParts["RightArm"].Health[CurMax] = RightArm - Data.Health.BodyParts["RightLeg"].Health[CurMax] = RightLeg - } - catch { - Logger.error("[SVM] HEALTH EDIT - Something went wrong with trying to generate custom maximum health, new profile? \n" + e) - } - } - } - postDBLoad(container) { - const PreDBStart = performance.now(); - const Logger = container.resolve("WinstonLogger"); - try {//This is dumb piece of code is a handler so PostDB won't run after PreDB did throw a message that something ain't right with the loader. - const PresetLoader = require('../Loader/loader.json'); - const Config = require('../Presets/' + PresetLoader.CurrentlySelectedPreset + '.json'); - } - catch (e) { - return - } - //Config variables to asset for funcs. - const PresetLoader = require('../Loader/loader.json'); - const Config = require('../Presets/' + PresetLoader.CurrentlySelectedPreset + '.json'); - const Arrays = require('../src/Arrays.json'); - //DB redirects - const DB = container.resolve("DatabaseService").getTables(); - const hideout = DB.hideout; - const locations = DB.locations; - const traders = DB.traders; - const Quests = DB.templates.quests; - const suits = DB.templates.customization; - const items = DB.templates.items; - const globals = DB.globals.config; - const Bot = DB.bots.types - // Redirects to server internal configs. - const configServer = container.resolve("ConfigServer"); - const Inraid = configServer.getConfig("spt-inraid"); - const Repair = configServer.getConfig("spt-repair"); - const locs = configServer.getConfig("spt-location"); - const Airdrop = configServer.getConfig("spt-airdrop"); - const Ragfair = configServer.getConfig("spt-ragfair"); - const Insurance = configServer.getConfig("spt-insurance"); - const Health = configServer.getConfig("spt-health"); - const Bots = configServer.getConfig("spt-bot"); - const Quest = configServer.getConfig("spt-quest"); - const WeatherValues = configServer.getConfig("spt-weather"); - const trader = configServer.getConfig("spt-trader"); - const Events = configServer.getConfig("spt-seasonalevents"); - //const Inventory = configServer.getConfig("aki-inventory"); - const BlackItems = configServer.getConfig("spt-item"); - const PMC = configServer.getConfig("spt-pmc") - //############## FLEAMARKET SECTION ########### - if (Config.Fleamarket.EnableFleamarket) { - if (Config.Fleamarket.EnablePlayerOffers) { - globals.RagFair.minUserLevel = Config.Fleamarket.FleaMarketLevel; - Ragfair.dynamic.purchasesAreFoundInRaid = Config.Fleamarket.FleaFIR; - globals.RagFair.isOnlyFoundInRaidAllowed = Config.Fleamarket.FleaNoFIRSell; - Ragfair.dynamic.blacklist.enableBsgList = !Config.Fleamarket.DisableBSGList; - Ragfair.sell.fees = Config.Fleamarket.EnableFees; - Ragfair.sell.chance.base = Config.Fleamarket.Sell_chance; - Ragfair.sell.chance.sellMultiplier = Config.Fleamarket.Sell_mult; - Ragfair.sell.time.max = Config.Fleamarket.Tradeoffer_max; - Ragfair.sell.time.min = Config.Fleamarket.Tradeoffer_min; - globals.RagFair.ratingIncreaseCount = Config.Fleamarket.Rep_gain; - globals.RagFair.ratingDecreaseCount = Config.Fleamarket.Rep_loss; - - if (Config.Fleamarket.OverrideOffers) { - const offer = { - "from": -100000, - "to": 100000, - "count": Config.Fleamarket.SellOffersAmount - } - globals.RagFair.maxActiveOfferCount = [] - globals.RagFair.maxActiveOfferCount.push(offer) - } - } - //Bundle Chance - Ragfair.dynamic.pack.chancePercent = Config.Fleamarket.DynamicOffers.BundleOfferChance; - //Dynamic offers - Ragfair.dynamic.expiredOfferThreshold = Config.Fleamarket.DynamicOffers.ExpireThreshold; - //Min-Max - Ragfair.dynamic.offerItemCount.min = Config.Fleamarket.DynamicOffers.PerOffer_min; - Ragfair.dynamic.offerItemCount.max = Config.Fleamarket.DynamicOffers.PerOffer_max; - //Unifying the multiplier, not the best case scenario, but it is rather simple to comprehend and modify for common user, they'll never know >_> - Ragfair.dynamic.priceRanges.default.min = Config.Fleamarket.DynamicOffers.Price_min; - Ragfair.dynamic.priceRanges.default.max = Config.Fleamarket.DynamicOffers.Price_max; - Ragfair.dynamic.priceRanges.pack.min = Config.Fleamarket.DynamicOffers.Price_min; - Ragfair.dynamic.priceRanges.pack.max = Config.Fleamarket.DynamicOffers.Price_max; - Ragfair.dynamic.priceRanges.preset.min = Config.Fleamarket.DynamicOffers.Price_min; - Ragfair.dynamic.priceRanges.preset.max = Config.Fleamarket.DynamicOffers.Price_max; - Ragfair.dynamic.endTimeSeconds.min = Config.Fleamarket.DynamicOffers.Time_min * 60; - Ragfair.dynamic.endTimeSeconds.max = Config.Fleamarket.DynamicOffers.Time_max * 60; - Ragfair.dynamic.nonStackableCount.min = Config.Fleamarket.DynamicOffers.NonStack_min; - Ragfair.dynamic.nonStackableCount.max = Config.Fleamarket.DynamicOffers.NonStack_max; - Ragfair.dynamic.stackablePercent.min = Config.Fleamarket.DynamicOffers.Stack_min; - Ragfair.dynamic.stackablePercent.max = Config.Fleamarket.DynamicOffers.Stack_max; - //Currencies - Ragfair.dynamic.currencies["5449016a4bdc2d6f028b456f"] = Config.Fleamarket.DynamicOffers.Roubleoffers; - Ragfair.dynamic.currencies["5696686a4bdc2da3298b456a"] = Config.Fleamarket.DynamicOffers.Dollaroffers; - Ragfair.dynamic.currencies["569668774bdc2da2298b4568"] = Config.Fleamarket.DynamicOffers.Eurooffers; - //Wear condition in offers - if (Config.Fleamarket.EnableFleaConditions) - Ragfair.dynamic.condition["5422acb9af1c889c16000029"].max.min = parseFloat((Config.Fleamarket.FleaConditions.FleaWeapons_Min / 100).toFixed(2)) - Ragfair.dynamic.condition["543be5664bdc2dd4348b4569"].max.min = parseFloat((Config.Fleamarket.FleaConditions.FleaMedical_Min / 100).toFixed(2)) - Ragfair.dynamic.condition["5447e0e74bdc2d3c308b4567"].max.min = parseFloat((Config.Fleamarket.FleaConditions.FleaSpec_Min / 100).toFixed(2)) - Ragfair.dynamic.condition["543be5e94bdc2df1348b4568"].max.min = parseFloat((Config.Fleamarket.FleaConditions.FleaKeys_Min / 100).toFixed(2)) - Ragfair.dynamic.condition["5448e5284bdc2dcb718b4567"].max.min = parseFloat((Config.Fleamarket.FleaConditions.FleaVests_Min / 100).toFixed(2)) - Ragfair.dynamic.condition["57bef4c42459772e8d35a53b"].max.min = parseFloat((Config.Fleamarket.FleaConditions.FleaArmor_Min / 100).toFixed(2)) - Ragfair.dynamic.condition["543be6674bdc2df1348b4569"].max.min = parseFloat((Config.Fleamarket.FleaConditions.FleaFood_Min / 100).toFixed(2)) - Ragfair.dynamic.condition["5422acb9af1c889c16000029"].max.max = parseFloat((Config.Fleamarket.FleaConditions.FleaWeapons_Max / 100).toFixed(2)) - Ragfair.dynamic.condition["543be5664bdc2dd4348b4569"].max.max = parseFloat((Config.Fleamarket.FleaConditions.FleaMedical_Max / 100).toFixed(2)) - Ragfair.dynamic.condition["5447e0e74bdc2d3c308b4567"].max.max = parseFloat((Config.Fleamarket.FleaConditions.FleaSpec_Max / 100).toFixed(2)) - Ragfair.dynamic.condition["543be5e94bdc2df1348b4568"].max.max = parseFloat((Config.Fleamarket.FleaConditions.FleaKeys_Max / 100).toFixed(2)) - Ragfair.dynamic.condition["5448e5284bdc2dcb718b4567"].max.max = parseFloat((Config.Fleamarket.FleaConditions.FleaVests_Max / 100).toFixed(2)) - Ragfair.dynamic.condition["57bef4c42459772e8d35a53b"].max.max = parseFloat((Config.Fleamarket.FleaConditions.FleaArmor_Max / 100).toFixed(2)) - Ragfair.dynamic.condition["543be6674bdc2df1348b4569"].max.max = parseFloat((Config.Fleamarket.FleaConditions.FleaFood_Max / 100).toFixed(2)) - } - //############## LOOT SECTION ################# - if (Config.Loot.EnableLoot) { - //loose loot mults - locs.looseLootMultiplier.bigmap = Config.Loot.Locations.Streets.Loose; - locs.looseLootMultiplier.factory4_day = Config.Loot.Locations.FactoryDay.Loose; - locs.looseLootMultiplier.factory4_night = Config.Loot.Locations.FactoryNight.Loose; - locs.looseLootMultiplier.interchange = Config.Loot.Locations.Interchange.Loose; - locs.looseLootMultiplier.laboratory = Config.Loot.Locations.Laboratory.Loose; - locs.looseLootMultiplier.rezervbase = Config.Loot.Locations.Reserve.Loose; - locs.looseLootMultiplier.shoreline = Config.Loot.Locations.Shoreline.Loose; - locs.looseLootMultiplier.woods = Config.Loot.Locations.Woods.Loose; - locs.looseLootMultiplier.lighthouse = Config.Loot.Locations.Lighthouse.Loose; - locs.looseLootMultiplier.tarkovstreets = Config.Loot.Locations.Streets.Loose; - locs.looseLootMultiplier.sandbox = Config.Loot.Locations.Sandbox.Loose; - locs.looseLootMultiplier.sandbox_high = Config.Loot.Locations.SandboxHard.Loose; - //container loot mults - locs.staticLootMultiplier.bigmap = Config.Loot.Locations.Bigmap.Container; - locs.staticLootMultiplier.factory4_day = Config.Loot.Locations.FactoryDay.Container; - locs.staticLootMultiplier.factory4_night = Config.Loot.Locations.FactoryNight.Container; - locs.staticLootMultiplier.interchange = Config.Loot.Locations.Interchange.Container; - locs.staticLootMultiplier.laboratory = Config.Loot.Locations.Laboratory.Container; - locs.staticLootMultiplier.rezervbase = Config.Loot.Locations.Reserve.Container; - locs.staticLootMultiplier.shoreline = Config.Loot.Locations.Shoreline.Container; - locs.staticLootMultiplier.woods = Config.Loot.Locations.Woods.Container; - locs.staticLootMultiplier.lighthouse = Config.Loot.Locations.Lighthouse.Container; - locs.staticLootMultiplier.tarkovstreets = Config.Loot.Locations.Streets.Container; - locs.staticLootMultiplier.sandbox = Config.Loot.Locations.Sandbox.Container; - locs.staticLootMultiplier.sandbox_high = Config.Loot.Locations.SandboxHard.Container; - locs.containerRandomisationSettings.enabled = !Config.Loot.Locations.AllContainers - //############## AIRDROPS SECTION ################## - locations["bigmap"].base.AirdropParameters[0].PlaneAirdropChance = parseFloat((Config.Loot.Airdrops.Bigmap_air / 100).toFixed(2)); - locations["shoreline"].base.AirdropParameters[0].PlaneAirdropChance = parseFloat((Config.Loot.Airdrops.Shoreline_air / 100).toFixed(2)); - locations["rezervbase"].base.AirdropParameters[0].PlaneAirdropChance = parseFloat((Config.Loot.Airdrops.Reserve_air / 100).toFixed(2)); - locations["lighthouse"].base.AirdropParameters[0].PlaneAirdropChance = parseFloat((Config.Loot.Airdrops.Lighthouse_air / 100).toFixed(2)); - locations["interchange"].base.AirdropParameters[0].PlaneAirdropChance = parseFloat((Config.Loot.Airdrops.Interchange_air / 100).toFixed(2)); - locations["tarkovstreets"].base.AirdropParameters[0].PlaneAirdropChance = parseFloat((Config.Loot.Airdrops.Streets_air / 100).toFixed(2)); - locations["sandbox"].base.AirdropParameters[0].PlaneAirdropChance = parseFloat((Config.Loot.Airdrops.Sandbox_air / 100).toFixed(2)); - locations["sandbox_high"].base.AirdropParameters[0].PlaneAirdropChance = parseFloat((Config.Loot.Airdrops.Sandbox_air / 100).toFixed(2)); - locations["woods"].base.AirdropParameters[0].PlaneAirdropChance = parseFloat((Config.Loot.Airdrops.Woods_air / 100).toFixed(2)); - for (let timers in locations) { - if (timers != "develop" && timers != "base" && timers != "privatearea" && timers != "terminal" && timers != "factory4_day" && timers != "hideout" && timers != "laboratory" && timers != "factory4_night" && timers != "town" && timers != "suburbs") {// 3.10 need to rework. - locations[timers].base.AirdropParameters[0].PlaneAirdropStartMin = Config.Loot.Airdrops.AirtimeMin * 60; - locations[timers].base.AirdropParameters[0].PlaneAirdropStartMax = Config.Loot.Airdrops.AirtimeMax * 60; - } - } - let Mixed = Config.Loot.Airdrops.Mixed - let Weapon = Config.Loot.Airdrops.Weapon - let Barter = Config.Loot.Airdrops.Barter - let Medical = Config.Loot.Airdrops.Medical - AirdropContents("mixed", Mixed) - AirdropContents("weaponArmor", Weapon) - AirdropContents("barter", Barter) - AirdropContents("foodMedical", Medical) - } - //############## BOTS SECTION ################# - if (Config.Bots.EnableBots) { - for (let i in locations) { - if (i !== "base" && locations[i].base.BossLocationSpawn) { - for (let x in locations[i].base.BossLocationSpawn) { - switch (locations[i].base.BossLocationSpawn[x].BossName) { - case "bossBoar": - locations[i].base.BossLocationSpawn[x].BossChance = Config.Bots.AIChance.Kaban - break; - case "bossKolontay": - if (i == "sandbox_high") { - locations[i].base.BossLocationSpawn[x].BossChance = Config.Bots.AIChance.KolontayGZ - } - if (i == "tarkovstreets") { - locations[i].base.BossLocationSpawn[x].BossChance = Config.Bots.AIChance.KolontayStreets - } - break; - case "bossPartisan": - // if (i == "bigmap") { Controlled by trigger, ignored for now. - // locations[i].base.BossLocationSpawn[x].BossChance = Config.Bots.AIChance.PartisanCustoms - // } - if (i == "shoreline") { - locations[i].base.BossLocationSpawn[x].BossChance = Config.Bots.AIChance.PartisanShoreline - } - if (i == "lighthouse") { - locations[i].base.BossLocationSpawn[x].BossChance = Config.Bots.AIChance.PartisanLighthouse - } - if (i == "woods") { - locations[i].base.BossLocationSpawn[x].BossChance = Config.Bots.AIChance.PartisanWoods - } - break; - case "bossBully": - locations[i].base.BossLocationSpawn[x].BossChance = Config.Bots.AIChance.Reshala - break; - case "bossSanitar": - locations[i].base.BossLocationSpawn[x].BossChance = Config.Bots.AIChance.Sanitar - break; - case "bossKilla": - if (i == "interchange") { - locations[i].base.BossLocationSpawn[x].BossChance = Config.Bots.AIChance.Killa - } - break; - case "bossTagilla": - if (i == "factory4_day") { - locations[i].base.BossLocationSpawn[x].BossChance = Config.Bots.AIChance.Tagilla - } - if (i == "factory4_night") { - locations[i].base.BossLocationSpawn[x].BossChance = Config.Bots.AIChance.TagillaNight - } - break; - case "bossGluhar": - locations[i].base.BossLocationSpawn[x].BossChance = Config.Bots.AIChance.Glukhar - break; - case "bossKojaniy": - locations[i].base.BossLocationSpawn[x].BossChance = Config.Bots.AIChance.Shturman - break; - case "bossZryachiy": - locations[i].base.BossLocationSpawn[x].BossChance = Config.Bots.AIChance.Zryachiy - break; - case "exUsec": - locations[i].base.BossLocationSpawn[x].BossChance = Config.Bots.AIChance.Rogue - break; - case "bossKnight": - if (i == "woods") { - locations[i].base.BossLocationSpawn[x].BossChance = Config.Bots.AIChance.TrioWoods - } - if (i == "shoreline") { - locations[i].base.BossLocationSpawn[x].BossChance = Config.Bots.AIChance.TrioShoreline - } - if (i == "bigmap") { - locations[i].base.BossLocationSpawn[x].BossChance = Config.Bots.AIChance.Trio - } - if (i == "lighthouse") { - locations[i].base.BossLocationSpawn[x].BossChance = Config.Bots.AIChance.TrioLighthouse - } - break; - case "pmcBot": - if (i == "laboratory") { - locations[i].base.BossLocationSpawn[x].BossChance = Config.Bots.AIChance.RaiderLab - } - if (i == "rezervbase") { - locations[i].base.BossLocationSpawn[x].BossChance = Config.Bots.AIChance.RaiderReserve - } - break; - case "sectantPriest": - if (i == "factory4_night") { - locations[i].base.BossLocationSpawn[x].BossChance = Config.Bots.AIChance.CultistFactory - } - if (i == "woods") { - - locations[i].base.BossLocationSpawn[x].BossChance = Config.Bots.AIChance.CultistWoods - } - if (i == "bigmap") { - locations[i].base.BossLocationSpawn[x].BossChance = Config.Bots.AIChance.CultistCustoms - } - if (i == "shoreline") { - locations[i].base.BossLocationSpawn[x].BossChance = Config.Bots.AIChance.CultistShoreline - } - break; - } - } - } - } - const WepDur = Config.Bots.WeaponDurab; - const ArmorDur = Config.Bots.ArmorDurab; - const BotWepMinID = [WepDur.ScavMin, WepDur.MarksmanMin, WepDur.RaiderMin, WepDur.RogueMin, WepDur.PMCMin, WepDur.BossMin, WepDur.FollowerMin]; - const BotWepMaxID = [WepDur.ScavMax, WepDur.MarksmanMax, WepDur.RaiderMax, WepDur.RogueMax, WepDur.PMCMax, WepDur.BossMax, WepDur.FollowerMax]; - const BotArmorMinID = [ArmorDur.ScavMin, ArmorDur.MarksmanMin, ArmorDur.RaiderMin, ArmorDur.RogueMin, ArmorDur.PMCMin, ArmorDur.BossMin, ArmorDur.FollowerMin]; - const BotArmorMaxID = [ArmorDur.ScavMax, ArmorDur.MarksmanMax, ArmorDur.RaiderMax, ArmorDur.RogueMax, ArmorDur.PMCMax, ArmorDur.BossMax, ArmorDur.FollowerMax]; - - const BotTypeID = ["assault", "marksman", "pmcbot", "exusec", "pmc", "boss", "follower"] - for (let durab in BotTypeID) { - Bots.durability[BotTypeID[durab]].weapon.lowestMax = BotWepMinID[durab]; - Bots.durability[BotTypeID[durab]].weapon.highestMax = BotWepMaxID[durab]; - Bots.durability[BotTypeID[durab]].armor.maxDelta = 100 - BotArmorMinID[durab]; - Bots.durability[BotTypeID[durab]].armor.minDelta = 100 - BotArmorMaxID[durab]; - switch (BotTypeID[durab]) { - case "assault": - Bots.durability["cursedassault"].weapon.lowestMax = BotWepMinID[durab] - Bots.durability["cursedassault"].weapon.highestMax = BotWepMaxID[durab] - Bots.durability["cursedassault"].armor.maxDelta = 100 - BotArmorMinID[durab]; - Bots.durability["cursedassault"].armor.minDelta = 100 - BotArmorMaxID[durab]; - - Bots.durability["crazyassaultevent"].weapon.lowestMax = BotWepMinID[durab] - Bots.durability["crazyassaultevent"].weapon.highestMax = BotWepMaxID[durab] - Bots.durability["crazyassaultevent"].armor.maxDelta = 100 - BotArmorMinID[durab]; - Bots.durability["crazyassaultevent"].armor.minDelta = 100 - BotArmorMaxID[durab]; - break; - case "pmcbot": - Bots.durability["arenafighterevent"].weapon.lowestMax = BotWepMinID[durab] - Bots.durability["arenafighterevent"].weapon.highestMax = BotWepMaxID[durab] - Bots.durability["arenafighterevent"].armor.maxDelta = 100 - BotArmorMinID[durab]; - Bots.durability["arenafighterevent"].armor.minDelta = 100 - BotArmorMaxID[durab]; - break - case "boss": - Bots.durability["sectantpriest"].weapon.lowestMax = BotWepMinID[durab]; - Bots.durability["sectantpriest"].weapon.highestMax = BotWepMaxID[durab]; - Bots.durability["sectantpriest"].armor.maxDelta = 100 - BotArmorMinID[durab]; - Bots.durability["sectantpriest"].armor.minDelta = 100 - BotArmorMaxID[durab]; - break; - case "follower": - Bots.durability["sectantwarrior"].weapon.lowestMax = BotWepMinID[durab]; - Bots.durability["sectantwarrior"].weapon.highestMax = BotWepMaxID[durab]; - Bots.durability["sectantwarrior"].armor.maxDelta = 100 - BotArmorMinID[durab]; - Bots.durability["sectantwarrior"].armor.minDelta = 100 - BotArmorMaxID[durab]; - break; - } - } - } - //############## INSURANCE/REPAIR SECTION ############ - if (Config.Services.EnableServices) { - //Repair.priceMultiplier = Config.Insurance.RepairBox.RepairMult; Disabled due to visual bug - it doesn't show converted number, the function itself is working tho - Repair.armorKitSkillPointGainPerRepairPointMultiplier = Config.Services.RepairBox.ArmorSkillMult; - Repair.weaponTreatment.pointGainMultiplier = Config.Services.RepairBox.WeaponMaintenanceSkillMult; - Repair.repairKitIntellectGainMultiplier.weapon = Config.Services.RepairBox.IntellectSkillMultWeaponKit; - Repair.repairKitIntellectGainMultiplier.armor = Config.Services.RepairBox.IntellectSkillMultArmorKit; - Repair.maxIntellectGainPerRepair.kit = Config.Services.RepairBox.IntellectSkillLimitKit; - Repair.maxIntellectGainPerRepair.trader = Config.Services.RepairBox.IntellectSkillLimitTraders; - Repair.applyRandomizeDurabilityLoss = !Config.Services.RepairBox.NoRandomRepair; - if (Config.Services.EnableInsurance) { - Insurance.returnChancePercent["54cb50c76803fa8b248b4571"] = Config.Services.ReturnChancePrapor; - Insurance.returnChancePercent["54cb57776803fa99248b456e"] = Config.Services.ReturnChanceTherapist; - traders["54cb50c76803fa8b248b4571"].base.insurance.max_storage_time = Config.Services.PraporStorageTime; - traders["54cb57776803fa99248b456e"].base.insurance.max_storage_time = Config.Services.TherapistStorageTime; - traders["54cb50c76803fa8b248b4571"].base.insurance.min_return_hour = Config.Services.Prapor_Min; - traders["54cb50c76803fa8b248b4571"].base.insurance.max_return_hour = Config.Services.Prapor_Max; - traders["54cb57776803fa99248b456e"].base.insurance.min_return_hour = Config.Services.Therapist_Min; - traders["54cb57776803fa99248b456e"].base.insurance.max_return_hour = Config.Services.Therapist_Max; - Insurance.chanceNoAttachmentsTakenPercent = Config.Services.InsuranceAttachmentChance - //3.9.0 insurance fix + new fields - Insurance.runIntervalSeconds = Config.Services.InsuranceInterval - if (Config.Services.EnableTimeOverride) { - Insurance.returnTimeOverrideSeconds = Config.Services.InsuranceTimeOverride - } - let TherapistMult = [Config.Services.InsuranceMultTherapistLvl1, Config.Services.InsuranceMultTherapistLvl2, Config.Services.InsuranceMultTherapistLvl3, Config.Services.InsuranceMultTherapistLvl4] - for (let level in traders["54cb57776803fa99248b456e"].base.loyaltyLevels) { - traders["54cb57776803fa99248b456e"].base.loyaltyLevels[level].insurance_price_coef = TherapistMult[level] - } - let PraporMult = [Config.Services.InsuranceMultPraporLvl1, Config.Services.InsuranceMultPraporLvl2, Config.Services.InsuranceMultPraporLvl3, Config.Services.InsuranceMultPraporLvl4] - for (let level in traders["54cb50c76803fa8b248b4571"].base.loyaltyLevels) { - traders["54cb50c76803fa8b248b4571"].base.loyaltyLevels[level].insurance_price_coef = PraporMult[level] - } - } - //Enable all clothes available for both side - if (Config.Services.ClothesAnySide) { - for (let suit in suits) { - let suitData = suits[suit] - if (suitData._parent === "5cd944ca1388ce03a44dc2a4" || suitData._parent === "5cd944d01388ce000a659df9") { - suitData._props.Side = ["Bear", "Usec"]; - } - } - } - if (Config.Services.ClothesFree || Config.Services.ClothesLevelUnlock) { - for (let tradercloth in traders) { - if (traders[tradercloth].suits) { - for (let file in traders[tradercloth].suits) { - let fileData = traders[tradercloth].suits[file] - if (Config.Services.ClothesLevelUnlock) { - fileData.requirements.loyaltyLevel = 1; - fileData.requirements.profileLevel = 1; - fileData.requirements.standing = 0; - fileData.requirements.questRequirements = [];//Only adik hits this - } - //fileData.requirements.skillRequirements = [];//This is useless, it always stands for empty - if (Config.Services.ClothesFree) { - fileData.requirements.itemRequirements = []; - } - } - } - } - } - if (Config.Services.EnableHealMarkup) { - let TherapistLevels = [Config.Services.TherapistLvl1, Config.Services.TherapistLvl2, Config.Services.TherapistLvl3, Config.Services.TherapistLvl4] - for (let level in traders["54cb57776803fa99248b456e"].base.loyaltyLevels) { - traders["54cb57776803fa99248b456e"].base.loyaltyLevels[level].heal_price_coef = TherapistLevels[level] * 100 - } - globals.Health.HealPrice.TrialLevels = Config.Services.FreeHealLvl - globals.Health.HealPrice.TrialRaids = Config.Services.FreeHealRaids - } - if (Config.Services.EnableRepair) { - for (let CurTrader in traders) { - if (CurTrader !== "ragfair" && (CurTrader == "5a7c2eca46aef81a7ca2145d" || CurTrader == "5ac3b934156ae10c4430e83c" || CurTrader == "5c0647fdd443bc2504c2d371" || CurTrader == "54cb50c76803fa8b248b4571" || CurTrader == "54cb57776803fa99248b456e" || CurTrader == "579dc571d53a0658a154fbec" || CurTrader == "5935c25fb3acc3127c3d8cd9" || CurTrader == "58330581ace78e27b8b10cee")) { - for (let level in traders[CurTrader].base.loyaltyLevels) { - traders[CurTrader].base.loyaltyLevels[level].repair_price_coef *= Config.Services.RepairBox.RepairMult; - } - } - } - if (Config.Services.RepairBox.OpArmorRepair) { - for (let armormats in globals.ArmorMaterials) { - globals.ArmorMaterials[armormats].MaxRepairDegradation = 0 - globals.ArmorMaterials[armormats].MinRepairDegradation = 0 - globals.ArmorMaterials[armormats].MaxRepairKitDegradation = 0 - globals.ArmorMaterials[armormats].MinRepairKitDegradation = 0 - } - } - if (Config.Services.RepairBox.OpGunRepair) { - for (let stuff in items) { - if (items[stuff]._props.MaxRepairDegradation !== undefined && items[stuff]._props.MaxRepairKitDegradation !== undefined) { - EditSimpleItemData(stuff, "MinRepairDegradation", 0); - EditSimpleItemData(stuff, "MaxRepairDegradation", 0); - EditSimpleItemData(stuff, "MinRepairKitDegradation", 0); - EditSimpleItemData(stuff, "MaxRepairKitDegradation", 0); - } - } - } - } - } - //############## CSM SECTION ################## - if (Config.CSM.EnableCSM) { - if (Config.CSM.CustomPocket) { - const JsonUtil = container.resolve("JsonUtil"); - let CustomPocketItem = JsonUtil.clone(items["627a4e6b255f7527fb05a0f6"]) - let PocketSize = Config.CSM.Pockets - CustomPocketItem._id = "a8edfb0bce53d103d3f62b9b"; - for (let cell in CustomPocketItem._props.Grids)//tried to make less code, made more, smh. - { - CustomPocketItem._props.Grids[cell]._parent = "a8edfb0bce53d103d3f62b9b" - } - for (let cell in CustomPocketItem._props.Slots) { - CustomPocketItem._props.Slots[cell]._parent = "a8edfb0bce53d103d3f62b9b" - } - CustomPocketItem._props.Grids[0]._id = "a8edfb0bce53d103d3f62b0b" - CustomPocketItem._props.Grids[0]._props.cellsH = PocketSize.FirstWidth - CustomPocketItem._props.Grids[0]._props.cellsV = PocketSize.FirstHeight - CustomPocketItem._props.Grids[1]._id = "a8edfb0bce53d103d3f62b1b" - CustomPocketItem._props.Grids[1]._props.cellsH = PocketSize.SecondWidth - CustomPocketItem._props.Grids[1]._props.cellsV = PocketSize.SecondHeight - CustomPocketItem._props.Grids[2]._id = "a8edfb0bce53d103d3f62b2b" - CustomPocketItem._props.Grids[2]._props.cellsH = PocketSize.ThirdWidth - CustomPocketItem._props.Grids[2]._props.cellsV = PocketSize.ThirdHeight - CustomPocketItem._props.Grids[3]._id = "a8edfb0bce53d103d3f62b3b" - CustomPocketItem._props.Grids[3]._props.cellsH = PocketSize.FourthWidth - CustomPocketItem._props.Grids[3]._props.cellsV = PocketSize.FourthHeight - CustomPocketItem._props.Slots[0]._id = "a8edfb0bce53d103d3f62b4b" - CustomPocketItem._props.Slots[1]._id = "a8edfb0bce53d103d3f62b5b" - CustomPocketItem._props.Slots[2]._id = "a8edfb0bce53d103d3f62b6b" - if (PocketSize.FourthWidth == 0 || PocketSize.FourthHeight == 0) { - CustomPocketItem._props.Grids.splice(3, 1); - } - if (PocketSize.ThirdWidth == 0 || PocketSize.ThirdHeight == 0) { - CustomPocketItem._props.Grids.splice(2, 1); - } - if (PocketSize.SecondWidth == 0 || PocketSize.SecondHeight == 0) { - CustomPocketItem._props.Grids.splice(1, 1); - } - if (PocketSize.FirstWidth == 0 || PocketSize.FirstHeight == 0) { - CustomPocketItem._props.Grids.splice(0, 1); - } - - switch (true) { - case Config.CSM.Pockets.SpecSlots == 0: - CustomPocketItem._props.Slots.splice(0, 3); - break; - case Config.CSM.Pockets.SpecSlots == 1: - CustomPocketItem._props.Slots.splice(1, 2); - break; - case Config.CSM.Pockets.SpecSlots == 2: - CustomPocketItem._props.Slots.splice(2, 1); - break; - case Config.CSM.Pockets.SpecSlots == 3: - break; - case Config.CSM.Pockets.SpecSlots >= 4://Graduality done, switched `switch` to true statement and expressions. - CustomPocketItem._props.Slots[3] = JsonUtil.clone(CustomPocketItem._props.Slots[2]) - CustomPocketItem._props.Slots[3]._id = "a8edfb0bce53d103d3f62b7b" - CustomPocketItem._props.Slots[3]._name = "SpecialSlot4" - CustomPocketItem._props.Slots[3]._parent = "a8edfb0bce53d103d3f62b9b" - Insurance.blacklistedEquipment.push("SpecialSlot4") - case Config.CSM.Pockets.SpecSlots == 5: - CustomPocketItem._props.Slots[4] = JsonUtil.clone(CustomPocketItem._props.Slots[2]) - CustomPocketItem._props.Slots[4]._id = "a8edfb0bce53d103d3f62b8b" - CustomPocketItem._props.Slots[4]._name = "SpecialSlot5" - CustomPocketItem._props.Slots[4]._parent = "a8edfb0bce53d103d3f62b9b" - Insurance.blacklistedEquipment.push("SpecialSlot5") - break; - } - //This is a solution to avoid removing cases from bodies if they die. - let IDsToFilter = ["5783c43d2459774bbe137486", "60b0f6c058e0b0481a09ad11", "619cbf9e0a7c3a1a2731940a", "619cbf7d23893217ec30b689", "59fafd4b86f7745ca07e1232", "62a09d3bcf4a99369e262447"]; - let Pockets = Config.CSM.Pockets - let CasesToFilter = [Pockets.SpecSimpleWallet, Pockets.SpecWZWallet, Pockets.SpecKeycardHolder, Pockets.SpecInjectorCase, Pockets.SpecKeytool, Pockets.SpecGKeychain]; - for (let ID in IDsToFilter) { - items[IDsToFilter[ID]]._props.DiscardLimit = -1; - items[IDsToFilter[ID]]._props.InsuranceDisabled = true; - } - for (let specialslots in CustomPocketItem._props.Slots) { - for (let element in IDsToFilter) { - if (CasesToFilter[element]) { - CustomPocketItem._props.Slots[specialslots]._props.filters[0].Filter.push(IDsToFilter[element]) - } - } - //items[IDsToFilter[specialslots]]._props.HideEntrails = true; - } - items["a8edfb0bce53d103d3f62b9b"] = CustomPocketItem; - //items["5795f317245977243854e041"]._props.HideEntrails = true; Still unsure what does it do - } - if (Config.CSM.EnableSecureCases) { - const SecCon = Config.CSM.SecureContainers - - const SecHeight = [ - SecCon.AlphaHeight, - SecCon.KappaHeight, - SecCon.BetaHeight, - SecCon.EpsilonHeight, - SecCon.GammaHeight, - SecCon.GammaTUEHeight, - SecCon.WaistPouchHeight, - SecCon.DevHeight - ]; - const SecWidth = [ - SecCon.AlphaWidth, - SecCon.KappaWidth, - SecCon.BetaWidth, - SecCon.EpsilonWidth, - SecCon.GammaWidth, - SecCon.GammaTUEWidth, - SecCon.WaistPouchWidth, - SecCon.DevWidth - ]; - for (let SecConts in Arrays.SecConID) { - items[Arrays.SecConID[SecConts]]._props.Grids[0]._props["cellsV"] = SecHeight[SecConts]; - items[Arrays.SecConID[SecConts]]._props.Grids[0]._props["cellsH"] = SecWidth[SecConts]; - } - } - if (Config.CSM.EnableCases) { - const Cases = Config.CSM.Cases - const Size = [ - Cases.MoneyCase, - Cases.SimpleWallet, - Cases.WZWallet, - Cases.GrenadeCase, - Cases.ItemsCase, - Cases.WeaponCase, - Cases.LuckyScav, - Cases.AmmunitionCase, - Cases.MagazineCase, - Cases.DogtagCase, - Cases.MedicineCase, - Cases.ThiccItemsCase, - Cases.ThiccWeaponCase, - Cases.SiccCase, - Cases.Keytool, - Cases.DocumentsCase, - Cases.PistolCase, - Cases.Holodilnick, - Cases.InjectorCase, - Cases.KeycardHolderCase, - Cases.GKeychain - ] - const Filts = [ - Cases.MoneyCase.Filter, - Cases.SimpleWallet.Filter, - Cases.WZWallet.Filter, - Cases.GrenadeCase.Filter, - Cases.ItemsCase.Filter, - Cases.WeaponCase.Filter, - Cases.LuckyScav.Filter, - Cases.AmmunitionCase.Filter, - Cases.MagazineCase.Filter, - Cases.DogtagCase.Filter, - Cases.MedicineCase.Filter, - Cases.ThiccItemsCase.Filter, - Cases.ThiccWeaponCase.Filter, - Cases.SiccCase.Filter, - Cases.Keytool.Filter, - Cases.DocumentsCase.Filter, - Cases.PistolCase.Filter, - Cases.Holodilnick.Filter, - Cases.InjectorCase.Filter, - Cases.KeycardHolderCase.Filter, - Cases.GKeychain.Filter - ] - for (let Case in Arrays.CasesID) { - items[Arrays.CasesID[Case]]._props.Grids[0]._props["cellsV"] = Size[Case].Height; - items[Arrays.CasesID[Case]]._props.Grids[0]._props["cellsH"] = Size[Case].Width; - } - //Filters - for (let Filters in Filts) { - if (Filts[Filters]) // To check whether checkmark is true or false - { - items[Arrays.CasesID[Filters]]._props.Grids[0]._props.filters = []; - } - } - } - } - //############## ITEMS SECTION ################ - if (Config.Items.EnableItems) { - - //Price Modifier - for (const item in DB.templates.handbook.Items) { - if (DB.templates.handbook.Items[item].ParentId !== "5b5f78b786f77447ed5636af" && DB.templates.handbook.Items[item].Price != null) { - DB.templates.handbook.Items[item].Price = (DB.templates.handbook.Items[item].Price * Config.Items.ItemPriceMult) - } - } - //Loading-Unloading rounds in a magazine - globals.BaseUnloadTime = globals.BaseUnloadTime * Config.Items.AmmoLoadSpeed; - globals.BaseLoadTime = globals.BaseLoadTime * Config.Items.AmmoLoadSpeed; - //Signal Pistol into Special slots - if (Config.Items.AddSignalPistolToSpec) { - if (items["a8edfb0bce53d103d3f62b9b"] !== undefined) { - for (let specialslots in items["a8edfb0bce53d103d3f62b9b"]._props.Slots) { - items["a8edfb0bce53d103d3f62b9b"]._props.Slots[specialslots]._props.filters[0].Filter.push("620109578d82e67e7911abf2") - } - } - if (items["627a4e6b255f7527fb05a0f6"] !== undefined) { - for (let specialslots in items["627a4e6b255f7527fb05a0f6"]._props.Slots) { - items["627a4e6b255f7527fb05a0f6"]._props.Slots[specialslots]._props.filters[0].Filter.push("620109578d82e67e7911abf2") - } - } - if (items["65e080be269cbd5c5005e529"] !== undefined) { - for (let specialslots in items["65e080be269cbd5c5005e529"]._props.Slots) { - items["65e080be269cbd5c5005e529"]._props.Slots[specialslots]._props.filters[0].Filter.push("620109578d82e67e7911abf2") - } - } - } - for (const id in items) { - let base = items[id] - //Examining time - if (base._type == "Item" && base._props.ExamineTime !== undefined) { - EditSimpleItemData(id, "ExamineTime", Config.Items.ExamineTime); - } - //Fragmentation Multiplier - if (base._props.FragmentationChance !== undefined) { - EditSimpleItemData(id, "FragmentationChance", parseFloat(base._props.FragmentationChance * Config.Items.FragmentMult).toFixed(2)); - } - //Heat Factor Multiplier - if (base._props.HeatFactor !== undefined) { - EditSimpleItemData(id, "HeatFactor", parseFloat(base._props.HeatFactor * Config.Items.HeatFactor).toFixed(4)); - } - //Dropping items in raid rather deleting them - if (base._type == "Item" && base._props.DiscardLimit !== undefined && Config.Items.RaidDrop) { - EditSimpleItemData(id, "DiscardLimit", -1); - } - //Turns off weapon overheat - if (base._props.AllowOverheat !== undefined && Config.Items.WeaponHeatOff) { - EditSimpleItemData(id, "AllowOverheat", false); - } - //Malfunction chance - if ((base._parent == "5447b5cf4bdc2d65278b4567" || base._parent == "5447b6254bdc2dc3278b4568" || items[id]._parent == "5447b5f14bdc2d61278b4567" || items[id]._parent == "5447bed64bdc2d97278b4568" || items[id]._parent == "5447b6094bdc2dc3278b4567" || items[id]._parent == "5447b5e04bdc2d62278b4567" || items[id]._parent == "5447b6194bdc2d67278b4567") && items[id]._props.BaseMalfunctionChance !== undefined) { - EditSimpleItemData(id, "BaseMalfunctionChance", parseFloat(base._props.BaseMalfunctionChance * Config.Items.MalfunctChanceMult).toFixed(6)); - } - if (base._parent == "5448bc234bdc2d3c308b4569" && base._props.MalfunctionChance !== undefined) { - EditSimpleItemData(id, "MalfunctionChance", parseFloat(base._props.MalfunctionChance * Config.Items.MalfunctChanceMult).toFixed(2)); - } - //Misfire chance - if (base._parent == "5485a8684bdc2da71d8b4567" && base._props.MalfMisfireChance !== undefined) { - EditSimpleItemData(id, "MalfMisfireChance", parseFloat(base._props.MalfMisfireChance * Config.Items.MisfireChance).toFixed(3)); - } - //Examine all items - if (Config.Items.AllExaminedItems && Config.Items.ExamineKeys) { - EditSimpleItemData(id, "ExaminedByDefault", true); - } - //Examine all items EXCEPT KEYS, checking for parent IDs of mechanical, keycards and keys in general just in case. - else if (Config.Items.AllExaminedItems && base._parent !== "5c99f98d86f7745c314214b3" && base.parent !== "5c164d2286f774194c5e69fa" && base.parent !== "543be5e94bdc2df1348b4568") { - EditSimpleItemData(id, "ExaminedByDefault", true); - } - //Change the weight - if (base._type !== "Node" && base._type !== undefined && (base.parent !== "557596e64bdc2dc2118b4571" || base._parent !== "55d720f24bdc2d88028b456d")) { - EditSimpleItemData(id, "Weight", parseFloat(Config.Items.WeightChanger * base._props.Weight).toFixed(3)); - } - if (Config.Items.NoGearPenalty) { - if (base._props.mousePenalty) { - EditSimpleItemData(id, "mousePenalty", 0) - } - if (base._props.weaponErgonomicPenalty) { - EditSimpleItemData(id, "weaponErgonomicPenalty", 0) - } - if (base._props.speedPenaltyPercent) { - EditSimpleItemData(id, "speedPenaltyPercent", 0) - } - } - //Ammo Stacks - if (base._parent.includes("5485a8684bdc2da71d8b4567") && Config.Items.AmmoSwitch) { - let str = base._name//.split("_", 2) - if (AmmoFilter(Arrays.Pistol, str)) { - EditSimpleItemData(id, "StackMaxSize", Config.Items.AmmoStacks.PistolRound) - } - else if (AmmoFilter(Arrays.Shotgun, str)) { - EditSimpleItemData(id, "StackMaxSize", Config.Items.AmmoStacks.ShotgunRound) - } - else if (AmmoFilter(Arrays.ARifle, str)) { - EditSimpleItemData(id, "StackMaxSize", Config.Items.AmmoStacks.RifleRound) - } - else if (AmmoFilter(Arrays.MRifle, str)) { - EditSimpleItemData(id, "StackMaxSize", Config.Items.AmmoStacks.MarksmanRound) - } - } - //Change money stacks - if (base._parent == "543be5dd4bdc2deb348b4569" && base._props.StackMaxSize !== undefined && Config.Items.EnableCurrency) { - switch (base._id) { - case "569668774bdc2da2298b4568": - EditSimpleItemData(id, "StackMaxSize", Config.Items.EuroStack); - break; - case "5696686a4bdc2da3298b456a": - EditSimpleItemData(id, "StackMaxSize", Config.Items.DollarStack); - break; - case "5d235b4d86f7742e017bc88a": - EditSimpleItemData(id, "StackMaxSize", Config.Items.GPStack); - break; - default: - EditSimpleItemData(id, "StackMaxSize", Config.Items.RubStack); - break; - } - } - //Allow armored rigs with armors - if (Config.Items.EquipRigsWithArmors && base._props.BlocksArmorVest !== undefined) { - EditSimpleItemData(id, "BlocksArmorVest", false); - } - //Remove filters - if (Config.Items.RemoveSecureContainerFilters && base._parent == "5448bf274bdc2dfc2f8b456a" && base._props.Grids[0]._props.filters !== undefined) { - base._props.Grids[0]._props.filters = []; - } - if (Config.Items.RemoveBackpacksRestrictions && base._parent == "5448e53e4bdc2d60728b4567" && base._props.Grids[0]._props.filters !== undefined) { - base._props.Grids[0]._props.filters = []; - } - //Change items experience gain - if (base._props.LootExperience !== undefined) { - let calculation = Math.round(base._props.LootExperience * Config.Items.LootExp); - EditSimpleItemData(id, "LootExperience", calculation); - } - if (base._props.ExamineExperience !== undefined) { - let calculation = Math.round(base._props.ExamineExperience * Config.Items.ExamineExp); - EditSimpleItemData(id, "ExamineExperience", calculation); - } - //Remove the keys usage - God i hate how i wrote it - if (Config.Items.EnableKeys) { - if ((base._parent == "5c99f98d86f7745c314214b3") && base._props.MaximumNumberOfUsage !== undefined) { - - if (base._parent == "5c99f98d86f7745c314214b3" && base._props.MaximumNumberOfUsage == 1 && !Config.Items.AvoidSingleKeys) { - base._props.MaximumNumberOfUsage = 0 - } - if ( Arrays.MarkedKeys.includes(base._id) && !Config.Items.AvoidMarkedKeys) { - base._props.MaximumNumberOfUsage = 0 - } - if (!(Arrays.MarkedKeys.includes(base._id)) && base._props.MaximumNumberOfUsage !== 1) { - base._props.MaximumNumberOfUsage = 0 - } - } - - if (base._parent == "5c164d2286f774194c5e69fa" && base._props.MaximumNumberOfUsage !== undefined && Config.Items.InfiniteKeycards) { - base._props.MaximumNumberOfUsage = 0 - } - if (base._parent == "5c99f98d86f7745c314214b3" && base._props.MaximumNumberOfUsage != 0) { - base._props.MaximumNumberOfUsage *= Config.Items.KeyUseMult - if (base._props.MaximumNumberOfUsage > Config.Items.KeyDurabilityThreshold) { - base._props.MaximumNumberOfUsage = Config.Items.KeyDurabilityThreshold - } - } - if (base._parent == "5c164d2286f774194c5e69fa" && base._props.MaximumNumberOfUsage != 0) { - base._props.MaximumNumberOfUsage *= Config.Items.KeycardUseMult - if (base._props.MaximumNumberOfUsage > Config.Items.KeyDurabilityThreshold) { - base._props.MaximumNumberOfUsage = Config.Items.KeyDurabilityThreshold - } - } - } - } - if (Config.Items.SMGToHolster) { - items["55d7217a4bdc2d86028b456d"]._props.Slots[2]._props.filters[0].Filter.push("5447b5e04bdc2d62278b4567"); - } - if (Config.Items.PistolToMain) { - items["55d7217a4bdc2d86028b456d"]._props.Slots[0]._props.filters[0].Filter.push("5447b5cf4bdc2d65278b4567", "617f1ef5e8b54b0998387733"); - items["55d7217a4bdc2d86028b456d"]._props.Slots[1]._props.filters[0].Filter.push("5447b5cf4bdc2d65278b4567", "617f1ef5e8b54b0998387733"); - } - if (Config.Items.RemoveRaidRestr) { - globals.RestrictionsInRaid = [] - } - if (Config.Items.IDChanger) { - //Edit item properties, i know it looks stupid, but hey - it works and i like it. - //5th revision, now including separate fields for filters, parents and expressions. - Logger.info("[SVM] Custom Properties is loading", "blue") - try { - if (Config.Items.IDParent.length > 0) { //ID=ParentID, same as above - let ParentList = Config.Items.IDParent.split("\r\n") - let IDArray = []; - for (let Line in ParentList) { - const Variables = ParentList[Line].split(":") - Logger.info("Parent: " + Variables) - for (let ids in items) { - if (Variables[0] == items[ids]._parent) { - IDArray.push(items[ids]._id); - } - } - Logger.info("Affected by parent: ") - Logger.info(IDArray) - for (let ID in IDArray) { - Variables[0] = IDArray[ID] - IDChanger(Variables) - } - } - } - if (Config.Items.IDDefault.length > 0) {//ID:Variable:Value - let DefaultList = Config.Items.IDDefault.split("\r\n") - for (let Line in DefaultList) { - let Variables = DefaultList[Line].split(":") - Logger.info("Default: " + Variables) - IDChanger(Variables) - } - } - if (Config.Items.IDFilter.length > 0) { //ID:Slots/Grids:Grid/Slot Number:Filter/ExcludedFilter:PushIntoArray - let FilterList = Config.Items.IDFilter.split("\r\n") - for (let Line in FilterList) { - const Variables = FilterList[Line].split(":") - Logger.info("Filter: " + Variables) - if (Variables.length === 5) { - let check = CheckType(Variables[4]) - for (let fields in check) { - items[Variables[0]]._props[Variables[1]][Variables[2]]._props.filters[0][Variables[3]].push(check[fields]) - } - } - else { - Logger.error("[SVM] INVENTORY AND ITEMS - Filters ID - failed to apply\n") - } - } - } - if (Config.Items.IDPrice.length > 0) { //ID:Expression:Number - const handbook = DB.templates.handbook.Items - let IDPriceLines = Config.Items.IDPrice.split("\r\n") - for (let Line in IDPriceLines) { - const Variables = IDPriceLines[Line].split(":") - Logger.info("Price: " + Variables) - let IDChecker = true; - for (let Target in handbook) { - if (handbook[Target].Id.includes(Variables[0])) { - handbook[Target].Price = Calculus(handbook[Target].Price, Variables[1], Variables[2]) - IDChecker = false; - break; - } - } - if (IDChecker) { - Logger.warning("[SVM] INVENTORY AND ITEMS - Price ID - " + Variables[0] + " - This ID is not found in handbook.\nChecking as ParentID") - let childs = [] - for (let ID in items) { - if (items[ID]._parent == Variables[0]) { - childs.push(items[ID]._id) - } - } - if (childs.length > 0) { - Logger.success("[SVM] Success, Changing prices of Child IDs") - Logger.info(childs) - for (let child in childs) { - for (let ID in handbook) { - if (handbook[ID].Id.includes(childs[child])) { - handbook[ID].Price = Calculus(handbook[ID].Price, Variables[1], Variables[2]) - break; - } - } - } - } - else { - Logger.error("[SVM] Price ID Failed, this ID doesn't exist in Items.json") - } - } - } - } - Logger.success("[SVM] Custom properties successfully loaded") + const Config = require('../Presets/' + PresetLoader.CurrentlySelectedPreset + '.json'); } catch (e) { - Logger.error("[SVM] INVENTORY AND ITEMS - Custom properties failed to load, error of the code:\n" + e) + const Logger = container.resolve("WinstonLogger"); + Logger.warning("\n[SVM] SVM is lacking loader file or there is an error, mod is disabled\n" + + "Most likely you're running this mod for the first time, head to the SVM mod folder and run the Greed.exe\n" + + "Don't forget to apply your changes...Really, hit that Apply button, it will create loader file\n" + + "[SVM] If it's Syntax error, edit it manually in loader.json or/and edit values with UIs properly\n" + + "Exception message below may help you distinguish what went wrong:\n"); + Logger.error(e.message + "\n"); + return } - } - } - //############## PLAYER SECTION ############### - if (Config.Player.EnablePlayer) { - //Skill box - globals.SkillsSettings.SkillProgressRate = Config.Player.SkillProgMult; - globals.SkillsSettings.WeaponSkillProgressRate = Config.Player.WeaponSkillMult; - //health after raid box - Health.healthMultipliers.death = Config.Player.DiedHealth.Health_death; - Health.healthMultipliers.blacked = Config.Player.DiedHealth.Health_blacked; - Health.save.health = Config.Player.DiedHealth.Savehealth; - Health.save.effects = Config.Player.DiedHealth.Saveeffects; - // skill eff box - if (Config.Player.EnableFatigue) { - globals.SkillMinEffectiveness = Config.Player.Skills.SkillMinEffect; - globals.SkillFatiguePerPoint = Config.Player.Skills.SkillFatiguePerPoint; - globals.SkillFreshEffectiveness = Config.Player.Skills.SkillFreshEffect; - globals.SkillFreshPoints = Config.Player.Skills.SkillFPoints; - globals.SkillPointsBeforeFatigue = Config.Player.Skills.SkillPointsBeforeFatigue; - globals.SkillFatigueReset = Config.Player.Skills.SkillFatigueReset; - } - //############## Player level XP box ############## - globals.exp.kill.victimBotLevelExp = Config.Player.CharXP.ScavKill; - globals.exp.kill.victimLevelExp = Config.Player.CharXP.PMCKill; - globals.exp.kill.botHeadShotMult = Config.Player.CharXP.ScavHMult; - globals.exp.kill.pmcHeadShotMult = Config.Player.CharXP.PMCHMult - //############## END OF RAID Box ############## - globals.exp.match_end.runnerMult = Config.Player.RaidMult.Runner - globals.exp.match_end.miaMult = Config.Player.RaidMult.MIA - globals.exp.match_end.survivedMult = Config.Player.RaidMult.Survived - globals.exp.match_end.killedMult = Config.Player.RaidMult.Killed - //Remove fall damage - if (Config.Player.FallDamage) { - globals.Health.Falling.SafeHeight = 200 - globals.Health.Falling.DamagePerMeter = 0 - } - //Change stamina (unlimited or no) - if (Config.Player.MaxStamina !== 100 && !Config.Player.UnlimitedStamina) { - globals.Stamina.Capacity = Config.Player.MaxStamina; - } - else if (Config.Player.UnlimitedStamina) { - globals.Stamina.Capacity = 500; - globals.Stamina.BaseRestorationRate = 500; - globals.Stamina.StaminaExhaustionCausesJiggle = false; - globals.Stamina.StaminaExhaustionStartsBreathSound = false; - globals.Stamina.StaminaExhaustionRocksCamera = false; - globals.Stamina.SprintDrainRate = 0; - globals.Stamina.JumpConsumption = 0; - globals.Stamina.AimDrainRate = 0; - globals.Stamina.SitToStandConsumption = 0; - } - globals.Health.Effects.Existence.HydrationLoopTime = (globals.Health.Effects.Existence.HydrationLoopTime / Config.Player.HydrationLoss) - globals.Health.Effects.Existence.EnergyLoopTime = (globals.Health.Effects.Existence.EnergyLoopTime / Config.Player.EnergyLoss) - globals.Health.Effects.Existence.DestroyedStomachEnergyTimeFactor = Config.Player.BlackStomach; - globals.Health.Effects.Existence.DestroyedStomachHydrationTimeFactor = Config.Player.BlackStomach; - } - //############## HIDEOUT SECTION ############## - if (Config.Hideout.EnableHideout) { - //Change hideout fuel consumption - hideout.settings.generatorFuelFlowRate *= Config.Hideout.FuelConsumptionRate; - hideout.settings.generatorSpeedWithoutFuel *= Config.Hideout.NoFuelMult; - //hideoutC.fuelDrainRateMultipler = Config.Hideout.FuelConsumptionRate; - hideout.settings.airFilterUnitFlowRate *= Config.Hideout.AirFilterRate; - hideout.settings.gpuBoostRate *= Config.Hideout.GPUBoostRate; - if (Config.Hideout.EnableStash) { - items["566abbc34bdc2d92178b4576"]._props.Grids[0]._props.cellsV = Config.Hideout.Stash.StashLvl1 - items["5811ce572459770cba1a34ea"]._props.Grids[0]._props.cellsV = Config.Hideout.Stash.StashLvl2 - items["5811ce662459770f6f490f32"]._props.Grids[0]._props.cellsV = Config.Hideout.Stash.StashLvl3 - items["5811ce772459770e9e5f9532"]._props.Grids[0]._props.cellsV = Config.Hideout.Stash.StashLvl4 - items["6602bcf19cc643f44a04274b"]._props.Grids[0]._props.cellsV = Config.Hideout.Stash.StashTUE - } - //Enable hideout fast constructions - for (const data in hideout.areas) { - let areaData = hideout.areas[data] - for (const i in areaData.stages) { - if (areaData.stages[i].constructionTime > 0) { - areaData.stages[i].constructionTime = parseInt(areaData.stages[i].constructionTime * Config.Hideout.HideoutConstMult) - if (areaData.stages[i].constructionTime < 1) { - areaData.stages[i].constructionTime = 2 + const PresetLoader = require('../Loader/loader.json'); + const Config = require('../Presets/' + PresetLoader.CurrentlySelectedPreset + '.json'); + const StaticRouterModService = container.resolve("StaticRouterModService"); + const HttpResponse = container.resolve("HttpResponseUtil"); + const repeatableQuestController = container.resolve("RepeatableQuestController"); + + //PRE LOAD - QUESTS SECTION + if (Config.Quests.EnableQuests && Config.Quests.EnableQuestsMisc)//Horrible, as usual + { + try { + container.afterResolution("QuestCallbacks", (_t, result) => { + result.activityPeriods = (url, info, sessionID) => { + let Edited = repeatableQuestController.getClientRepeatableQuests(sessionID); + for (let quests in Edited) { + for (let act in Edited[quests].activeQuests) {//this needs to be trimmed as well, eventually. + if (Edited[quests].activeQuests[act].changeCost[0].count !== undefined) { + Edited[quests].activeQuests[act].changeCost[0].count = 5000 * Config.Quests.QuestCostMult; + } + if (Config.Quests.QuestRepToZero) { + Edited[quests].activeQuests[act].changeStandingCost = 0; + } + } + for (let inact in Edited[quests].inactiveQuests) { + if (Edited[quests].inactiveQuests[inact].changeCost[0].count !== undefined) { + Edited[quests].inactiveQuests[inact].changeCost[0].count = 5000 * Config.Quests.QuestCostMult; + } + if (Config.Quests.QuestRepToZero) { + Edited[quests].inactiveQuests[inact].changeStandingCost = 0; + } + } + for (let req in Edited[quests].changeRequirement) { + Edited[quests].changeRequirement[req].changeCost[0].count = 5000 * Config.Quests.QuestCostMult; + if (Config.Quests.QuestRepToZero) { + Edited[quests].changeRequirement[req].changeStandingCost = 0; + } + } + } + return HttpResponse.getBody(Edited); + } + }, { frequency: "Always" }); + + container.afterResolution("QuestCallbacks", (_t, result) => { + result.changeRepeatableQuest = (pmcData, body, sessionID) => { + //const repeatableQuestController = container.resolve("RepeatableQuestController"); + let Edited = repeatableQuestController.changeRepeatableQuest(pmcData, body, sessionID); + for (let quests in Edited.profileChanges) { + for (let test in Edited.profileChanges[quests].repeatableQuests[0].changeRequirement) { + Edited.profileChanges[quests].repeatableQuests[0].changeRequirement[test].changeCost[0].count = 5000 * Config.Quests.QuestCostMult; + if (Config.Quests.QuestRepToZero) { + Edited.profileChanges[quests].repeatableQuests[0].changeRequirement[test].changeStandingCost = 0; + } + } + } + return Edited; + } + }, { frequency: "Always" }); + } + catch (e) { + Logger.error("[SVM] REPEATABLE QUEST HANDLED EXCEPTION - Something wrong attempting to change quest reroll price\n" + e.message + "\n"); } - } } - } - //Enable fast hideout production - for (const data in hideout.production.recipes) { - let productionData = hideout.production.recipes[data]; + //PRE LOAD - RAIDS SECTION + if (Config.Raids.RaidEvents.Halloween || Config.Raids.RaidEvents.Christmas)//Extra check, just in case + { + StaticRouterModService.registerStaticRouter("EventOverride", + [ + { + url: "/client/game/version/validate", + action: (url, info, sessionID) => { + const DB = container.resolve("DatabaseService"); + const globalConfig = DB.getGlobals().config; + const configServer = container.resolve("ConfigServer"); + const SeasonalEventService = container.resolve("SeasonalEventService"); + const Events = configServer.getConfig("spt-seasonalevents"); - if (productionData._id == "5d5589c1f934db045e6c5492") { - productionData.productionTime = Config.Hideout.WaterFilterTime * 60 - productionData.requirements[1].resource = Config.Hideout.WaterFilterRate + //let event = []; + if (Config.Raids.RaidEvents.Christmas) { + SeasonalEventService.christmasEventActive = true; + SeasonalEventService.updateGlobalEvents(globalConfig, Events.events[1]); + } + if (Config.Raids.RaidEvents.Halloween) { + SeasonalEventService.halloweenEventActive = true; + SeasonalEventService.updateGlobalEvents(globalConfig, Events.events[0]); + } + return HttpResponse.nullResponse(); + } + } + ], "spt"); } - if (productionData._id == "5d5c205bd582a50d042a3c0e") { - productionData.productionLimitCount = Config.Hideout.MaxBitcoins; - productionData.productionTime = Config.Hideout.BitcoinTime * 60; + if (Config.Hideout.EnableHideout) { + if (Config.Hideout.Regeneration.OfflineRegen) { + container.afterResolution("GameController", (_t, result) => { + result.updateProfileHealthValues = (url, info, sessionID) => { + } + }, { frequency: "Always" }); + } } - if (!productionData.continuous && productionData.productionTime >= 10) { - productionData.productionTime = parseInt(productionData.productionTime * Config.Hideout.HideoutProdMult) - if (productionData.productionTime < 1) { - productionData.productionTime = 2 - } - } - } - //Scav cases modifications - for (const scav in hideout.production.scavRecipes) { - let caseData = hideout.production.scavRecipes[scav]; - if (caseData.productionTime >= 10) { - caseData.productionTime = parseInt(caseData.productionTime * Config.Hideout.ScavCaseTime); - if (caseData.productionTime < 1) { - caseData.productionTime = 2 - } - } - } - for (const scase in hideout.production.scavRecipes) { - let caseData = hideout.production.scavRecipes[scase]; - if (caseData.requirements[0].templateId == "5449016a4bdc2d6f028b456f" || caseData.requirements[0].templateId == "5696686a4bdc2da3298b456a" || caseData.requirements[0].templateId == "569668774bdc2da2298b4568") { - caseData.requirements[0].count = parseInt(caseData.requirements[0].count * Config.Hideout.ScavCasePrice); - } - } - //Remove construction requirements - if (Config.Hideout.RemoveConstructionsRequirements || Config.Hideout.RemoveSkillRequirements || Config.Hideout.RemoveTraderLevelRequirements) { - for (const data in hideout.areas) { - let areaData = hideout.areas[data] - //Logger.info(areaData.stages[1].requirements[1]) - for (const stage in areaData.stages) { - if (areaData.stages[stage].requirements !== undefined && areaData.stages[stage].requirements !== "[]") { - let rewriter = []; - for (let req in areaData.stages[stage].requirements)//This is horrible - { - if (areaData.stages[stage].requirements[req].hasOwnProperty("templateId") && !Config.Hideout.RemoveConstructionsRequirements) { - rewriter.push(areaData.stages[stage].requirements[req]) + + if (Config.Raids.SafeExit) { + container.afterResolution("MatchCallbacks", (_t, result) => { + result.endLocalRaid = (url, info, sessionID) => { + if (info.results.result == "Left") { + info.results.result = "Runner" + } + const MatchController = container.resolve("MatchController"); + MatchController.endLocalRaid(sessionID, info); + return HttpResponse.nullResponse(); } - else if (areaData.stages[stage].requirements[req].hasOwnProperty("skillName") && !Config.Hideout.RemoveSkillRequirements) { - rewriter.push(areaData.stages[stage].requirements[req]) + }, { frequency: "Always" }); + } + if (Config.Raids.SaveGearAfterDeath) { + container.afterResolution("MatchCallbacks", (_t, result) => { + result.endLocalRaid = (url, info, sessionID) => { + if (info.results.result !== "Survived") { + info.results.result = "Runner" + } + const MatchController = container.resolve("MatchController"); + MatchController.endLocalRaid(sessionID, info); + return HttpResponse.nullResponse(); } - else if (areaData.stages[stage].requirements[req].hasOwnProperty("traderId") && !Config.Hideout.RemoveTraderLevelRequirements) { - rewriter.push(areaData.stages[stage].requirements[req]) - } - else if (areaData.stages[stage].requirements[req].hasOwnProperty("areaType"))//Just for sanity check to avoid certain errors like building bitcoin farm while there is no generator. + }, { frequency: "Always" }); + } + //PRE LOAD - CSM SECTION + //Attempt to fix pockets if custom is not present + StaticRouterModService.registerStaticRouter("Revive Pockets", + [ { - rewriter.push(areaData.stages[stage].requirements[req]) + url: "/client/game/version/validate", + action: (url, info, sessionID) => { + let pmcData = container.resolve("ProfileHelper").getPmcProfile(sessionID); + let pockets; + try { + if (pmcData.Info.GameVersion == "unheard_edition") { + pockets = "65e080be269cbd5c5005e529"; + } + else { + pockets = "627a4e6b255f7527fb05a0f6"; + } + pmcData.Inventory.items.forEach((item) => { + if (item.slotId == "Pockets" && item._tpl == "a8edfb0bce53d103d3f62b9b") { + item._tpl = pockets; + } + }) + return HttpResponse.nullResponse(); + } + catch (e) { + Logger.warning("[SVM] REVIVE POCKETS - Attempt cancelled - New profile? Ignore if so.\n" + e.message) + return HttpResponse.nullResponse(); + } + } + }], "spt"); + if (Config.CSM.EnableCSM && Config.CSM.CustomPocket) { + StaticRouterModService.registerStaticRouter("CustomPocket", + [ + { + url: "/client/game/version/validate", + action: (url, info, sessionID) => { + let pmcData = container.resolve("ProfileHelper").getPmcProfile(sessionID); + try { + pmcData.Inventory.items.forEach((item) => { + if (item.slotId == "Pockets") { + item._tpl = "a8edfb0bce53d103d3f62b9b"; + } + }) + return HttpResponse.nullResponse(); + } + catch (e) { + Logger.error("[SVM] CSM CUSTOM POCKETS - New profile detected, Cancelling function, restart the game to fix it.\n" + e.message) + return HttpResponse.nullResponse(); + } + } + }], "spt"); + } + //HEALTH + SCAV FUNCTIONS + if (Config.Player.EnableHealth || Config.Scav.EnableScavHealth || Config.Scav.ScavCustomPockets || Config.Player.EnableStats || Config.Scav.EnableStats) + //TO OVERRIDE HEALTH, STATS + CURRENT SCAV HEALTH, STATS AND POCKETS BEFORE RAID + { + StaticRouterModService.registerStaticRouter("EditHealth", + [ + { + url: "/client/game/version/validate", + action: (url, info, sessionID) => { + try { + let pmcData = container.resolve("ProfileHelper").getPmcProfile(sessionID); + let scavData = container.resolve("ProfileHelper").getScavProfile(sessionID); + if (Config.Player.EnableStats) { + pmcData.Health.Energy.Maximum = Config.Player.PMCStats.MaxEnergy; + pmcData.Health.Hydration.Maximum = Config.Player.PMCStats.MaxHydration; + } + if (Config.Scav.EnableStats) { + scavData.Health.Energy.Maximum = Config.Scav.ScavStats.MaxEnergy; + scavData.Health.Hydration.Maximum = Config.Scav.ScavStats.MaxHydration; + } + if (Config.Player.EnableHealth) { + HealthEdit(pmcData, Config.Player.Health.Head, Config.Player.Health.Chest, Config.Player.Health.Stomach, Config.Player.Health.LeftArm, Config.Player.Health.LeftLeg, Config.Player.Health.RightArm, Config.Player.Health.RightLeg, "Maximum"); + } + if (Config.Scav.EnableScavHealth) { + HealthEdit(scavData, Config.Scav.Health.Head, Config.Scav.Health.Chest, Config.Scav.Health.Stomach, Config.Scav.Health.LeftArm, Config.Scav.Health.LeftLeg, Config.Scav.Health.RightArm, Config.Scav.Health.RightLeg, "Current"); + HealthEdit(scavData, Config.Scav.Health.Head, Config.Scav.Health.Chest, Config.Scav.Health.Stomach, Config.Scav.Health.LeftArm, Config.Scav.Health.LeftLeg, Config.Scav.Health.RightArm, Config.Scav.Health.RightLeg, "Maximum"); + } + if (Config.Scav.ScavCustomPockets) { + scavData.Inventory.items.forEach((item) => { + if (item.slotId == "Pockets") { + item._tpl = "a8edfb0bce53d103d3f6219b"; + } + }) + } + return HttpResponse.nullResponse(); + } + catch (e) { + Logger.error("[SVM] PMC/SCAV HEALTH/STATS - Didn't manage to apply settings, new profile?\n" + e) + return HttpResponse.nullResponse(); + } + } + }], "spt"); + } + if (Config.Scav.EnableScavHealth || Config.Scav.ScavCustomPockets || Config.Scav.EnableStats) { // TO OVERRIDE NEXT SCAVS HEALTH + POCKETS + //May Omnissiah save our souls, have to use both because register affects deaths and resolution affects extracts. Don't ask + container.afterResolution("ProfileController", (_t, result) => { + result.generatePlayerScav = (sessionID) => { + const playerScavGenerator = container.resolve("PlayerScavGenerator"); + const scavData = playerScavGenerator.generate(sessionID); + if (Config.Scav.EnableStats) { + scavData.Health.Energy.Maximum = Config.Scav.ScavStats.MaxEnergy; + scavData.Health.Hydration.Maximum = Config.Scav.ScavStats.MaxHydration; + } + if (Config.Scav.EnableScavHealth) { + HealthEdit(scavData, Config.Scav.Health.Head, Config.Scav.Health.Chest, Config.Scav.Health.Stomach, Config.Scav.Health.LeftArm, Config.Scav.Health.LeftLeg, Config.Scav.Health.RightArm, Config.Scav.Health.RightLeg, "Current"); + HealthEdit(scavData, Config.Scav.Health.Head, Config.Scav.Health.Chest, Config.Scav.Health.Stomach, Config.Scav.Health.LeftArm, Config.Scav.Health.LeftLeg, Config.Scav.Health.RightArm, Config.Scav.Health.RightLeg, "Maximum"); + } + if (Config.Scav.ScavCustomPockets) { + scavData.Inventory.items.forEach((item) => { + if (item.slotId == "Pockets") { + item._tpl = "a8edfb0bce53d103d3f6219b"; + } + }) + } + return scavData; } - } - areaData.stages[stage].requirements = rewriter - } - } - } - } - //Hideout regen menu - //3.10 - for (let limb in globals.Health.Effects.Regeneration.BodyHealth) { - globals.Health.Effects.Regeneration.BodyHealth[limb].Value *= Config.Hideout.Regeneration.HealthRegen - } - globals.Health.Effects.Regeneration.Energy = Config.Hideout.Regeneration.EnergyRegen - globals.Health.Effects.Regeneration.Hydration = Config.Hideout.Regeneration.HydrationRegen + }, { frequency: "Always" }); - for (const data in hideout.areas) { - let areaData = hideout.areas[data] - for (const i in areaData.stages) { - for (const x in areaData.stages[i].bonuses) { - if (Config.Hideout.Regeneration.HideoutHydration && areaData.stages[i].bonuses[x].type == "HydrationRegeneration") { - areaData.stages[i].bonuses[x].value = 0; - } - if (Config.Hideout.Regeneration.HideoutEnergy && areaData.stages[i].bonuses[x].type == "EnergyRegeneration") { - areaData.stages[i].bonuses[x].value = 0; - } - if (Config.Hideout.Regeneration.HideoutHealth && areaData.stages[i].bonuses[x].type == "HealthRegeneration") { - areaData.stages[i].bonuses[x].value = 0; - } - } + StaticRouterModService.registerStaticRouter("EditHealthv2", + [ + { + url: "/client/match/local/end", + action: (url, info, sessionID) => { + if (info.results.result !== "survived" && info.results.result !== "runner") // 3.9.0 If statement for avoiding rerolling survived SCAV, biggest issue of 1.8.3 + { + const saveServer = container.resolve("SaveServer"); + const playerScavGenerator = container.resolve("PlayerScavGenerator"); + const scavData = playerScavGenerator.generate(sessionID); + if (Config.Scav.EnableStats) { + scavData.Health.Energy.Maximum = Config.Scav.ScavStats.MaxEnergy; + scavData.Health.Hydration.Maximum = Config.Scav.ScavStats.MaxHydration; + } + if (Config.Scav.EnableScavHealth) { + HealthEdit(scavData, Config.Scav.Health.Head, Config.Scav.Health.Chest, Config.Scav.Health.Stomach, Config.Scav.Health.LeftArm, Config.Scav.Health.LeftLeg, Config.Scav.Health.RightArm, Config.Scav.Health.RightLeg, "Current"); + HealthEdit(scavData, Config.Scav.Health.Head, Config.Scav.Health.Chest, Config.Scav.Health.Stomach, Config.Scav.Health.LeftArm, Config.Scav.Health.LeftLeg, Config.Scav.Health.RightArm, Config.Scav.Health.RightLeg, "Maximum"); + } + if (Config.Scav.ScavCustomPockets) { + scavData.Inventory.items.forEach((item) => { + if (item.slotId == "Pockets") { + item._tpl = "a8edfb0bce53d103d3f6219b"; + } + }) + } + saveServer.getProfile(sessionID).characters.scav = scavData; + } + return HttpResponse.nullResponse(); + } + }], "spt"); + } + function HealthEdit(Data, Head, Chest, Stomach, LeftArm, LeftLeg, RightArm, RightLeg, CurMax) { + try { + Data.Health.BodyParts["Head"].Health[CurMax] = Head + Data.Health.BodyParts["Chest"].Health[CurMax] = Chest + Data.Health.BodyParts["Stomach"].Health[CurMax] = Stomach + Data.Health.BodyParts["LeftArm"].Health[CurMax] = LeftArm + Data.Health.BodyParts["LeftLeg"].Health[CurMax] = LeftLeg + Data.Health.BodyParts["RightArm"].Health[CurMax] = RightArm + Data.Health.BodyParts["RightLeg"].Health[CurMax] = RightLeg + } + catch { + Logger.error("[SVM] HEALTH EDIT - Something went wrong with trying to generate custom maximum health, new profile? \n" + e) + } } - } } + postDBLoad(container) { + const PreDBStart = performance.now(); + const Logger = container.resolve("WinstonLogger"); + try {//This is dumb piece of code is a handler so PostDB won't run after PreDB did throw a message that something ain't right with the loader. + const PresetLoader = require('../Loader/loader.json'); + const Config = require('../Presets/' + PresetLoader.CurrentlySelectedPreset + '.json'); + } + catch (e) { + return + } + //Config variables to asset for funcs. + const PresetLoader = require('../Loader/loader.json'); + const Config = require('../Presets/' + PresetLoader.CurrentlySelectedPreset + '.json'); + const Arrays = require('../src/Arrays.json'); + //DB redirects + const DB = container.resolve("DatabaseService").getTables(); + const hideout = DB.hideout; + const locations = DB.locations; + const traders = DB.traders; + const Quests = DB.templates.quests; + const suits = DB.templates.customization; + const items = DB.templates.items; + const globals = DB.globals.config; + const Bot = DB.bots.types + // Redirects to server internal configs. + const configServer = container.resolve("ConfigServer"); + const Inraid = configServer.getConfig("spt-inraid"); + const Repair = configServer.getConfig("spt-repair"); + const locs = configServer.getConfig("spt-location"); + const Airdrop = configServer.getConfig("spt-airdrop"); + const Ragfair = configServer.getConfig("spt-ragfair"); + const Insurance = configServer.getConfig("spt-insurance"); + const Health = configServer.getConfig("spt-health"); + const Bots = configServer.getConfig("spt-bot"); + const Quest = configServer.getConfig("spt-quest"); + const HideoutConfig = configServer.getConfig("spt-hideout"); + const WeatherValues = configServer.getConfig("spt-weather"); + const trader = configServer.getConfig("spt-trader"); + const Events = configServer.getConfig("spt-seasonalevents"); + //const Inventory = configServer.getConfig("aki-inventory"); + const BlackItems = configServer.getConfig("spt-item"); + const PMC = configServer.getConfig("spt-pmc") + //############## FLEAMARKET SECTION ########### + if (Config.Fleamarket.EnableFleamarket) { + if (Config.Fleamarket.EnablePlayerOffers) { + globals.RagFair.minUserLevel = Config.Fleamarket.FleaMarketLevel; + Ragfair.dynamic.purchasesAreFoundInRaid = Config.Fleamarket.FleaFIR; + globals.RagFair.isOnlyFoundInRaidAllowed = Config.Fleamarket.FleaNoFIRSell; + Ragfair.dynamic.blacklist.enableBsgList = !Config.Fleamarket.DisableBSGList; + Ragfair.sell.fees = Config.Fleamarket.EnableFees; + Ragfair.sell.chance.base = Config.Fleamarket.Sell_chance; + Ragfair.sell.chance.sellMultiplier = Config.Fleamarket.Sell_mult; + Ragfair.sell.time.max = Config.Fleamarket.Tradeoffer_max; + Ragfair.sell.time.min = Config.Fleamarket.Tradeoffer_min; + globals.RagFair.ratingIncreaseCount = Config.Fleamarket.Rep_gain; + globals.RagFair.ratingDecreaseCount = Config.Fleamarket.Rep_loss; - //############## RAIDS SECTION ################ - if (Config.Raids.EnableRaids) { - //############## INRAID SECTION ################## - if (Config.Raids.RaidStartup.EnableRaidStartup) { - Inraid.MIAOnRaidEnd = Config.Raids.RaidStartup.MIAEndofRaid; - Inraid.raidMenuSettings.aiAmount = Arrays.AIAmount[Config.Raids.RaidStartup.AIAmount]; - Inraid.raidMenuSettings.aiDifficulty = Arrays.AIDifficulty[Config.Raids.RaidStartup.AIDifficulty]; - Inraid.raidMenuSettings.bossEnabled = Config.Raids.RaidStartup.EnableBosses; - Inraid.raidMenuSettings.scavWars = Config.Raids.RaidStartup.ScavWars; - Inraid.raidMenuSettings.taggedAndCursed = Config.Raids.RaidStartup.TaggedAndCursed; - Inraid.save.loot = Config.Raids.RaidStartup.SaveLoot; - } - if (Config.Raids.ForceSeason) { - WeatherValues.overrideSeason = Config.Raids.Season; - } - trader.fence.coopExtractGift.sendGift = !Config.Raids.Exfils.FenceGift; - const Midcore = configServer.getConfig("spt-lostondeath"); - if (Config.Raids.SaveQuestItems) { - Midcore.questItems = false; - } - //Low Ground zero level access - locations["sandbox"].base.RequiredPlayerLevelMax = Config.Raids.SandboxAccessLevel; - //Time acceleration - WeatherValues.acceleration = Config.Raids.Timeacceleration - //Deploy Window time - globals.TimeBeforeDeployLocal = Config.Raids.RaidStartup.TimeBeforeDeployLocal - //Always survived - if (Config.Raids.NoRunThrough) { - globals.exp.match_end.survived_exp_requirement = 0; - globals.exp.match_end.survived_seconds_requirement = 0; - } - DB.locations["laboratory"].base.Insurance = Config.Raids.LabInsurance; - //Remove labs entry keycard - if (Config.Raids.Removelabkey) { - locations["laboratory"].base.AccessKeys = [] - } - - if (Config.Raids.Exfils.ArmorExtract) { - globals.RequirementReferences.Alpinist.splice(2, 1) - } - if (Config.Raids.Exfils.GearExtract) { - globals.RequirementReferences.Alpinist.splice(0, 2) - } - //Remove extracts restrictions - for (let i in locations) { - if (i !== "base") { - let ExitNames = locations[i].base.exits // 3.10 TODO CHECK - for (let x in ExitNames) { - if (ExitNames !== "EXFIL_Train" && (!ExitNames.includes("lab") || ExitNames == "lab_Vent") && ExitNames !== "Saferoom Exfil") {//Ok, i feel dumb again, but i was in a rush ok? - - if (Config.Raids.Exfils.GearExtract && Config.Raids.Exfils.ArmorExtract && locations[i].base.exits[x].PassageRequirement == "Reference") { - FreeExit(locations[i].base.exits[x]) - } - if (Config.Raids.Exfils.NoBackpack && locations[i].base.exits[x].PassageRequirement == "Empty") { - FreeExit(locations[i].base.exits[x]) - } - if (locations[i].base.exits[x].PassageRequirement == "TransferItem" && Config.Raids.EnableCarCoop) { - locations[i].base.exits[x].ExfiltrationTime = Config.Raids.Exfils.CarExtractTime; - switch (i) { - case "woods": - if (Config.Raids.Exfils.CarWoods !== 0) { - locations[i].base.exits[x].Count = Config.Raids.Exfils.CarWoods; + if (Config.Fleamarket.OverrideOffers) { + const offer = { + "from": -100000, + "to": 100000, + "count": Config.Fleamarket.SellOffersAmount } - else { - FreeExit(locations[i].base.exits[x]) - } - break; - case "interchange": - if (Config.Raids.Exfils.CarInterchange !== 0) { - locations[i].base.exits[x].Count = Config.Raids.Exfils.CarInterchange; - } - else { - FreeExit(locations[i].base.exits[x]) - } - break; - case "bigmap": - if (Config.Raids.Exfils.CarCustoms !== 0) { - locations[i].base.exits[x].Count = Config.Raids.Exfils.CarCustoms; - } - else { - FreeExit(locations[i].base.exits[x]) - } - break; - case "tarkovstreets": - if (Config.Raids.Exfils.CarStreets !== 0) { - locations[i].base.exits[x].Count = Config.Raids.Exfils.CarStreets; - } - else { - FreeExit(locations[i].base.exits[x]) - } - break; - case "lighthouse": - if (Config.Raids.Exfils.CarLighthouse !== 0) { - locations[i].base.exits[x].Count = Config.Raids.Exfils.CarLighthouse; - } - else { - FreeExit(locations[i].base.exits[x]) - } - break; - case "shoreline": - if (Config.Raids.Exfils.CarShoreline !== 0) { - locations[i].base.exits[x].Count = Config.Raids.Exfils.CarShoreline; - } - else { - FreeExit(locations[i].base.exits[x]) - } - break; - case "sandbox": - case "sandbox_high": - if (Config.Raids.Exfils.CarSandbox !== 0) { - locations[i].base.exits[x].Count = Config.Raids.Exfils.CarSandbox; - } - else { - FreeExit(locations[i].base.exits[x]) - } - break; - default: - break; + globals.RagFair.maxActiveOfferCount = [] + globals.RagFair.maxActiveOfferCount.push(offer) } - } - if (Config.Raids.Exfils.CoopPaid && Config.Raids.EnableCarCoop && locations[i].base.exits[x].PassageRequirement == "ScavCooperation") { - locations[i].base.exits[x].PassageRequirement = "TransferItem"; - locations[i].base.exits[x].ExfiltrationType = "SharedTimer"; - locations[i].base.exits[x].Id = "5449016a4bdc2d6f028b456f"; - locations[i].base.exits[x].PlayersCount = 0; - locations[i].base.exits[x].RequirementTip = "EXFIL_Item"; - switch (i) { - case "woods": - if (Config.Raids.Exfils.CoopPaidWoods !== 0) { - locations[i].base.exits[x].Count = Config.Raids.Exfils.CoopPaidWoods; - } - else { - FreeExit(locations[i].base.exits[x]) - } - break; - case "tarkovstreets": - if (Config.Raids.Exfils.CoopPaidStreets !== 0) { - locations[i].base.exits[x].Count = Config.Raids.Exfils.CoopPaidStreets; - } - else { - FreeExit(locations[i].base.exits[x]) - } - break; - case "interchange": - if (Config.Raids.Exfils.CoopPaidInterchange !== 0) { - locations[i].base.exits[x].Count = Config.Raids.Exfils.CoopPaidInterchange; - } - else { - FreeExit(locations[i].base.exits[x]) - } - break; - case "lighthouse": - if (Config.Raids.Exfils.CoopPaidLighthouse !== 0) { - locations[i].base.exits[x].Count = Config.Raids.Exfils.CoopPaidLighthouse; - } - else { - FreeExit(locations[i].base.exits[x]) - } - break; - case "rezervbase": - if (Config.Raids.Exfils.CoopPaidReserve !== 0) { - locations[i].base.exits[x].Count = Config.Raids.Exfils.CoopPaidReserve; - } - else { - FreeExit(locations[i].base.exits[x]) - } - break; - case "shoreline": - if (Config.Raids.Exfils.CoopPaidShoreline !== 0) { - locations[i].base.exits[x].Count = Config.Raids.Exfils.CoopPaidShoreline; - } - else { - FreeExit(locations[i].base.exits[x]) - } - break; - case "sandbox": - case "sandbox_high": - if (Config.Raids.Exfils.CoopPaidSandbox !== 0) { - locations[i].base.exits[x].Count = Config.Raids.Exfils.CoopPaidSandbox; - } - else { - FreeExit(locations[i].base.exits[x]) - } - break; - default: - break; + } + //Bundle Chance + Ragfair.dynamic.pack.chancePercent = Config.Fleamarket.DynamicOffers.BundleOfferChance; + //Dynamic offers + Ragfair.dynamic.expiredOfferThreshold = Config.Fleamarket.DynamicOffers.ExpireThreshold; + //Min-Max + Ragfair.dynamic.offerItemCount.min = Config.Fleamarket.DynamicOffers.PerOffer_min; + Ragfair.dynamic.offerItemCount.max = Config.Fleamarket.DynamicOffers.PerOffer_max; + //Unifying the multiplier, not the best case scenario, but it is rather simple to comprehend and modify for common user, they'll never know >_> + Ragfair.dynamic.priceRanges.default.min = Config.Fleamarket.DynamicOffers.Price_min; + Ragfair.dynamic.priceRanges.default.max = Config.Fleamarket.DynamicOffers.Price_max; + Ragfair.dynamic.priceRanges.pack.min = Config.Fleamarket.DynamicOffers.Price_min; + Ragfair.dynamic.priceRanges.pack.max = Config.Fleamarket.DynamicOffers.Price_max; + Ragfair.dynamic.priceRanges.preset.min = Config.Fleamarket.DynamicOffers.Price_min; + Ragfair.dynamic.priceRanges.preset.max = Config.Fleamarket.DynamicOffers.Price_max; + Ragfair.dynamic.endTimeSeconds.min = Config.Fleamarket.DynamicOffers.Time_min * 60; + Ragfair.dynamic.endTimeSeconds.max = Config.Fleamarket.DynamicOffers.Time_max * 60; + Ragfair.dynamic.nonStackableCount.min = Config.Fleamarket.DynamicOffers.NonStack_min; + Ragfair.dynamic.nonStackableCount.max = Config.Fleamarket.DynamicOffers.NonStack_max; + Ragfair.dynamic.stackablePercent.min = Config.Fleamarket.DynamicOffers.Stack_min; + Ragfair.dynamic.stackablePercent.max = Config.Fleamarket.DynamicOffers.Stack_max; + //Currencies + Ragfair.dynamic.currencies["5449016a4bdc2d6f028b456f"] = Config.Fleamarket.DynamicOffers.Roubleoffers; + Ragfair.dynamic.currencies["5696686a4bdc2da3298b456a"] = Config.Fleamarket.DynamicOffers.Dollaroffers; + Ragfair.dynamic.currencies["569668774bdc2da2298b4568"] = Config.Fleamarket.DynamicOffers.Eurooffers; + //Wear condition in offers + if (Config.Fleamarket.EnableFleaConditions) + Ragfair.dynamic.condition["5422acb9af1c889c16000029"].max.min = parseFloat((Config.Fleamarket.FleaConditions.FleaWeapons_Min / 100).toFixed(2)) + Ragfair.dynamic.condition["543be5664bdc2dd4348b4569"].max.min = parseFloat((Config.Fleamarket.FleaConditions.FleaMedical_Min / 100).toFixed(2)) + Ragfair.dynamic.condition["5447e0e74bdc2d3c308b4567"].max.min = parseFloat((Config.Fleamarket.FleaConditions.FleaSpec_Min / 100).toFixed(2)) + Ragfair.dynamic.condition["543be5e94bdc2df1348b4568"].max.min = parseFloat((Config.Fleamarket.FleaConditions.FleaKeys_Min / 100).toFixed(2)) + Ragfair.dynamic.condition["5448e5284bdc2dcb718b4567"].max.min = parseFloat((Config.Fleamarket.FleaConditions.FleaVests_Min / 100).toFixed(2)) + Ragfair.dynamic.condition["57bef4c42459772e8d35a53b"].max.min = parseFloat((Config.Fleamarket.FleaConditions.FleaArmor_Min / 100).toFixed(2)) + Ragfair.dynamic.condition["543be6674bdc2df1348b4569"].max.min = parseFloat((Config.Fleamarket.FleaConditions.FleaFood_Min / 100).toFixed(2)) + Ragfair.dynamic.condition["5422acb9af1c889c16000029"].max.max = parseFloat((Config.Fleamarket.FleaConditions.FleaWeapons_Max / 100).toFixed(2)) + Ragfair.dynamic.condition["543be5664bdc2dd4348b4569"].max.max = parseFloat((Config.Fleamarket.FleaConditions.FleaMedical_Max / 100).toFixed(2)) + Ragfair.dynamic.condition["5447e0e74bdc2d3c308b4567"].max.max = parseFloat((Config.Fleamarket.FleaConditions.FleaSpec_Max / 100).toFixed(2)) + Ragfair.dynamic.condition["543be5e94bdc2df1348b4568"].max.max = parseFloat((Config.Fleamarket.FleaConditions.FleaKeys_Max / 100).toFixed(2)) + Ragfair.dynamic.condition["5448e5284bdc2dcb718b4567"].max.max = parseFloat((Config.Fleamarket.FleaConditions.FleaVests_Max / 100).toFixed(2)) + Ragfair.dynamic.condition["57bef4c42459772e8d35a53b"].max.max = parseFloat((Config.Fleamarket.FleaConditions.FleaArmor_Max / 100).toFixed(2)) + Ragfair.dynamic.condition["543be6674bdc2df1348b4569"].max.max = parseFloat((Config.Fleamarket.FleaConditions.FleaFood_Max / 100).toFixed(2)) + } + //############## LOOT SECTION ################# + if (Config.Loot.EnableLoot) { + //loose loot mults + locs.looseLootMultiplier.bigmap = Config.Loot.Locations.Bigmap.Loose; + locs.looseLootMultiplier.factory4_day = Config.Loot.Locations.FactoryDay.Loose; + locs.looseLootMultiplier.factory4_night = Config.Loot.Locations.FactoryNight.Loose; + locs.looseLootMultiplier.interchange = Config.Loot.Locations.Interchange.Loose; + locs.looseLootMultiplier.laboratory = Config.Loot.Locations.Laboratory.Loose; + locs.looseLootMultiplier.rezervbase = Config.Loot.Locations.Reserve.Loose; + locs.looseLootMultiplier.shoreline = Config.Loot.Locations.Shoreline.Loose; + locs.looseLootMultiplier.woods = Config.Loot.Locations.Woods.Loose; + locs.looseLootMultiplier.lighthouse = Config.Loot.Locations.Lighthouse.Loose; + locs.looseLootMultiplier.tarkovstreets = Config.Loot.Locations.Streets.Loose; + locs.looseLootMultiplier.sandbox = Config.Loot.Locations.Sandbox.Loose; + locs.looseLootMultiplier.sandbox_high = Config.Loot.Locations.SandboxHard.Loose; + //container loot mults + locs.staticLootMultiplier.bigmap = Config.Loot.Locations.Bigmap.Container; + locs.staticLootMultiplier.factory4_day = Config.Loot.Locations.FactoryDay.Container; + locs.staticLootMultiplier.factory4_night = Config.Loot.Locations.FactoryNight.Container; + locs.staticLootMultiplier.interchange = Config.Loot.Locations.Interchange.Container; + locs.staticLootMultiplier.laboratory = Config.Loot.Locations.Laboratory.Container; + locs.staticLootMultiplier.rezervbase = Config.Loot.Locations.Reserve.Container; + locs.staticLootMultiplier.shoreline = Config.Loot.Locations.Shoreline.Container; + locs.staticLootMultiplier.woods = Config.Loot.Locations.Woods.Container; + locs.staticLootMultiplier.lighthouse = Config.Loot.Locations.Lighthouse.Container; + locs.staticLootMultiplier.tarkovstreets = Config.Loot.Locations.Streets.Container; + locs.staticLootMultiplier.sandbox = Config.Loot.Locations.Sandbox.Container; + locs.staticLootMultiplier.sandbox_high = Config.Loot.Locations.SandboxHard.Container; + locs.containerRandomisationSettings.enabled = !Config.Loot.Locations.AllContainers + //############## AIRDROPS SECTION ################## + locations["bigmap"].base.AirdropParameters[0].PlaneAirdropChance = parseFloat((Config.Loot.Airdrops.Bigmap_air / 100).toFixed(2)); + locations["shoreline"].base.AirdropParameters[0].PlaneAirdropChance = parseFloat((Config.Loot.Airdrops.Shoreline_air / 100).toFixed(2)); + locations["rezervbase"].base.AirdropParameters[0].PlaneAirdropChance = parseFloat((Config.Loot.Airdrops.Reserve_air / 100).toFixed(2)); + locations["lighthouse"].base.AirdropParameters[0].PlaneAirdropChance = parseFloat((Config.Loot.Airdrops.Lighthouse_air / 100).toFixed(2)); + locations["interchange"].base.AirdropParameters[0].PlaneAirdropChance = parseFloat((Config.Loot.Airdrops.Interchange_air / 100).toFixed(2)); + locations["tarkovstreets"].base.AirdropParameters[0].PlaneAirdropChance = parseFloat((Config.Loot.Airdrops.Streets_air / 100).toFixed(2)); + locations["sandbox"].base.AirdropParameters[0].PlaneAirdropChance = parseFloat((Config.Loot.Airdrops.Sandbox_air / 100).toFixed(2)); + locations["sandbox_high"].base.AirdropParameters[0].PlaneAirdropChance = parseFloat((Config.Loot.Airdrops.Sandbox_air / 100).toFixed(2)); + locations["woods"].base.AirdropParameters[0].PlaneAirdropChance = parseFloat((Config.Loot.Airdrops.Woods_air / 100).toFixed(2)); + for (let timers in locations) { + if (timers != "develop" && timers != "base" && timers != "privatearea" && timers != "terminal" && timers != "factory4_day" && timers != "hideout" && timers != "laboratory" && timers != "factory4_night" && timers != "town" && timers != "suburbs") {// 3.10 need to rework. + locations[timers].base.AirdropParameters[0].PlaneAirdropStartMin = Config.Loot.Airdrops.AirtimeMin * 60; + locations[timers].base.AirdropParameters[0].PlaneAirdropStartMax = Config.Loot.Airdrops.AirtimeMax * 60; } - } - if (Config.Raids.Exfils.FreeCoop && Config.Raids.EnableCarCoop && locations[i].base.exits[x].PassageRequirement == "ScavCooperation") { - FreeExit(locations[i].base.exits[x]) - } } - } + let Mixed = Config.Loot.Airdrops.Mixed + let Weapon = Config.Loot.Airdrops.Weapon + let Barter = Config.Loot.Airdrops.Barter + let Medical = Config.Loot.Airdrops.Medical + AirdropContents("mixed", Mixed) + AirdropContents("weaponArmor", Weapon) + AirdropContents("barter", Barter) + AirdropContents("foodMedical", Medical) } - } - //Make all extractions available to extract - if (Config.Raids.Exfils.ChanceExtracts) { - for (let i in locations) { - if (i !== "base") { - for (let x in locations[i].base.exits) { - if (locations[i].base.exits[x].Name !== "EXFIL_Train") { - locations[i].base.exits[x].Chance = 100; - } - } - } - } - } - //Extend raids time - if (Config.Raids.RaidTime != 0) { - for (let map in locations) { - if (map !== "base") { - if (isJSONValueDefined(locations[map].base.exit_access_time)) { - locations[map].base.exit_access_time += Config.Raids.RaidTime - } - if (isJSONValueDefined(locations[map].base.EscapeTimeLimit)) { - locations[map].base.EscapeTimeLimit += Config.Raids.RaidTime - } - } - } - } - //Make all extractions of the map available regardless of the infill - if (Config.Raids.Exfils.ExtendedExtracts) { - for (let map in locations) { - switch (map) { - case "bigmap": - for (const extract in locations[map].base.exits) { - locations[map].base.exits[extract].EntryPoints = "Customs,Boiler Tanks" - } - break; - case "interchange": - for (const extract in locations[map].base.exits) { - locations[map].base.exits[extract].EntryPoints = "MallSE,MallNW" - } - break; - case "shoreline": - for (const extract in locations[map].base.exits) { - locations[map].base.exits[extract].EntryPoints = "Village,Riverside" - } - break; - case "woods": - for (const extract in locations[map].base.exits) { - locations[map].base.exits[extract].EntryPoints = "House,Old Station" - } - break; - case "lighthouse": - for (const extract in locations[map].base.exits) { - locations[map].base.exits[extract].EntryPoints = "Tunnel,North" - } - break; - case "tarkovstreets": - for (const extract in locations[map].base.exits) { - locations[map].base.exits[extract].EntryPoints = "E1_2,E6_1,E2_3,E3_4,E4_5,E5_6,E6_1" - } - break; - case "sandbox": - case "sandbox_high": - for (const extract in locations[map].base.exits) { - locations[map].base.exits[extract].EntryPoints = "west,east" - } - break; + //############## BOTS SECTION ################# + if (Config.Bots.EnableBots) { + for (let i in locations) { + if (i !== "base" && locations[i].base.BossLocationSpawn) { + for (let x in locations[i].base.BossLocationSpawn) { + switch (locations[i].base.BossLocationSpawn[x].BossName) { + case "bossBoar": + locations[i].base.BossLocationSpawn[x].BossChance = Config.Bots.AIChance.Kaban + break; + case "bossKolontay": + if (i == "sandbox_high") { + locations[i].base.BossLocationSpawn[x].BossChance = Config.Bots.AIChance.KolontayGZ + } + if (i == "tarkovstreets") { + locations[i].base.BossLocationSpawn[x].BossChance = Config.Bots.AIChance.KolontayStreets + } + break; + case "bossPartisan": + if (i == "bigmap") { + locations[i].base.BossLocationSpawn[x].BossChance = Config.Bots.AIChance.PartisanCustoms + if (Config.Bots.AIChance.ForcePartisan) { + locations[i].base.BossLocationSpawn[x].TriggerId = ""; + locations[i].base.BossLocationSpawn[x].botEvent = ""; + } + } + if (i == "shoreline") { + locations[i].base.BossLocationSpawn[x].BossChance = Config.Bots.AIChance.PartisanShoreline + if (Config.Bots.AIChance.ForcePartisan) { + locations[i].base.BossLocationSpawn[x].TriggerId = ""; + locations[i].base.BossLocationSpawn[x].botEvent = ""; + } + } + if (i == "lighthouse") { + locations[i].base.BossLocationSpawn[x].BossChance = Config.Bots.AIChance.PartisanLighthouse + if (Config.Bots.AIChance.ForcePartisan) { + locations[i].base.BossLocationSpawn[x].TriggerId = ""; + locations[i].base.BossLocationSpawn[x].botEvent = ""; + } + } + if (i == "woods") { + locations[i].base.BossLocationSpawn[x].BossChance = Config.Bots.AIChance.PartisanWoods + if (Config.Bots.AIChance.ForcePartisan) { + locations[i].base.BossLocationSpawn[x].TriggerId = ""; + locations[i].base.BossLocationSpawn[x].botEvent = ""; + } + } + break; + case "bossBully": + locations[i].base.BossLocationSpawn[x].BossChance = Config.Bots.AIChance.Reshala + break; + case "bossSanitar": + locations[i].base.BossLocationSpawn[x].BossChance = Config.Bots.AIChance.Sanitar + break; + case "bossKilla": + if (i == "interchange") { + locations[i].base.BossLocationSpawn[x].BossChance = Config.Bots.AIChance.Killa + } + break; + case "bossTagilla": + if (i == "factory4_day") { + locations[i].base.BossLocationSpawn[x].BossChance = Config.Bots.AIChance.Tagilla + } + if (i == "factory4_night") { + locations[i].base.BossLocationSpawn[x].BossChance = Config.Bots.AIChance.TagillaNight + } + break; + case "bossGluhar": + locations[i].base.BossLocationSpawn[x].BossChance = Config.Bots.AIChance.Glukhar + break; + case "bossKojaniy": + locations[i].base.BossLocationSpawn[x].BossChance = Config.Bots.AIChance.Shturman + break; + case "bossZryachiy": + locations[i].base.BossLocationSpawn[x].BossChance = Config.Bots.AIChance.Zryachiy + break; + case "exUsec": + locations[i].base.BossLocationSpawn[x].BossChance = Config.Bots.AIChance.Rogue + break; + case "bossKnight": + if (i == "woods") { + locations[i].base.BossLocationSpawn[x].BossChance = Config.Bots.AIChance.TrioWoods + } + if (i == "shoreline") { + locations[i].base.BossLocationSpawn[x].BossChance = Config.Bots.AIChance.TrioShoreline + } + if (i == "bigmap") { + locations[i].base.BossLocationSpawn[x].BossChance = Config.Bots.AIChance.Trio + } + if (i == "lighthouse") { + locations[i].base.BossLocationSpawn[x].BossChance = Config.Bots.AIChance.TrioLighthouse + } + break; + case "pmcBot": + if (i == "laboratory") { + locations[i].base.BossLocationSpawn[x].BossChance = Config.Bots.AIChance.RaiderLab + } + if (i == "rezervbase") { + locations[i].base.BossLocationSpawn[x].BossChance = Config.Bots.AIChance.RaiderReserve + } + break; + case "sectantPriest": + if (i == "factory4_night") { + locations[i].base.BossLocationSpawn[x].BossChance = Config.Bots.AIChance.CultistFactory + } + if (i == "woods") { - default: - break; - } + locations[i].base.BossLocationSpawn[x].BossChance = Config.Bots.AIChance.CultistWoods + } + if (i == "bigmap") { + locations[i].base.BossLocationSpawn[x].BossChance = Config.Bots.AIChance.CultistCustoms + } + if (i == "shoreline") { + locations[i].base.BossLocationSpawn[x].BossChance = Config.Bots.AIChance.CultistShoreline + } + break; + } + } + } + } + const WepDur = Config.Bots.WeaponDurab; + const ArmorDur = Config.Bots.ArmorDurab; + const BotWepMinID = [WepDur.ScavMin, WepDur.MarksmanMin, WepDur.RaiderMin, WepDur.RogueMin, WepDur.PMCMin, WepDur.BossMin, WepDur.FollowerMin]; + const BotWepMaxID = [WepDur.ScavMax, WepDur.MarksmanMax, WepDur.RaiderMax, WepDur.RogueMax, WepDur.PMCMax, WepDur.BossMax, WepDur.FollowerMax]; + const BotArmorMinID = [ArmorDur.ScavMin, ArmorDur.MarksmanMin, ArmorDur.RaiderMin, ArmorDur.RogueMin, ArmorDur.PMCMin, ArmorDur.BossMin, ArmorDur.FollowerMin]; + const BotArmorMaxID = [ArmorDur.ScavMax, ArmorDur.MarksmanMax, ArmorDur.RaiderMax, ArmorDur.RogueMax, ArmorDur.PMCMax, ArmorDur.BossMax, ArmorDur.FollowerMax]; + + const BotTypeID = ["assault", "marksman", "pmcbot", "exusec", "pmc", "boss", "follower"] + for (let durab in BotTypeID) { + Bots.durability[BotTypeID[durab]].weapon.lowestMax = BotWepMinID[durab]; + Bots.durability[BotTypeID[durab]].weapon.highestMax = BotWepMaxID[durab]; + Bots.durability[BotTypeID[durab]].armor.maxDelta = 100 - BotArmorMinID[durab]; + Bots.durability[BotTypeID[durab]].armor.minDelta = 100 - BotArmorMaxID[durab]; + switch (BotTypeID[durab]) { + case "assault": + Bots.durability["cursedassault"].weapon.lowestMax = BotWepMinID[durab] + Bots.durability["cursedassault"].weapon.highestMax = BotWepMaxID[durab] + Bots.durability["cursedassault"].armor.maxDelta = 100 - BotArmorMinID[durab]; + Bots.durability["cursedassault"].armor.minDelta = 100 - BotArmorMaxID[durab]; + + Bots.durability["crazyassaultevent"].weapon.lowestMax = BotWepMinID[durab] + Bots.durability["crazyassaultevent"].weapon.highestMax = BotWepMaxID[durab] + Bots.durability["crazyassaultevent"].armor.maxDelta = 100 - BotArmorMinID[durab]; + Bots.durability["crazyassaultevent"].armor.minDelta = 100 - BotArmorMaxID[durab]; + break; + case "pmcbot": + Bots.durability["arenafighterevent"].weapon.lowestMax = BotWepMinID[durab] + Bots.durability["arenafighterevent"].weapon.highestMax = BotWepMaxID[durab] + Bots.durability["arenafighterevent"].armor.maxDelta = 100 - BotArmorMinID[durab]; + Bots.durability["arenafighterevent"].armor.minDelta = 100 - BotArmorMaxID[durab]; + break + case "boss": + Bots.durability["sectantpriest"].weapon.lowestMax = BotWepMinID[durab]; + Bots.durability["sectantpriest"].weapon.highestMax = BotWepMaxID[durab]; + Bots.durability["sectantpriest"].armor.maxDelta = 100 - BotArmorMinID[durab]; + Bots.durability["sectantpriest"].armor.minDelta = 100 - BotArmorMaxID[durab]; + break; + case "follower": + Bots.durability["sectantwarrior"].weapon.lowestMax = BotWepMinID[durab]; + Bots.durability["sectantwarrior"].weapon.highestMax = BotWepMaxID[durab]; + Bots.durability["sectantwarrior"].armor.maxDelta = 100 - BotArmorMinID[durab]; + Bots.durability["sectantwarrior"].armor.minDelta = 100 - BotArmorMaxID[durab]; + break; + } + } } - } - Events.events[0].settings.zombieSettings.enabled = !Config.Raids.RaidEvents.DisableZombies - //Explanation of this - Turns out SPT's method doesn't seem to convert upper case to lower case with the maps, while BSG's UI requests exactly uppercased scenario - //In the end we have bigmap and lab only spawning waves because they are consistent on both sides. I hate my life. - if (Config.Raids.RaidEvents.RandomInfectionLevel) { - Events.events[0].settings.zombieSettings.mapInfectionAmount = - { - "laboratory": 100, - "bigmap": Math.floor(Math.random() * 100), - "woods": Math.floor(Math.random() * 100), - "shoreline": Math.floor(Math.random() * 100), - "sandbox": Math.floor(Math.random() * 100), - "rezervbase": Math.floor(Math.random() * 100), - "tarkovstreets": Math.floor(Math.random() * 100), - "factory4": Math.floor(Math.random() * 100), - "lighthouse": Math.floor(Math.random() * 100), - "interchange": Math.floor(Math.random() * 100) + //############## INSURANCE/REPAIR SECTION ############ + if (Config.Services.EnableServices) { + //Repair.priceMultiplier = Config.Insurance.RepairBox.RepairMult; Disabled due to visual bug - it doesn't show converted number, the function itself is working tho + Repair.armorKitSkillPointGainPerRepairPointMultiplier = Config.Services.RepairBox.ArmorSkillMult; + Repair.weaponTreatment.pointGainMultiplier = Config.Services.RepairBox.WeaponMaintenanceSkillMult; + Repair.repairKitIntellectGainMultiplier.weapon = Config.Services.RepairBox.IntellectSkillMultWeaponKit; + Repair.repairKitIntellectGainMultiplier.armor = Config.Services.RepairBox.IntellectSkillMultArmorKit; + Repair.maxIntellectGainPerRepair.kit = Config.Services.RepairBox.IntellectSkillLimitKit; + Repair.maxIntellectGainPerRepair.trader = Config.Services.RepairBox.IntellectSkillLimitTraders; + Repair.applyRandomizeDurabilityLoss = !Config.Services.RepairBox.NoRandomRepair; + if (Config.Services.EnableInsurance) { + Insurance.returnChancePercent["54cb50c76803fa8b248b4571"] = Config.Services.ReturnChancePrapor; + Insurance.returnChancePercent["54cb57776803fa99248b456e"] = Config.Services.ReturnChanceTherapist; + traders["54cb50c76803fa8b248b4571"].base.insurance.max_storage_time = Config.Services.PraporStorageTime; + traders["54cb57776803fa99248b456e"].base.insurance.max_storage_time = Config.Services.TherapistStorageTime; + traders["54cb50c76803fa8b248b4571"].base.insurance.min_return_hour = Config.Services.Prapor_Min; + traders["54cb50c76803fa8b248b4571"].base.insurance.max_return_hour = Config.Services.Prapor_Max; + traders["54cb57776803fa99248b456e"].base.insurance.min_return_hour = Config.Services.Therapist_Min; + traders["54cb57776803fa99248b456e"].base.insurance.max_return_hour = Config.Services.Therapist_Max; + Insurance.chanceNoAttachmentsTakenPercent = Config.Services.InsuranceAttachmentChance + //3.9.0 insurance fix + new fields + Insurance.runIntervalSeconds = Config.Services.InsuranceInterval + if (Config.Services.EnableTimeOverride) { + Insurance.returnTimeOverrideSeconds = Config.Services.InsuranceTimeOverride + } + let TherapistMult = [Config.Services.InsuranceMultTherapistLvl1, Config.Services.InsuranceMultTherapistLvl2, Config.Services.InsuranceMultTherapistLvl3, Config.Services.InsuranceMultTherapistLvl4] + for (let level in traders["54cb57776803fa99248b456e"].base.loyaltyLevels) { + traders["54cb57776803fa99248b456e"].base.loyaltyLevels[level].insurance_price_coef = TherapistMult[level] + } + let PraporMult = [Config.Services.InsuranceMultPraporLvl1, Config.Services.InsuranceMultPraporLvl2, Config.Services.InsuranceMultPraporLvl3, Config.Services.InsuranceMultPraporLvl4] + for (let level in traders["54cb50c76803fa8b248b4571"].base.loyaltyLevels) { + traders["54cb50c76803fa8b248b4571"].base.loyaltyLevels[level].insurance_price_coef = PraporMult[level] + } + } + //Enable all clothes available for both side + if (Config.Services.ClothesAnySide) { + for (let suit in suits) { + let suitData = suits[suit] + if (suitData._parent === "5cd944ca1388ce03a44dc2a4" || suitData._parent === "5cd944d01388ce000a659df9") { + suitData._props.Side = ["Bear", "Usec"]; + } + } + } + if (Config.Services.ClothesFree || Config.Services.ClothesLevelUnlock) { + for (let tradercloth in traders) { + if (traders[tradercloth].suits) { + for (let file in traders[tradercloth].suits) { + let fileData = traders[tradercloth].suits[file] + if (Config.Services.ClothesLevelUnlock) { + fileData.requirements.loyaltyLevel = 1; + fileData.requirements.profileLevel = 1; + fileData.requirements.standing = 0; + fileData.requirements.questRequirements = [];//Only adik hits this + fileData.requirements.achievementRequirements = []; // 1.10.1 Adik once again - removing the requirement for 'Master of Ultra' achievement. + } + //fileData.requirements.skillRequirements = [];//This is useless, it always stands for empty + if (Config.Services.ClothesFree) { + fileData.requirements.itemRequirements = []; + } + } + } + } + } + if (Config.Services.EnableHealMarkup) { + let TherapistLevels = [Config.Services.TherapistLvl1, Config.Services.TherapistLvl2, Config.Services.TherapistLvl3, Config.Services.TherapistLvl4] + for (let level in traders["54cb57776803fa99248b456e"].base.loyaltyLevels) { + traders["54cb57776803fa99248b456e"].base.loyaltyLevels[level].heal_price_coef = TherapistLevels[level] * 100 + } + globals.Health.HealPrice.TrialLevels = Config.Services.FreeHealLvl + globals.Health.HealPrice.TrialRaids = Config.Services.FreeHealRaids + } + if (Config.Services.EnableRepair) { + for (let CurTrader in traders) { + if (CurTrader !== "ragfair" && (CurTrader == "5a7c2eca46aef81a7ca2145d" || CurTrader == "5ac3b934156ae10c4430e83c" || CurTrader == "5c0647fdd443bc2504c2d371" || CurTrader == "54cb50c76803fa8b248b4571" || CurTrader == "54cb57776803fa99248b456e" || CurTrader == "579dc571d53a0658a154fbec" || CurTrader == "5935c25fb3acc3127c3d8cd9" || CurTrader == "58330581ace78e27b8b10cee")) { + for (let level in traders[CurTrader].base.loyaltyLevels) { + traders[CurTrader].base.loyaltyLevels[level].repair_price_coef *= Config.Services.RepairBox.RepairMult; + } + } + } + if (Config.Services.RepairBox.OpArmorRepair) { + for (let armormats in globals.ArmorMaterials) { + globals.ArmorMaterials[armormats].MaxRepairDegradation = 0 + globals.ArmorMaterials[armormats].MinRepairDegradation = 0 + globals.ArmorMaterials[armormats].MaxRepairKitDegradation = 0 + globals.ArmorMaterials[armormats].MinRepairKitDegradation = 0 + } + } + if (Config.Services.RepairBox.OpGunRepair) { + for (let stuff in items) { + if (items[stuff]._props.MaxRepairDegradation !== undefined && items[stuff]._props.MaxRepairKitDegradation !== undefined) { + EditSimpleItemData(stuff, "MinRepairDegradation", 0); + EditSimpleItemData(stuff, "MaxRepairDegradation", 0); + EditSimpleItemData(stuff, "MinRepairKitDegradation", 0); + EditSimpleItemData(stuff, "MaxRepairKitDegradation", 0); + } + } + } + } } - //Hopefully a temporary fix - Events.events[0].settings.zombieSettings.mapInfectionAmount["Woods"] = Events.events[0].settings.zombieSettings.mapInfectionAmount["woods"] - Events.events[0].settings.zombieSettings.mapInfectionAmount["Shoreline"] = Events.events[0].settings.zombieSettings.mapInfectionAmount["shoreline"] - Events.events[0].settings.zombieSettings.mapInfectionAmount["RezervBase"] = Events.events[0].settings.zombieSettings.mapInfectionAmount["rezervbase"] - Events.events[0].settings.zombieSettings.mapInfectionAmount["TarkovStreets"] = Events.events[0].settings.zombieSettings.mapInfectionAmount["tarkovstreets"] - Events.events[0].settings.zombieSettings.mapInfectionAmount["Lighthouse"] = Events.events[0].settings.zombieSettings.mapInfectionAmount["lighthouse"] - Events.events[0].settings.zombieSettings.mapInfectionAmount["Interchange"] = Events.events[0].settings.zombieSettings.mapInfectionAmount["interchange"] - for(let map in Events.eventBossSpawns.halloweenzombies) - { - for (let wave in Events.eventBossSpawns.halloweenzombies[map]) - { - switch(map)//Feature - Infection level affects spawn chances. + //############## CSM SECTION ################## + if (Config.CSM.EnableCSM) { + if (Config.CSM.CustomPocket) { + const JsonUtil = container.resolve("JsonUtil"); + let CustomPocketItem = JsonUtil.clone(items["627a4e6b255f7527fb05a0f6"]) + let PocketSize = Config.CSM.Pockets + CustomPocketItem._id = "a8edfb0bce53d103d3f62b9b"; + for (let cell in CustomPocketItem._props.Grids)//tried to make less code, made more, smh. + { + CustomPocketItem._props.Grids[cell]._parent = "a8edfb0bce53d103d3f62b9b" + } + for (let cell in CustomPocketItem._props.Slots) { + CustomPocketItem._props.Slots[cell]._parent = "a8edfb0bce53d103d3f62b9b" + } + CustomPocketItem._props.Grids[0]._id = "a8edfb0bce53d103d3f62b0b" + CustomPocketItem._props.Grids[0]._props.cellsH = PocketSize.FirstWidth + CustomPocketItem._props.Grids[0]._props.cellsV = PocketSize.FirstHeight + CustomPocketItem._props.Grids[1]._id = "a8edfb0bce53d103d3f62b1b" + CustomPocketItem._props.Grids[1]._props.cellsH = PocketSize.SecondWidth + CustomPocketItem._props.Grids[1]._props.cellsV = PocketSize.SecondHeight + CustomPocketItem._props.Grids[2]._id = "a8edfb0bce53d103d3f62b2b" + CustomPocketItem._props.Grids[2]._props.cellsH = PocketSize.ThirdWidth + CustomPocketItem._props.Grids[2]._props.cellsV = PocketSize.ThirdHeight + CustomPocketItem._props.Grids[3]._id = "a8edfb0bce53d103d3f62b3b" + CustomPocketItem._props.Grids[3]._props.cellsH = PocketSize.FourthWidth + CustomPocketItem._props.Grids[3]._props.cellsV = PocketSize.FourthHeight + CustomPocketItem._props.Slots[0]._id = "a8edfb0bce53d103d3f62b4b" + CustomPocketItem._props.Slots[1]._id = "a8edfb0bce53d103d3f62b5b" + CustomPocketItem._props.Slots[2]._id = "a8edfb0bce53d103d3f62b6b" + if (PocketSize.FourthWidth == 0 || PocketSize.FourthHeight == 0) { + CustomPocketItem._props.Grids.splice(3, 1); + } + if (PocketSize.ThirdWidth == 0 || PocketSize.ThirdHeight == 0) { + CustomPocketItem._props.Grids.splice(2, 1); + } + if (PocketSize.SecondWidth == 0 || PocketSize.SecondHeight == 0) { + CustomPocketItem._props.Grids.splice(1, 1); + } + if (PocketSize.FirstWidth == 0 || PocketSize.FirstHeight == 0) { + CustomPocketItem._props.Grids.splice(0, 1); + } + + switch (true) { + case Config.CSM.Pockets.SpecSlots == 0: + CustomPocketItem._props.Slots.splice(0, 3); + break; + case Config.CSM.Pockets.SpecSlots == 1: + CustomPocketItem._props.Slots.splice(1, 2); + break; + case Config.CSM.Pockets.SpecSlots == 2: + CustomPocketItem._props.Slots.splice(2, 1); + break; + case Config.CSM.Pockets.SpecSlots == 3: + break; + case Config.CSM.Pockets.SpecSlots >= 4://Graduality done, switched `switch` to true statement and expressions. + CustomPocketItem._props.Slots[3] = JsonUtil.clone(CustomPocketItem._props.Slots[2]) + CustomPocketItem._props.Slots[3]._id = "a8edfb0bce53d103d3f62b7b" + CustomPocketItem._props.Slots[3]._name = "SpecialSlot4" + CustomPocketItem._props.Slots[3]._parent = "a8edfb0bce53d103d3f62b9b" + Insurance.blacklistedEquipment.push("SpecialSlot4") + case Config.CSM.Pockets.SpecSlots == 5: + CustomPocketItem._props.Slots[4] = JsonUtil.clone(CustomPocketItem._props.Slots[2]) + CustomPocketItem._props.Slots[4]._id = "a8edfb0bce53d103d3f62b8b" + CustomPocketItem._props.Slots[4]._name = "SpecialSlot5" + CustomPocketItem._props.Slots[4]._parent = "a8edfb0bce53d103d3f62b9b" + Insurance.blacklistedEquipment.push("SpecialSlot5") + break; + } + //This is a solution to avoid removing cases from bodies if they die. + let IDsToFilter = ["5783c43d2459774bbe137486", "60b0f6c058e0b0481a09ad11", "619cbf9e0a7c3a1a2731940a", "619cbf7d23893217ec30b689", "59fafd4b86f7745ca07e1232", "62a09d3bcf4a99369e262447"]; + let Pockets = Config.CSM.Pockets + let CasesToFilter = [Pockets.SpecSimpleWallet, Pockets.SpecWZWallet, Pockets.SpecKeycardHolder, Pockets.SpecInjectorCase, Pockets.SpecKeytool, Pockets.SpecGKeychain]; + for (let ID in IDsToFilter) { + items[IDsToFilter[ID]]._props.DiscardLimit = -1; + items[IDsToFilter[ID]]._props.InsuranceDisabled = true; + } + for (let specialslots in CustomPocketItem._props.Slots) { + for (let element in IDsToFilter) { + if (CasesToFilter[element]) { + CustomPocketItem._props.Slots[specialslots]._props.filters[0].Filter.push(IDsToFilter[element]) + } + } + //items[IDsToFilter[specialslots]]._props.HideEntrails = true; + } + items["a8edfb0bce53d103d3f62b9b"] = CustomPocketItem; + //items["5795f317245977243854e041"]._props.HideEntrails = true; Still unsure what does it do + } + if (Config.CSM.EnableSecureCases) { + const SecCon = Config.CSM.SecureContainers + + const SecHeight = [ + SecCon.AlphaHeight, + SecCon.KappaHeight, + SecCon.BetaHeight, + SecCon.EpsilonHeight, + SecCon.GammaHeight, + SecCon.GammaTUEHeight, + SecCon.WaistPouchHeight, + SecCon.DevHeight + ]; + const SecWidth = [ + SecCon.AlphaWidth, + SecCon.KappaWidth, + SecCon.BetaWidth, + SecCon.EpsilonWidth, + SecCon.GammaWidth, + SecCon.GammaTUEWidth, + SecCon.WaistPouchWidth, + SecCon.DevWidth + ]; + for (let SecConts in Arrays.SecConID) { + items[Arrays.SecConID[SecConts]]._props.Grids[0]._props["cellsV"] = SecHeight[SecConts]; + items[Arrays.SecConID[SecConts]]._props.Grids[0]._props["cellsH"] = SecWidth[SecConts]; + } + } + if (Config.CSM.EnableCases) { + const Cases = Config.CSM.Cases + const Size = [ + Cases.MoneyCase, + Cases.SimpleWallet, + Cases.WZWallet, + Cases.GrenadeCase, + Cases.ItemsCase, + Cases.WeaponCase, + Cases.LuckyScav, + Cases.AmmunitionCase, + Cases.MagazineCase, + Cases.DogtagCase, + Cases.MedicineCase, + Cases.ThiccItemsCase, + Cases.ThiccWeaponCase, + Cases.SiccCase, + Cases.Keytool, + Cases.DocumentsCase, + Cases.PistolCase, + Cases.Holodilnick, + Cases.InjectorCase, + Cases.KeycardHolderCase, + Cases.GKeychain, + Cases.StreamerCase + ] + const Filts = [ // I think i can shortcut this eventually + Cases.MoneyCase.Filter, + Cases.SimpleWallet.Filter, + Cases.WZWallet.Filter, + Cases.GrenadeCase.Filter, + Cases.ItemsCase.Filter, + Cases.WeaponCase.Filter, + Cases.LuckyScav.Filter, + Cases.AmmunitionCase.Filter, + Cases.MagazineCase.Filter, + Cases.DogtagCase.Filter, + Cases.MedicineCase.Filter, + Cases.ThiccItemsCase.Filter, + Cases.ThiccWeaponCase.Filter, + Cases.SiccCase.Filter, + Cases.Keytool.Filter, + Cases.DocumentsCase.Filter, + Cases.PistolCase.Filter, + Cases.Holodilnick.Filter, + Cases.InjectorCase.Filter, + Cases.KeycardHolderCase.Filter, + Cases.GKeychain.Filter, + Cases.StreamerCase.Filter + ] + for (let Case in Arrays.CasesID) { + items[Arrays.CasesID[Case]]._props.Grids[0]._props["cellsV"] = Size[Case].Height; + items[Arrays.CasesID[Case]]._props.Grids[0]._props["cellsH"] = Size[Case].Width; + } + //Filters + for (let Filters in Filts) { + if (Filts[Filters]) // To check whether checkmark is true or false + { + items[Arrays.CasesID[Filters]]._props.Grids[0]._props.filters = []; + } + } + } + } + //############## ITEMS SECTION ################ + if (Config.Items.EnableItems) { + + //Price Modifier + for (const item in DB.templates.handbook.Items) { + if (DB.templates.handbook.Items[item].ParentId !== "5b5f78b786f77447ed5636af" && DB.templates.handbook.Items[item].Price != null) { + DB.templates.handbook.Items[item].Price = (DB.templates.handbook.Items[item].Price * Config.Items.ItemPriceMult) + } + } + //Loading-Unloading rounds in a magazine + globals.BaseUnloadTime = globals.BaseUnloadTime * Config.Items.AmmoLoadSpeed; + globals.BaseLoadTime = globals.BaseLoadTime * Config.Items.AmmoLoadSpeed; + //Signal Pistol into Special slots + if (Config.Items.AddSignalPistolToSpec) { + if (items["a8edfb0bce53d103d3f62b9b"] !== undefined) { + for (let specialslots in items["a8edfb0bce53d103d3f62b9b"]._props.Slots) { + items["a8edfb0bce53d103d3f62b9b"]._props.Slots[specialslots]._props.filters[0].Filter.push("620109578d82e67e7911abf2") + } + } + if (items["627a4e6b255f7527fb05a0f6"] !== undefined) { + for (let specialslots in items["627a4e6b255f7527fb05a0f6"]._props.Slots) { + items["627a4e6b255f7527fb05a0f6"]._props.Slots[specialslots]._props.filters[0].Filter.push("620109578d82e67e7911abf2") + } + } + if (items["65e080be269cbd5c5005e529"] !== undefined) { + for (let specialslots in items["65e080be269cbd5c5005e529"]._props.Slots) { + items["65e080be269cbd5c5005e529"]._props.Slots[specialslots]._props.filters[0].Filter.push("620109578d82e67e7911abf2") + } + } + } + for (const id in items) { + let base = items[id] + //Examining time + if (base._type == "Item" && base._props.ExamineTime !== undefined) { + EditSimpleItemData(id, "ExamineTime", Config.Items.ExamineTime); + } + //Fragmentation Multiplier + if (base._props.FragmentationChance !== undefined) { + EditSimpleItemData(id, "FragmentationChance", parseFloat(base._props.FragmentationChance * Config.Items.FragmentMult).toFixed(2)); + } + //Heat Factor Multiplier + if (base._props.HeatFactor !== undefined) { + EditSimpleItemData(id, "HeatFactor", parseFloat(base._props.HeatFactor * Config.Items.HeatFactor).toFixed(4)); + } + //Dropping items in raid rather deleting them + if (base._type == "Item" && base._props.DiscardLimit !== undefined && Config.Items.RaidDrop) { + EditSimpleItemData(id, "DiscardLimit", -1); + } + //Turns off weapon overheat + if (base._props.AllowOverheat !== undefined && Config.Items.WeaponHeatOff) { + EditSimpleItemData(id, "AllowOverheat", false); + } + //Malfunction chance + if ((base._parent == "5447b5cf4bdc2d65278b4567" || base._parent == "5447b6254bdc2dc3278b4568" || items[id]._parent == "5447b5f14bdc2d61278b4567" || items[id]._parent == "5447bed64bdc2d97278b4568" || items[id]._parent == "5447b6094bdc2dc3278b4567" || items[id]._parent == "5447b5e04bdc2d62278b4567" || items[id]._parent == "5447b6194bdc2d67278b4567") && items[id]._props.BaseMalfunctionChance !== undefined) { + EditSimpleItemData(id, "BaseMalfunctionChance", parseFloat(base._props.BaseMalfunctionChance * Config.Items.MalfunctChanceMult).toFixed(6)); + } + if (base._parent == "5448bc234bdc2d3c308b4569" && base._props.MalfunctionChance !== undefined) { + EditSimpleItemData(id, "MalfunctionChance", parseFloat(base._props.MalfunctionChance * Config.Items.MalfunctChanceMult).toFixed(2)); + } + //Misfire chance + if (base._parent == "5485a8684bdc2da71d8b4567" && base._props.MalfMisfireChance !== undefined) { + EditSimpleItemData(id, "MalfMisfireChance", parseFloat(base._props.MalfMisfireChance * Config.Items.MisfireChance).toFixed(3)); + } + //Examine all items + if (Config.Items.AllExaminedItems && Config.Items.ExamineKeys) { + EditSimpleItemData(id, "ExaminedByDefault", true); + } + //Examine all items EXCEPT KEYS, checking for parent IDs of mechanical, keycards and keys in general just in case. + else if (Config.Items.AllExaminedItems && base._parent !== "5c99f98d86f7745c314214b3" && base._parent !== "5c164d2286f774194c5e69fa" && base._parent !== "543be5e94bdc2df1348b4568") { + EditSimpleItemData(id, "ExaminedByDefault", true); + } + //Change the weight + if (base._type !== "Node" && base._type !== undefined && (base._parent !== "557596e64bdc2dc2118b4571" || base._parent !== "55d720f24bdc2d88028b456d")) { + EditSimpleItemData(id, "Weight", parseFloat(Config.Items.WeightChanger * base._props.Weight).toFixed(3)); + } + if (Config.Items.NoGearPenalty) { + if (base._props.mousePenalty) { + EditSimpleItemData(id, "mousePenalty", 0) + } + if (base._props.weaponErgonomicPenalty) { + EditSimpleItemData(id, "weaponErgonomicPenalty", 0) + } + if (base._props.speedPenaltyPercent) { + EditSimpleItemData(id, "speedPenaltyPercent", 0) + } + } + //Ammo Stacks + if (base._parent.includes("5485a8684bdc2da71d8b4567") && Config.Items.AmmoSwitch) { + let str = base._name//.split("_", 2) + if (AmmoFilter(Arrays.Pistol, str)) { + EditSimpleItemData(id, "StackMaxSize", Config.Items.AmmoStacks.PistolRound) + } + else if (AmmoFilter(Arrays.Shotgun, str)) { + EditSimpleItemData(id, "StackMaxSize", Config.Items.AmmoStacks.ShotgunRound) + } + else if (AmmoFilter(Arrays.ARifle, str)) { + EditSimpleItemData(id, "StackMaxSize", Config.Items.AmmoStacks.RifleRound) + } + else if (AmmoFilter(Arrays.MRifle, str)) { + EditSimpleItemData(id, "StackMaxSize", Config.Items.AmmoStacks.MarksmanRound) + } + } + //Change money stacks + if (base._parent == "543be5dd4bdc2deb348b4569" && base._props.StackMaxSize !== undefined && Config.Items.EnableCurrency) { + switch (base._id) { + case "569668774bdc2da2298b4568": + EditSimpleItemData(id, "StackMaxSize", Config.Items.EuroStack); + break; + case "5696686a4bdc2da3298b456a": + EditSimpleItemData(id, "StackMaxSize", Config.Items.DollarStack); + break; + case "5d235b4d86f7742e017bc88a": + EditSimpleItemData(id, "StackMaxSize", Config.Items.GPStack); + break; + default: + EditSimpleItemData(id, "StackMaxSize", Config.Items.RubStack); + break; + } + } + //Allow armored rigs with armors + if (Config.Items.EquipRigsWithArmors && base._props.BlocksArmorVest !== undefined) { + EditSimpleItemData(id, "BlocksArmorVest", false); + } + //Remove filters + if (Config.Items.RemoveSecureContainerFilters && base._parent == "5448bf274bdc2dfc2f8b456a" && base._props.Grids[0]._props.filters !== undefined) { + base._props.Grids[0]._props.filters = []; + } + if (Config.Items.RemoveBackpacksRestrictions && base._parent == "5448e53e4bdc2d60728b4567" && base._props.Grids[0]._props.filters !== undefined) { + base._props.Grids[0]._props.filters = []; + } + //Change items experience gain + if (base._props.LootExperience !== undefined) { + let calculation = Math.round(base._props.LootExperience * Config.Items.LootExp); + EditSimpleItemData(id, "LootExperience", calculation); + } + if (base._props.ExamineExperience !== undefined) { + let calculation = Math.round(base._props.ExamineExperience * Config.Items.ExamineExp); + EditSimpleItemData(id, "ExamineExperience", calculation); + } + //Remove the keys usage - God i hate how i wrote it + if (Config.Items.EnableKeys) { + if ((base._parent == "5c99f98d86f7745c314214b3") && base._props.MaximumNumberOfUsage !== undefined && Config.Items.InfiniteKeys) { + + if (base._parent == "5c99f98d86f7745c314214b3" && base._props.MaximumNumberOfUsage == 1 && !Config.Items.AvoidSingleKeys) { + base._props.MaximumNumberOfUsage = 0 + } + if (Arrays.MarkedKeys.includes(base._id) && !Config.Items.AvoidMarkedKeys) { + base._props.MaximumNumberOfUsage = 0 + } + if (!(Arrays.MarkedKeys.includes(base._id)) && base._props.MaximumNumberOfUsage !== 1) { + base._props.MaximumNumberOfUsage = 0 + } + } + + if (base._parent == "5c164d2286f774194c5e69fa" && base._props.MaximumNumberOfUsage !== undefined && Config.Items.InfiniteKeycards) { + base._props.MaximumNumberOfUsage = 0 + } + if (base._parent == "5c99f98d86f7745c314214b3" && base._props.MaximumNumberOfUsage != 0) { + base._props.MaximumNumberOfUsage *= Config.Items.KeyUseMult + if (base._props.MaximumNumberOfUsage > Config.Items.KeyDurabilityThreshold) { + base._props.MaximumNumberOfUsage = Config.Items.KeyDurabilityThreshold + } + } + if (base._parent == "5c164d2286f774194c5e69fa" && base._props.MaximumNumberOfUsage != 0) { + base._props.MaximumNumberOfUsage *= Config.Items.KeycardUseMult + if (base._props.MaximumNumberOfUsage > Config.Items.KeyDurabilityThreshold) { + base._props.MaximumNumberOfUsage = Config.Items.KeyDurabilityThreshold + } + } + } + } + if (Config.Items.SMGToHolster) { + items["55d7217a4bdc2d86028b456d"]._props.Slots[2]._props.filters[0].Filter.push("5447b5e04bdc2d62278b4567"); + } + if (Config.Items.PistolToMain) { + items["55d7217a4bdc2d86028b456d"]._props.Slots[0]._props.filters[0].Filter.push("5447b5cf4bdc2d65278b4567", "617f1ef5e8b54b0998387733"); + items["55d7217a4bdc2d86028b456d"]._props.Slots[1]._props.filters[0].Filter.push("5447b5cf4bdc2d65278b4567", "617f1ef5e8b54b0998387733"); + } + if (Config.Items.RemoveRaidRestr) { + globals.RestrictionsInRaid = [] + } + if (Config.Items.IDChanger) { + //Edit item properties, i know it looks stupid, but hey - it works and i like it. + //5th revision, now including separate fields for filters, parents and expressions. + Logger.info("[SVM] Custom Properties is loading", "blue") + try { + if (Config.Items.IDParent.length > 0) { //ID=ParentID, same as above + let ParentList = Config.Items.IDParent.split("\r\n") + let IDArray = []; + for (let Line in ParentList) { + if (!ParentList[Line].startsWith("#") && !ParentList[Line].startsWith("//") && !ParentList[Line] == "") { + const Variables = ParentList[Line].split(":") + Logger.info("Parent: " + Variables) + for (let ids in items) { + if (Variables[0] == items[ids]._parent) { + IDArray.push(items[ids]._id); + } + } + Logger.info("Affected by parent: ") + Logger.info(IDArray) + for (let ID in IDArray) { + Variables[0] = IDArray[ID] + IDChanger(Variables) + } + } + } + } + if (Config.Items.IDDefault.length > 0) {//ID:Variable:Value + let DefaultList = Config.Items.IDDefault.split("\r\n") + for (let Line in DefaultList) { + if (!DefaultList[Line].startsWith("#") && !DefaultList[Line].startsWith("//") && !DefaultList[Line] == "") { + let Variables = DefaultList[Line].split(":") + Logger.info("Default: " + Variables) + IDChanger(Variables) + } + } + } + if (Config.Items.IDFilter.length > 0) { //ID:Slots/Grids:Grid/Slot Number:Filter/ExcludedFilter:PushIntoArray + let FilterList = Config.Items.IDFilter.split("\r\n") + for (let Line in FilterList) { + const Variables = FilterList[Line].split(":") + Logger.info("Filter: " + Variables) + if (Variables.length === 5) { + let check = CheckType(Variables[4]) + for (let fields in check) { + items[Variables[0]]._props[Variables[1]][Variables[2]]._props.filters[0][Variables[3]].push(check[fields]) + } + } + else { + Logger.error("[SVM] INVENTORY AND ITEMS - Filters ID - failed to apply\n") + } + } + } + if (Config.Items.IDPrice.length > 0) { //ID:Expression:Number + const handbook = DB.templates.handbook.Items + let IDPriceLines = Config.Items.IDPrice.split("\r\n") + for (let Line in IDPriceLines) { + if (!IDPriceLines[Line].startsWith("#") && !IDPriceLines[Line].startsWith("//") && !IDPriceLines[Line] == "") { + const Variables = IDPriceLines[Line].split(":") + Logger.info("Price: " + Variables) + let IDChecker = true; + for (let Target in handbook) { + if (handbook[Target].Id.includes(Variables[0])) { + handbook[Target].Price = Calculus(handbook[Target].Price, Variables[1], Variables[2]) + IDChecker = false; + break; + } + } + + if (IDChecker) { + Logger.warning("[SVM] INVENTORY AND ITEMS - Price ID - " + Variables[0] + " - This ID is not found in handbook.\nChecking as ParentID") + let childs = [] + for (let ID in items) { + if (items[ID]._parent == Variables[0]) { + childs.push(items[ID]._id) + } + } + if (childs.length > 0) { + Logger.success("[SVM] Success, Changing prices of Child IDs") + Logger.info(childs) + for (let child in childs) { + for (let ID in handbook) { + if (handbook[ID].Id.includes(childs[child])) { + handbook[ID].Price = Calculus(handbook[ID].Price, Variables[1], Variables[2]) + break; + } + } + } + } + else { + Logger.error("[SVM] Price ID Failed, this ID doesn't exist in Items.json") + } + } + } + } + } + Logger.success("[SVM] Custom properties successfully loaded") + } + catch (e) { + Logger.error("[SVM] INVENTORY AND ITEMS - Custom properties failed to load, error of the code:\n" + e) + } + } + } + //############## PLAYER SECTION ############### + if (Config.Player.EnablePlayer) { + //Skill box + globals.SkillsSettings.SkillProgressRate = Config.Player.SkillProgMult; + globals.SkillsSettings.WeaponSkillProgressRate = Config.Player.WeaponSkillMult; + //############## Health after raid status ############## + Health.healthMultipliers.death = Config.Player.DiedHealth.Health_death; + Health.healthMultipliers.blacked = Config.Player.DiedHealth.Health_blacked; + Health.save.health = Config.Player.DiedHealth.Savehealth; + Health.save.effects = Config.Player.DiedHealth.Saveeffects; + // skill eff box + if (Config.Player.EnableFatigue) { + globals.SkillMinEffectiveness = Config.Player.Skills.SkillMinEffect; + globals.SkillFatiguePerPoint = Config.Player.Skills.SkillFatiguePerPoint; + globals.SkillFreshEffectiveness = Config.Player.Skills.SkillFreshEffect; + globals.SkillFreshPoints = Config.Player.Skills.SkillFPoints; + globals.SkillPointsBeforeFatigue = Config.Player.Skills.SkillPointsBeforeFatigue; + globals.SkillFatigueReset = Config.Player.Skills.SkillFatigueReset; + } + //############## Player level XP box ############## + globals.exp.kill.victimBotLevelExp = Config.Player.CharXP.ScavKill; + globals.exp.kill.victimLevelExp = Config.Player.CharXP.PMCKill; + globals.exp.kill.botHeadShotMult = Config.Player.CharXP.ScavHMult; + globals.exp.kill.pmcHeadShotMult = Config.Player.CharXP.PMCHMult + //############## XP mults Box ############## + globals.exp.match_end.runnerMult = Config.Player.RaidMult.Runner + globals.exp.match_end.miaMult = Config.Player.RaidMult.MIA + globals.exp.match_end.survivedMult = Config.Player.RaidMult.Survived + globals.exp.match_end.killedMult = Config.Player.RaidMult.Killed + + //############## Stamina ############## + if (Config.Player.EnableStaminaLegs) { + globals.Stamina.Capacity = Config.Player.MaxStaminaLegs + globals.Stamina.BaseRestorationRate = Config.Player.RegenStaminaLegs + globals.Stamina.JumpConsumption = Config.Player.JumpConsumption + globals.Stamina.StandupConsumption.x = Config.Player.LayToStand + globals.Stamina.PoseLevelConsumptionPerNotch.x = Config.Player.CrouchToStand/10; + } + if (Config.Player.EnableStaminaHands) { + // globals.Stamina.AimDrainRate = Config.Player. + globals.Stamina.HandsCapacity = Config.Player.MaxStaminaHands + globals.Stamina.HandsRestoration = Config.Player.RegenStaminaHands + globals.Stamina.AimConsumptionByPose.x = Config.Player.LyingDown + globals.Stamina.AimConsumptionByPose.y = Config.Player.Crouching + globals.Stamina.AimConsumptionByPose.z = Config.Player.Standing + } + if (Config.Player.UnlimitedStamina) { + globals.Stamina.Capacity = 500; + globals.Stamina.BaseRestorationRate = 500; + globals.Stamina.StaminaExhaustionCausesJiggle = false; + globals.Stamina.StaminaExhaustionStartsBreathSound = false; + globals.Stamina.StaminaExhaustionRocksCamera = false; + globals.Stamina.SprintDrainRate = 0; + globals.Stamina.JumpConsumption = 0; + globals.Stamina.AimDrainRate = 0; + globals.Stamina.SitToStandConsumption = 0; + } + if (Config.Player.FallDamage) { + globals.Health.Falling.SafeHeight = 200 + globals.Health.Falling.DamagePerMeter = 0 + } + globals.Health.Effects.Existence.HydrationLoopTime = (globals.Health.Effects.Existence.HydrationLoopTime / Config.Player.HydrationLoss) + globals.Health.Effects.Existence.EnergyLoopTime = (globals.Health.Effects.Existence.EnergyLoopTime / Config.Player.EnergyLoss) + globals.Health.Effects.Existence.DestroyedStomachEnergyTimeFactor = Config.Player.BlackStomach; + globals.Health.Effects.Existence.DestroyedStomachHydrationTimeFactor = Config.Player.BlackStomach; + } + //############## HIDEOUT SECTION ############## + if (Config.Hideout.EnableHideout) { + //Change hideout fuel consumption + hideout.settings.generatorFuelFlowRate *= Config.Hideout.FuelConsumptionRate; + hideout.settings.generatorSpeedWithoutFuel *= Config.Hideout.NoFuelMult; + //hideoutC.fuelDrainRateMultipler = Config.Hideout.FuelConsumptionRate; + hideout.settings.airFilterUnitFlowRate *= Config.Hideout.AirFilterRate; + hideout.settings.gpuBoostRate *= Config.Hideout.GPUBoostRate; + HideoutConfig.cultistCircle.maxRewardItemCount = Config.Hideout.CultistMaxRewards + for (let time in HideoutConfig.cultistCircle.craftTimeThreshholds) { + HideoutConfig.cultistCircle.craftTimeThreshholds[time].craftTimeSeconds = parseInt(HideoutConfig.cultistCircle.craftTimeThreshholds[time].craftTimeSeconds * Config.Hideout.CultistTime) + } + for (let time in HideoutConfig.cultistCircle.directRewards) { + HideoutConfig.cultistCircle.directRewards[time].craftTimeSeconds = parseInt(HideoutConfig.cultistCircle.directRewards[time].craftTimeSeconds * Config.Hideout.CultistTime) + } + + if (Config.Hideout.EnableStash) { + items["566abbc34bdc2d92178b4576"]._props.Grids[0]._props.cellsV = Config.Hideout.Stash.StashLvl1 + items["5811ce572459770cba1a34ea"]._props.Grids[0]._props.cellsV = Config.Hideout.Stash.StashLvl2 + items["5811ce662459770f6f490f32"]._props.Grids[0]._props.cellsV = Config.Hideout.Stash.StashLvl3 + items["5811ce772459770e9e5f9532"]._props.Grids[0]._props.cellsV = Config.Hideout.Stash.StashLvl4 + items["6602bcf19cc643f44a04274b"]._props.Grids[0]._props.cellsV = Config.Hideout.Stash.StashTUE + } + //Enable hideout fast constructions + for (const data in hideout.areas) { + let areaData = hideout.areas[data] + for (const i in areaData.stages) { + if (areaData.stages[i].constructionTime > 0) { + areaData.stages[i].constructionTime = parseInt(areaData.stages[i].constructionTime * Config.Hideout.HideoutConstMult) + if (areaData.stages[i].constructionTime < 1) { + areaData.stages[i].constructionTime = 2 + } + } + } + } + //Enable fast hideout production + for (const data in hideout.production.recipes) { + let productionData = hideout.production.recipes[data]; + + if (productionData._id == "5d5589c1f934db045e6c5492") { + productionData.productionTime = Config.Hideout.WaterFilterTime * 60 + productionData.requirements[1].resource = Config.Hideout.WaterFilterRate + } + if (productionData._id == "5d5c205bd582a50d042a3c0e") { + productionData.productionLimitCount = Config.Hideout.MaxBitcoins; + productionData.productionTime = Config.Hideout.BitcoinTime * 60; + } + if (!productionData.continuous && productionData.productionTime >= 10) { + productionData.productionTime = parseInt(productionData.productionTime * Config.Hideout.HideoutProdMult) + if (productionData.productionTime < 1) { + productionData.productionTime = 2 + } + } + } + //Scav cases modifications + for (const scav in hideout.production.scavRecipes) { + let caseData = hideout.production.scavRecipes[scav]; + if (caseData.productionTime >= 10) { + caseData.productionTime = parseInt(caseData.productionTime * Config.Hideout.ScavCaseTime); + if (caseData.productionTime < 1) { + caseData.productionTime = 2 + } + } + } + for (const scase in hideout.production.scavRecipes) { + let caseData = hideout.production.scavRecipes[scase]; + if (caseData.requirements[0].templateId == "5449016a4bdc2d6f028b456f" || caseData.requirements[0].templateId == "5696686a4bdc2da3298b456a" || caseData.requirements[0].templateId == "569668774bdc2da2298b4568") { + caseData.requirements[0].count = parseInt(caseData.requirements[0].count * Config.Hideout.ScavCasePrice); + } + } + //Remove construction requirements + if (Config.Hideout.RemoveConstructionsRequirements || Config.Hideout.RemoveSkillRequirements || Config.Hideout.RemoveTraderLevelRequirements) { + for (const data in hideout.areas) { + let areaData = hideout.areas[data] + for (const stage in areaData.stages) { + if (areaData.stages[stage].requirements !== undefined && areaData.stages[stage].requirements.length > 0) { + let rewriter = []; + for (let req in areaData.stages[stage].requirements)//This is horrible + { + if (areaData.stages[stage].requirements[req].hasOwnProperty("templateId") && !Config.Hideout.RemoveConstructionsRequirements) { + rewriter.push(areaData.stages[stage].requirements[req]) + } + else if (areaData.stages[stage].requirements[req].hasOwnProperty("skillName") && !Config.Hideout.RemoveSkillRequirements) { + rewriter.push(areaData.stages[stage].requirements[req]) + } + else if (areaData.stages[stage].requirements[req].hasOwnProperty("traderId") && !Config.Hideout.RemoveTraderLevelRequirements) { + rewriter.push(areaData.stages[stage].requirements[req]) + } + else if (areaData.stages[stage].requirements[req].hasOwnProperty("areaType"))//Just for sanity check to avoid certain errors like building bitcoin farm while there is no generator. + { + rewriter.push(areaData.stages[stage].requirements[req]) + } + } + areaData.stages[stage].requirements = rewriter + } + } + } + } + //Hideout regen menu + for (let limb in globals.Health.Effects.Regeneration.BodyHealth) { + globals.Health.Effects.Regeneration.BodyHealth[limb].Value *= Config.Hideout.Regeneration.HealthRegen + } + globals.Health.Effects.Regeneration.Energy = Config.Hideout.Regeneration.EnergyRegen + globals.Health.Effects.Regeneration.Hydration = Config.Hideout.Regeneration.HydrationRegen + + for (const data in hideout.areas) { + let areaData = hideout.areas[data] + for (const i in areaData.stages) { + for (const x in areaData.stages[i].bonuses) { + if (Config.Hideout.Regeneration.HideoutHydration && areaData.stages[i].bonuses[x].type == "HydrationRegeneration") { + areaData.stages[i].bonuses[x].value = 0; + } + if (Config.Hideout.Regeneration.HideoutEnergy && areaData.stages[i].bonuses[x].type == "EnergyRegeneration") { + areaData.stages[i].bonuses[x].value = 0; + } + if (Config.Hideout.Regeneration.HideoutHealth && areaData.stages[i].bonuses[x].type == "HealthRegeneration") { + areaData.stages[i].bonuses[x].value = 0; + } + } + } + } + } + + //############## RAIDS SECTION ################ + if (Config.Raids.EnableRaids) { + //############## INRAID SECTION ################## + if (Config.Raids.RaidStartup.EnableRaidStartup) { + Inraid.raidMenuSettings.aiAmount = Arrays.AIAmount[Config.Raids.RaidStartup.AIAmount]; + Inraid.raidMenuSettings.aiDifficulty = Arrays.AIDifficulty[Config.Raids.RaidStartup.AIDifficulty]; + Inraid.raidMenuSettings.bossEnabled = Config.Raids.RaidStartup.EnableBosses; + Inraid.raidMenuSettings.scavWars = Config.Raids.RaidStartup.ScavWars; + Inraid.raidMenuSettings.taggedAndCursed = Config.Raids.RaidStartup.TaggedAndCursed; + Inraid.save.loot = Config.Raids.RaidStartup.SaveLoot; + } + if (Config.Raids.ForceSeason) { + WeatherValues.overrideSeason = Config.Raids.Season; + } + trader.fence.coopExtractGift.sendGift = !Config.Raids.Exfils.FenceGift; + const Midcore = configServer.getConfig("spt-lostondeath"); + if (Config.Raids.SaveQuestItems) { + Midcore.questItems = false; + } + //Low Ground zero level access + locations["sandbox"].base.RequiredPlayerLevelMax = Config.Raids.SandboxAccessLevel; + //Time acceleration + WeatherValues.acceleration = Config.Raids.Timeacceleration + //Deploy Window time + globals.TimeBeforeDeployLocal = Config.Raids.RaidStartup.TimeBeforeDeployLocal + //Always survived + if (Config.Raids.NoRunThrough) { + globals.exp.match_end.survived_exp_requirement = 0; + globals.exp.match_end.survived_seconds_requirement = 0; + } + DB.locations["laboratory"].base.Insurance = Config.Raids.LabInsurance; + //Remove labs entry keycard + if (Config.Raids.Removelabkey) { + locations["laboratory"].base.AccessKeys = [] + } + + if (Config.Raids.Exfils.ArmorExtract) { + globals.RequirementReferences.Alpinist.splice(2, 1) + } + if (Config.Raids.Exfils.GearExtract) { + globals.RequirementReferences.Alpinist.splice(0, 2) + } + //Remove extracts restrictions + for (let i in locations) { + if (i !== "base") { + let ExitNames = locations[i].base.exits // 3.10 TODO CHECK + for (let x in ExitNames) { + if (ExitNames !== "EXFIL_Train" && (!ExitNames.includes("lab") || ExitNames == "lab_Vent") && ExitNames !== "Saferoom Exfil") {//Ok, i feel dumb again, but i was in a rush ok? + + if (Config.Raids.Exfils.GearExtract && Config.Raids.Exfils.ArmorExtract && locations[i].base.exits[x].PassageRequirement == "Reference") { + FreeExit(locations[i].base.exits[x]) + } + if (Config.Raids.Exfils.NoBackpack && locations[i].base.exits[x].PassageRequirement == "Empty") { + FreeExit(locations[i].base.exits[x]) + } + if (locations[i].base.exits[x].PassageRequirement == "TransferItem" && Config.Raids.EnableCarCoop) { + locations[i].base.exits[x].ExfiltrationTime = Config.Raids.Exfils.CarExtractTime; + switch (i) { + case "woods": + if (Config.Raids.Exfils.CarWoods !== 0) { + locations[i].base.exits[x].Count = Config.Raids.Exfils.CarWoods; + } + else { + FreeExit(locations[i].base.exits[x]) + } + break; + case "interchange": + if (Config.Raids.Exfils.CarInterchange !== 0) { + locations[i].base.exits[x].Count = Config.Raids.Exfils.CarInterchange; + } + else { + FreeExit(locations[i].base.exits[x]) + } + break; + case "bigmap": + if (Config.Raids.Exfils.CarCustoms !== 0) { + locations[i].base.exits[x].Count = Config.Raids.Exfils.CarCustoms; + } + else { + FreeExit(locations[i].base.exits[x]) + } + break; + case "tarkovstreets": + if (Config.Raids.Exfils.CarStreets !== 0) { + locations[i].base.exits[x].Count = Config.Raids.Exfils.CarStreets; + } + else { + FreeExit(locations[i].base.exits[x]) + } + break; + case "lighthouse": + if (Config.Raids.Exfils.CarLighthouse !== 0) { + locations[i].base.exits[x].Count = Config.Raids.Exfils.CarLighthouse; + } + else { + FreeExit(locations[i].base.exits[x]) + } + break; + case "shoreline": + if (Config.Raids.Exfils.CarShoreline !== 0) { + locations[i].base.exits[x].Count = Config.Raids.Exfils.CarShoreline; + } + else { + FreeExit(locations[i].base.exits[x]) + } + break; + case "sandbox": + case "sandbox_high": + if (Config.Raids.Exfils.CarSandbox !== 0) { + locations[i].base.exits[x].Count = Config.Raids.Exfils.CarSandbox; + } + else { + FreeExit(locations[i].base.exits[x]) + } + break; + default: + break; + } + } + if (Config.Raids.Exfils.CoopPaid && Config.Raids.EnableCarCoop && locations[i].base.exits[x].PassageRequirement == "ScavCooperation") { + locations[i].base.exits[x].PassageRequirement = "TransferItem"; + locations[i].base.exits[x].ExfiltrationType = "SharedTimer"; + locations[i].base.exits[x].Id = "5449016a4bdc2d6f028b456f"; + locations[i].base.exits[x].PlayersCount = 0; + locations[i].base.exits[x].RequirementTip = "EXFIL_Item"; + switch (i) { + case "woods": + if (Config.Raids.Exfils.CoopPaidWoods !== 0) { + locations[i].base.exits[x].Count = Config.Raids.Exfils.CoopPaidWoods; + } + else { + FreeExit(locations[i].base.exits[x]) + } + break; + case "tarkovstreets": + if (Config.Raids.Exfils.CoopPaidStreets !== 0) { + locations[i].base.exits[x].Count = Config.Raids.Exfils.CoopPaidStreets; + } + else { + FreeExit(locations[i].base.exits[x]) + } + break; + case "interchange": + if (Config.Raids.Exfils.CoopPaidInterchange !== 0) { + locations[i].base.exits[x].Count = Config.Raids.Exfils.CoopPaidInterchange; + } + else { + FreeExit(locations[i].base.exits[x]) + } + break; + case "lighthouse": + if (Config.Raids.Exfils.CoopPaidLighthouse !== 0) { + locations[i].base.exits[x].Count = Config.Raids.Exfils.CoopPaidLighthouse; + } + else { + FreeExit(locations[i].base.exits[x]) + } + break; + case "rezervbase": + if (Config.Raids.Exfils.CoopPaidReserve !== 0) { + locations[i].base.exits[x].Count = Config.Raids.Exfils.CoopPaidReserve; + } + else { + FreeExit(locations[i].base.exits[x]) + } + break; + case "shoreline": + if (Config.Raids.Exfils.CoopPaidShoreline !== 0) { + locations[i].base.exits[x].Count = Config.Raids.Exfils.CoopPaidShoreline; + } + else { + FreeExit(locations[i].base.exits[x]) + } + break; + case "sandbox": + case "sandbox_high": + if (Config.Raids.Exfils.CoopPaidSandbox !== 0) { + locations[i].base.exits[x].Count = Config.Raids.Exfils.CoopPaidSandbox; + } + else { + FreeExit(locations[i].base.exits[x]) + } + break; + default: + break; + } + } + if (Config.Raids.Exfils.FreeCoop && Config.Raids.EnableCarCoop && locations[i].base.exits[x].PassageRequirement == "ScavCooperation") { + FreeExit(locations[i].base.exits[x]) + } + } + } + } + } + //Make all extractions available to extract + if (Config.Raids.Exfils.ChanceExtracts) { + for (let i in locations) { + if (i !== "base") { + for (let x in locations[i].base.exits) { + if (locations[i].base.exits[x].Name !== "EXFIL_Train") { + locations[i].base.exits[x].Chance = 100; + } + } + } + } + } + //Extend raids time + if (Config.Raids.RaidTime != 0) { + for (let map in locations) { + if (map !== "base") { + if (isJSONValueDefined(locations[map].base.exit_access_time)) { + locations[map].base.exit_access_time += Config.Raids.RaidTime + } + if (isJSONValueDefined(locations[map].base.EscapeTimeLimit)) { + locations[map].base.EscapeTimeLimit += Config.Raids.RaidTime + } + } + } + } + //Make all extractions of the map available regardless of the infill + if (Config.Raids.Exfils.ExtendedExtracts) { + for (let map in locations) { + switch (map) { + case "bigmap": + for (const extract in locations[map].base.exits) { + locations[map].base.exits[extract].EntryPoints = "Customs,Boiler Tanks" + } + break; + case "interchange": + for (const extract in locations[map].base.exits) { + locations[map].base.exits[extract].EntryPoints = "MallSE,MallNW" + } + break; + case "shoreline": + for (const extract in locations[map].base.exits) { + locations[map].base.exits[extract].EntryPoints = "Village,Riverside" + } + break; + case "woods": + for (const extract in locations[map].base.exits) { + locations[map].base.exits[extract].EntryPoints = "House,Old Station" + } + break; + case "lighthouse": + for (const extract in locations[map].base.exits) { + locations[map].base.exits[extract].EntryPoints = "Tunnel,North" + } + break; + case "tarkovstreets": + for (const extract in locations[map].base.exits) { + locations[map].base.exits[extract].EntryPoints = "E1_2,E6_1,E2_3,E3_4,E4_5,E5_6,E6_1" + } + break; + case "sandbox": + case "sandbox_high": + for (const extract in locations[map].base.exits) { + locations[map].base.exits[extract].EntryPoints = "west,east" + } + break; + default: + break; + } + } + } + //Removing that weird event ceasefire. + if (Config.Raids.RaidEvents.DisableHalloweenAIFriendly) { + for (let bottype in Events.hostilitySettingsForEvent.zombies.default) { + if (Events.hostilitySettingsForEvent.zombies.default[bottype].BotRole == "pmcBEAR") { + Events.hostilitySettingsForEvent.zombies.default[bottype].SavagePlayerBehaviour = "AlwaysEnemies" + for (let behavior in Events.hostilitySettingsForEvent.zombies.default[bottype]) { + if (Events.hostilitySettingsForEvent.zombies.default[bottype].Neutral[behavior] == "pmcUSEC") { + Events.hostilitySettingsForEvent.zombies.default[bottype].Neutral.splice(behavior, 1) + } + } + Events.hostilitySettingsForEvent.zombies.default[bottype].AlwaysEnemies.push("pmcUSEC") + } + else if (Events.hostilitySettingsForEvent.zombies.default[bottype].BotRole == "pmcUSEC") { + Events.hostilitySettingsForEvent.zombies.default[bottype].SavagePlayerBehaviour = "AlwaysEnemies" + for (let behavior in Events.hostilitySettingsForEvent.zombies.default[bottype]) { + if (Events.hostilitySettingsForEvent.zombies.default[bottype].Neutral[behavior] == "pmcBEAR") { + Events.hostilitySettingsForEvent.zombies.default[bottype].Neutral.splice(behavior, 1) + } + } + Events.hostilitySettingsForEvent.zombies.default[bottype].AlwaysEnemies.push("pmcBEAR") + } + else { + Events.hostilitySettingsForEvent.zombies.default[bottype].BearPlayerBehaviour = "AlwaysEnemies" + Events.hostilitySettingsForEvent.zombies.default[bottype].UsecPlayerBehaviour = "AlwaysEnemies" + } + } + } + Quest.showNonSeasonalEventQuests = Config.Raids.RaidEvents.NonSeasonalQuests + Events.events[0].settings.zombieSettings.enabled = !Config.Raids.RaidEvents.DisableZombies + + if (Config.Raids.RaidEvents.RandomInfectionLevel) { + Events.events[0].settings.zombieSettings.mapInfectionAmount = + { + "laboratory": 100, + "bigmap": Math.floor(Math.random() * 100) + 1, + "Woods": Math.floor(Math.random() * 100) + 1, + "Shoreline": Math.floor(Math.random() * 100) + 1, + "Sandbox": Math.floor(Math.random() * 100) + 1, + "RezervBase": Math.floor(Math.random() * 100) + 1, + "TarkovStreets": Math.floor(Math.random() * 100) + 1, + "factory4": Math.floor(Math.random() * 100) + 1, + "Lighthouse": Math.floor(Math.random() * 100) + 1, + "Interchange": Math.floor(Math.random() * 100) + 1 + } + //Hopefully a temporary fix + for (let map in Events.eventBossSpawns.halloweenzombies) { + for (let wave in Events.eventBossSpawns.halloweenzombies[map]) { + switch (map)//Feature - Infection level affects spawn chances. + { + case "factory4_day": + Events.eventBossSpawns.halloweenzombies[map][wave].BossChance = Events.events[0].settings.zombieSettings.mapInfectionAmount.factory4; + break; + case "factory4_night": + Events.eventBossSpawns.halloweenzombies[map][wave].BossChance = Events.events[0].settings.zombieSettings.mapInfectionAmount.factory4; + break; + case "sandbox": + Events.eventBossSpawns.halloweenzombies[map][wave].BossChance = Events.events[0].settings.zombieSettings.mapInfectionAmount.Sandbox; + break; + case "sandbox_high": + Events.eventBossSpawns.halloweenzombies[map][wave].BossChance = Events.events[0].settings.zombieSettings.mapInfectionAmount.Sandbox; + break; + default: + if (Events.events[0].settings.zombieSettings.mapInfectionAmount[map] !== undefined) { + Events.eventBossSpawns.halloweenzombies[map][wave].BossChance = Events.events[0].settings.zombieSettings.mapInfectionAmount[map]; + } + break; + } + } + } + } + Events.enableSeasonalEventDetection = !Config.Raids.RaidEvents.DisableEvents + if (Config.Raids.RaidEvents.RaidersEverywhere) // 3.9.0 Raider rework, need to split them up into 3 fields - Start of the raid Scavs, PMC and general waves. { - case "factory4_day": - Events.eventBossSpawns.halloweenzombies[map][wave].BossChance = Events.events[0].settings.zombieSettings.mapInfectionAmount.factory4; - break; - case "factory4_night": - Events.eventBossSpawns.halloweenzombies[map][wave].BossChance = Events.events[0].settings.zombieSettings.mapInfectionAmount.factory4; - break; - case "sandbox": - Events.eventBossSpawns.halloweenzombies[map][wave].BossChance = Events.events[0].settings.zombieSettings.mapInfectionAmount.Sandbox; - break; - case "sandbox_high": - Events.eventBossSpawns.halloweenzombies[map][wave].BossChance = Events.events[0].settings.zombieSettings.mapInfectionAmount.Sandbox; - break; - default: - if (Events.events[0].settings.zombieSettings.mapInfectionAmount[map] !== undefined){ - Events.eventBossSpawns.halloweenzombies[map][wave].BossChance = Events.events[0].settings.zombieSettings.mapInfectionAmount[map]; + for (let i in locations)//Locations DB + { + if (i !== "base" && locations[i].base.waves) { + for (let x in locations[i].base.waves) { + locations[i].base.waves[x].WildSpawnType = "pmcBot" + } + } + } + for (let loc in locs.customWaves.boss) { + for (let ai in locs.customWaves.boss[loc]) { + locs.customWaves.boss[loc][ai].BossName = "pmcBot"; + locs.customWaves.boss[loc][ai].BossEscortType = "pmcBot"; + } + } + for (let loc in locs.customWaves.normal) { + for (let ai in locs.customWaves.normal[loc]) { + locs.customWaves.normal[loc][ai].WildSpawnType = "pmcBot" + } } - break; } - } - } - } - Events.enableSeasonalEventDetection = !Config.Raids.RaidEvents.DisableEvents - if (Config.Raids.RaidEvents.RaidersEverywhere) // 3.9.0 Raider rework, need to split them up into 3 fields - Start of the raid Scavs, PMC and general waves. - { - for (let i in locations)//Locations DB - { - if (i !== "base" && locations[i].base.waves) { - for (let x in locations[i].base.waves) { - locations[i].base.waves[x].WildSpawnType = "pmcBot" + if (Config.Raids.RaidEvents.KillaFactory) { + const KillaWave = CreateBoss("bossKilla", Config.Raids.RaidEvents.KillaFactoryChance, "followerBully", 0, locations["factory4_day"].base.OpenZones) + locations["factory4_day"].base.BossLocationSpawn.push(KillaWave) + locations["factory4_night"].base.BossLocationSpawn.push(KillaWave) } - } - } - for (let loc in locs.customWaves.boss) { - for (let ai in locs.customWaves.boss[loc]) { - locs.customWaves.boss[loc][ai].BossName = "pmcBot"; - locs.customWaves.boss[loc][ai].BossEscortType = "pmcBot"; - } - } - for (let loc in locs.customWaves.normal) { - for (let ai in locs.customWaves.normal[loc]) { - locs.customWaves.normal[loc][ai].WildSpawnType = "pmcBot" - } - } - } - if (Config.Raids.RaidEvents.KillaFactory) { - const KillaWave = CreateBoss("bossKilla", Config.Raids.RaidEvents.KillaFactoryChance, "followerBully", 0, locations["factory4_day"].base.OpenZones) - locations["factory4_day"].base.BossLocationSpawn.push(KillaWave) - locations["factory4_night"].base.BossLocationSpawn.push(KillaWave) - } - if (Config.Raids.RaidEvents.TagillaInterchange) { - for (let bosscheck in locations["interchange"].base.BossLocationSpawn)//Looking for exactly Killa wave, even tho he is the only boss here, safety measure - { - if (locations["interchange"].base.BossLocationSpawn[bosscheck].BossName == "bossKilla") { - locations["interchange"].base.BossLocationSpawn[bosscheck].BossEscortAmount = 1 - locations["interchange"].base.BossLocationSpawn[bosscheck].BossEscortType = "bossTagilla" - } - } - } - const Waves = require('../src/Waves.json'); - if (Config.Raids.RaidEvents.BossesOnReserve) { - let BossWave = CreateBoss("bossKilla", 100, "followerBully", "0", locations["rezervbase"].base.OpenZones) - locations["rezervbase"].base.BossLocationSpawn.push(BossWave) - BossWave = CreateBoss("bossBully", 100, "followerBully", "4", locations["rezervbase"].base.OpenZones) - locations["rezervbase"].base.BossLocationSpawn.push(BossWave) - BossWave = CreateBoss("bossKojaniy", 100, "followerKojaniy", "2", locations["rezervbase"].base.OpenZones) - locations["rezervbase"].base.BossLocationSpawn.push(BossWave) - BossWave = CreateBoss("bossSanitar", 100, "followerSanitar", "2", locations["rezervbase"].base.OpenZones) - locations["rezervbase"].base.BossLocationSpawn.push(BossWave) - BossWave = CreateBoss("bossTagilla", 100, "followerBully", "0", locations["rezervbase"].base.OpenZones) - locations["rezervbase"].base.BossLocationSpawn.push(BossWave) - if (Config.Raids.RaidEvents.IncludeStreetBosses) { - const Kaban = Waves.Kaban - Kaban.BossZone = locations["rezervbase"].base.OpenZones - locations["rezervbase"].base.BossLocationSpawn.push(Kaban) - const Kolontay = Waves.Kolontay - Kaban.BossZone = locations["rezervbase"].base.OpenZones - locations["rezervbase"].base.BossLocationSpawn.push(Kolontay) - } - } - if (Config.Raids.RaidEvents.BossesOnHealthResort) { - if (Config.Raids.RaidEvents.HealthResortIncludeGuards) { - let BossWave = CreateBoss("bossKilla", 100, "followerBully", 0, "ZoneSanatorium1,ZoneSanatorium2") - locations["shoreline"].base.BossLocationSpawn.push(BossWave) - BossWave = CreateBoss("bossBully", 100, "followerBully", 4, "ZoneSanatorium1,ZoneSanatorium2") - locations["shoreline"].base.BossLocationSpawn.push(BossWave) - BossWave = CreateBoss("bossKojaniy", 100, "followerKojaniy", 2, "ZoneSanatorium1,ZoneSanatorium2") - locations["shoreline"].base.BossLocationSpawn.push(BossWave) - BossWave = CreateBoss("bossSanitar", 100, "followerSanitar", 2, "ZoneSanatorium1,ZoneSanatorium2") - locations["shoreline"].base.BossLocationSpawn.push(BossWave) - BossWave = CreateBoss("bossTagilla", 100, "followerBully", 0, "ZoneSanatorium1,ZoneSanatorium2") - locations["shoreline"].base.BossLocationSpawn.push(BossWave) - const Goons = Waves.Goons - Goons.BossZone = "ZoneSanatorium1,ZoneSanatorium2" - locations["shoreline"].base.BossLocationSpawn.push(Goons) - const Glukhar = Waves.Glukhar - Glukhar.BossZone = "ZoneSanatorium1,ZoneSanatorium2" - locations["shoreline"].base.BossLocationSpawn.push(Glukhar) - const Kaban = Waves.Kaban - Kaban.BossZone = "ZoneSanatorium1,ZoneSanatorium2" - locations["shoreline"].base.BossLocationSpawn.push(Kaban) - const Kolontay = Waves.Kolontay - Kolontay.BossZone = "ZoneSanatorium1,ZoneSanatorium2" - locations["shoreline"].base.BossLocationSpawn.push(Kolontay)//can be shorted harder, will leave it for the next time. - } - else { - let BossWave = CreateBoss("bossKilla", 100, "followerBully", 0, "ZoneSanatorium1,ZoneSanatorium2") - locations["shoreline"].base.BossLocationSpawn.push(BossWave) - BossWave = CreateBoss("bossBully", 100, "followerBully", 0, "ZoneSanatorium1,ZoneSanatorium2") - locations["shoreline"].base.BossLocationSpawn.push(BossWave) - BossWave = CreateBoss("bossKojaniy", 100, "followerKojaniy", 0, "ZoneSanatorium1,ZoneSanatorium2") - locations["shoreline"].base.BossLocationSpawn.push(BossWave) - BossWave = CreateBoss("bossSanitar", 100, "followerSanitar", 0, "ZoneSanatorium1,ZoneSanatorium2") - locations["shoreline"].base.BossLocationSpawn.push(BossWave) - BossWave = CreateBoss("bossTagilla", 100, "followerBully", 0, "ZoneSanatorium1,ZoneSanatorium2") - locations["shoreline"].base.BossLocationSpawn.push(BossWave) - BossWave = CreateBoss("bossGluhar", 100, "followerBully", 0, "ZoneSanatorium1,ZoneSanatorium2") - locations["shoreline"].base.BossLocationSpawn.push(BossWave) - BossWave = CreateBoss("bossBoar", 100, "followerKojaniy", 0, "ZoneSanatorium1,ZoneSanatorium2") - locations["shoreline"].base.BossLocationSpawn.push(BossWave) - BossWave = CreateBoss("bossKolontay", 100, "followerSanitar", 0, "ZoneSanatorium1,ZoneSanatorium2") - locations["shoreline"].base.BossLocationSpawn.push(BossWave) - const Goons = Waves.Goons - Goons.BossZone = "ZoneSanatorium1,ZoneSanatorium2" - locations["shoreline"].base.BossLocationSpawn.push(Goons) - } - } - if (Config.Raids.RaidEvents.BossesOnCustoms) { - for (let bosses in locations["bigmap"].base.BossLocationSpawn) { - if (locations["bigmap"].base.BossLocationSpawn[bosses].BossName == "bossBully") { - locations["bigmap"].base.BossLocationSpawn[bosses].BossChance = 100; - } - } - let BossWave = CreateBoss("bossKilla", 100, "followerBully", 0, "ZoneOldAZS") - locations["bigmap"].base.BossLocationSpawn.push(BossWave) - BossWave = CreateBoss("bossKojaniy", 100, "followerKojaniy", 2, "ZoneFactoryCenter") - locations["bigmap"].base.BossLocationSpawn.push(BossWave) - BossWave = CreateBoss("bossSanitar", 100, "followerSanitar", 2, "ZoneGasStation") - locations["bigmap"].base.BossLocationSpawn.push(BossWave) - BossWave = CreateBoss("bossTagilla", 100, "followerBully", 0, "ZoneOldAZS") - locations["bigmap"].base.BossLocationSpawn.push(BossWave) - const Glukhar = Waves.Glukhar - Glukhar.BossZone = "ZoneScavBase" - locations["bigmap"].base.BossLocationSpawn.push(Glukhar) - } - if (Config.Raids.RaidEvents.GoonsFactory) { - const Goons = Waves.Goons; - Goons.BossZone = "BotZone"; - Goons.BossChance = Config.Raids.RaidEvents.GoonsFactoryChance; - locations["factory4_day"].base.BossLocationSpawn.push(Goons) - locations["factory4_night"].base.BossLocationSpawn.push(Goons) - } - if (Config.Raids.RaidEvents.GlukharLabs) {//BossZone": "BotZoneFloor1,BotZoneFloor2", // "BossChance": 43, - const Glukhar = Waves.Glukhar - Glukhar.BossZone = "BotZoneFloor1,BotZoneFloor2" - locations["laboratory"].base.BossLocationSpawn.push(Glukhar) - } - for (let i in locations)//Bloodhounds events spawn chance - this is bad solution, but i made it on a quick hand, not sure this event lasts either. - { - if (i !== "base" && locations[i].base.BossLocationSpawn) { - for (let x in locations[i].base.BossLocationSpawn) { - if (locations[i].base.BossLocationSpawn[x].BossName == "arenaFighterEvent" && i == "bigmap") { - locations[i].base.BossLocationSpawn[x].BossChance = Config.Raids.RaidEvents.HoundsCustoms + + if (Config.Raids.RaidEvents.TagillaInterchange) { + for (let bosscheck in locations["interchange"].base.BossLocationSpawn)//Looking for exactly Killa wave, even tho he is the only boss here, safety measure + { + if (locations["interchange"].base.BossLocationSpawn[bosscheck].BossName == "bossKilla") { + locations["interchange"].base.BossLocationSpawn[bosscheck].BossEscortAmount = 1 + locations["interchange"].base.BossLocationSpawn[bosscheck].BossEscortType = "bossTagilla" + } + } } - if (locations[i].base.BossLocationSpawn[x].BossName == "arenaFighterEvent" && i == "woods") { - locations[i].base.BossLocationSpawn[x].BossChance = Config.Raids.RaidEvents.HoundsWoods + const Waves = require('../src/Waves.json'); + if (Config.Raids.RaidEvents.BossesOnReserve) { + let BossWave = CreateBoss("bossKilla", 100, "followerBully", "0", locations["rezervbase"].base.OpenZones) + locations["rezervbase"].base.BossLocationSpawn.push(BossWave) + BossWave = CreateBoss("bossBully", 100, "followerBully", "4", locations["rezervbase"].base.OpenZones) + locations["rezervbase"].base.BossLocationSpawn.push(BossWave) + BossWave = CreateBoss("bossKojaniy", 100, "followerKojaniy", "2", locations["rezervbase"].base.OpenZones) + locations["rezervbase"].base.BossLocationSpawn.push(BossWave) + BossWave = CreateBoss("bossSanitar", 100, "followerSanitar", "2", locations["rezervbase"].base.OpenZones) + locations["rezervbase"].base.BossLocationSpawn.push(BossWave) + BossWave = CreateBoss("bossTagilla", 100, "followerBully", "0", locations["rezervbase"].base.OpenZones) + locations["rezervbase"].base.BossLocationSpawn.push(BossWave) + if (Config.Raids.RaidEvents.IncludeStreetBosses) { + const Kaban = Waves.Kaban + Kaban.BossZone = locations["rezervbase"].base.OpenZones + locations["rezervbase"].base.BossLocationSpawn.push(Kaban) + const Kolontay = Waves.Kolontay + Kaban.BossZone = locations["rezervbase"].base.OpenZones + locations["rezervbase"].base.BossLocationSpawn.push(Kolontay) + } } - if (locations[i].base.BossLocationSpawn[x].BossName == "peacemaker" && i == "shoreline") { - locations[i].base.BossLocationSpawn[x].BossChance = Config.Raids.RaidEvents.PeaceFighters + if (Config.Raids.RaidEvents.BossesOnHealthResort) { + if (Config.Raids.RaidEvents.HealthResortIncludeGuards) { + let BossWave = CreateBoss("bossKilla", 100, "followerBully", 0, "ZoneSanatorium1,ZoneSanatorium2") + locations["shoreline"].base.BossLocationSpawn.push(BossWave) + BossWave = CreateBoss("bossBully", 100, "followerBully", 4, "ZoneSanatorium1,ZoneSanatorium2") + locations["shoreline"].base.BossLocationSpawn.push(BossWave) + BossWave = CreateBoss("bossKojaniy", 100, "followerKojaniy", 2, "ZoneSanatorium1,ZoneSanatorium2") + locations["shoreline"].base.BossLocationSpawn.push(BossWave) + BossWave = CreateBoss("bossSanitar", 100, "followerSanitar", 2, "ZoneSanatorium1,ZoneSanatorium2") + locations["shoreline"].base.BossLocationSpawn.push(BossWave) + BossWave = CreateBoss("bossTagilla", 100, "followerBully", 0, "ZoneSanatorium1,ZoneSanatorium2") + locations["shoreline"].base.BossLocationSpawn.push(BossWave) + const Goons = Waves.Goons + Goons.BossZone = "ZoneSanatorium1,ZoneSanatorium2" + locations["shoreline"].base.BossLocationSpawn.push(Goons) + const Glukhar = Waves.Glukhar + Glukhar.BossZone = "ZoneSanatorium1,ZoneSanatorium2" + locations["shoreline"].base.BossLocationSpawn.push(Glukhar) + const Kaban = Waves.Kaban + Kaban.BossZone = "ZoneSanatorium1,ZoneSanatorium2" + locations["shoreline"].base.BossLocationSpawn.push(Kaban) + const Kolontay = Waves.Kolontay + Kolontay.BossZone = "ZoneSanatorium1,ZoneSanatorium2" + locations["shoreline"].base.BossLocationSpawn.push(Kolontay)//can be shorted harder, will leave it for the next time. + } + else { + let BossWave = CreateBoss("bossKilla", 100, "followerBully", 0, "ZoneSanatorium1,ZoneSanatorium2") + locations["shoreline"].base.BossLocationSpawn.push(BossWave) + BossWave = CreateBoss("bossBully", 100, "followerBully", 0, "ZoneSanatorium1,ZoneSanatorium2") + locations["shoreline"].base.BossLocationSpawn.push(BossWave) + BossWave = CreateBoss("bossKojaniy", 100, "followerKojaniy", 0, "ZoneSanatorium1,ZoneSanatorium2") + locations["shoreline"].base.BossLocationSpawn.push(BossWave) + BossWave = CreateBoss("bossSanitar", 100, "followerSanitar", 0, "ZoneSanatorium1,ZoneSanatorium2") + locations["shoreline"].base.BossLocationSpawn.push(BossWave) + BossWave = CreateBoss("bossTagilla", 100, "followerBully", 0, "ZoneSanatorium1,ZoneSanatorium2") + locations["shoreline"].base.BossLocationSpawn.push(BossWave) + BossWave = CreateBoss("bossGluhar", 100, "followerBully", 0, "ZoneSanatorium1,ZoneSanatorium2") + locations["shoreline"].base.BossLocationSpawn.push(BossWave) + BossWave = CreateBoss("bossBoar", 100, "followerKojaniy", 0, "ZoneSanatorium1,ZoneSanatorium2") + locations["shoreline"].base.BossLocationSpawn.push(BossWave) + BossWave = CreateBoss("bossKolontay", 100, "followerSanitar", 0, "ZoneSanatorium1,ZoneSanatorium2") + locations["shoreline"].base.BossLocationSpawn.push(BossWave) + const Goons = Waves.Goons + Goons.BossZone = "ZoneSanatorium1,ZoneSanatorium2" + locations["shoreline"].base.BossLocationSpawn.push(Goons) + } } - if (locations[i].base.BossLocationSpawn[x].BossName == "skier" && i == "bigmap") { - locations[i].base.BossLocationSpawn[x].BossChance = Config.Raids.RaidEvents.SkierFighters + if (Config.Raids.RaidEvents.BossesOnCustoms) { + for (let bosses in locations["bigmap"].base.BossLocationSpawn) { + if (locations["bigmap"].base.BossLocationSpawn[bosses].BossName == "bossBully") { + locations["bigmap"].base.BossLocationSpawn[bosses].BossChance = 100; + } + } + let BossWave = CreateBoss("bossKilla", 100, "followerBully", 0, "ZoneOldAZS") + locations["bigmap"].base.BossLocationSpawn.push(BossWave) + BossWave = CreateBoss("bossKojaniy", 100, "followerKojaniy", 2, "ZoneFactoryCenter") + locations["bigmap"].base.BossLocationSpawn.push(BossWave) + BossWave = CreateBoss("bossSanitar", 100, "followerSanitar", 2, "ZoneGasStation") + locations["bigmap"].base.BossLocationSpawn.push(BossWave) + BossWave = CreateBoss("bossTagilla", 100, "followerBully", 0, "ZoneOldAZS") + locations["bigmap"].base.BossLocationSpawn.push(BossWave) + const Glukhar = Waves.Glukhar + Glukhar.BossZone = "ZoneScavBase" + locations["bigmap"].base.BossLocationSpawn.push(Glukhar) } - } - } - } - //#######BTR STUFF - if (Config.Raids.EnableBTR) { - if (Config.Raids.ForceBTRFriendly) { - for (let levels in globals.FenceSettings.Levels) { - globals.FenceSettings.Levels[levels].CanInteractWithBtr = true; - } - } - if (Config.Raids.ForceBTRStash) { - for (let levels in globals.FenceSettings.Levels) { - globals.FenceSettings.Levels[levels].DeliveryGridSize["x"] = Config.Raids.BTRWidth - globals.FenceSettings.Levels[levels].DeliveryGridSize["y"] = Config.Raids.BTRHeight - } - } - globals.BTRSettings.BasePriceTaxi = Config.Raids.BTRTaxiPrice - globals.BTRSettings.CleanUpPrice = Config.Raids.BTRCoverPrice - globals.BTRSettings.BearPriceMod = Config.Raids.BearMults - globals.BTRSettings.UsecPriceMod = Config.Raids.UsecMult - globals.BTRSettings.ScavPriceMod = Config.Raids.ScavMult - } - } - //############## TRADERS SECTION ############## - if (Config.Traders.EnableTraders) { - if (Config.Traders.Fence.EnableFence) { - trader.fence.assortSize = Config.Traders.Fence.AmountOnSale; - trader.fence.discountOptions.assortSize = Config.Traders.Fence.PremiumAmountOnSale; - trader.fence.weaponPresetMinMax.min = Config.Traders.Fence.PresetCount; - trader.fence.weaponPresetMinMax.max = Config.Traders.Fence.PresetCount; - trader.fence.presetPriceMult = Config.Traders.Fence.PresetMult; - trader.fence.itemPriceMult = Config.Traders.Fence.PriceMult; - for (let stock in trader.updateTime)//useless cycle for now, will remove later. - { - if (trader.updateTime[stock]._name == "fence" && trader.updateTime[stock].seconds.min != undefined) { - trader.updateTime[stock].seconds.min = Config.Traders.Fence.StockTime_Min * 60; - trader.updateTime[stock].seconds.max = Config.Traders.Fence.StockTime_Max * 60; - } - } - trader.fence.weaponDurabilityPercentMinMax.current.min = Config.Traders.Fence.GunDurability_Min - trader.fence.weaponDurabilityPercentMinMax.current.max = Config.Traders.Fence.GunDurability_Max - trader.fence.armorMaxDurabilityPercentMinMax.current.min = Config.Traders.Fence.ArmorDurability_Min - trader.fence.armorMaxDurabilityPercentMinMax.current.max = Config.Traders.Fence.ArmorDurability_Max - let BlacklistArray = Config.Traders.Fence.Blacklist.split("\r\n"); - BlackItems.blacklist.push(BlacklistArray); - } - globals.TradingSettings.BuyoutRestrictions.MinDurability = Config.Traders.MinDurabSell / 100 - Quest.redeemTime = Config.Traders.QuestRedeemTime; - trader.purchasesAreFoundInRaid = Config.Traders.FIRTrade; - traders["5c0647fdd443bc2504c2d371"].base.unlockedByDefault = Config.Traders.UnlockJaeger - traders["6617beeaa9cfa777ca915b7c"].base.unlockedByDefault = Config.Traders.UnlockRef - const Mark = Config.Traders.TraderMarkup; - const MarkArray = [Mark.Prapor, - Mark.Therapist, - Mark.Fence, - Mark.Skier, - Mark.Peacekeeper, - Mark.Mechanic, - Mark.Ragman, - Mark.Jaeger - ] - let i = 0; - for (let CurTrader in traders) {//Bad solution to avoid modded traders. - if (CurTrader !== "ragfair" && (CurTrader == "5a7c2eca46aef81a7ca2145d" || CurTrader == "5ac3b934156ae10c4430e83c" || - CurTrader == "5c0647fdd443bc2504c2d371" || CurTrader == "54cb50c76803fa8b248b4571" || CurTrader == "54cb57776803fa99248b456e" || - CurTrader == "579dc571d53a0658a154fbec" || CurTrader == "5935c25fb3acc3127c3d8cd9" || CurTrader == "58330581ace78e27b8b10cee")) { - for (let level in traders[CurTrader].base.loyaltyLevels) { - traders[CurTrader].base.loyaltyLevels[level].buy_price_coef = 100 - MarkArray[i] - } - i++ - } - } - //Enable all the quests - if (Config.Traders.AllQuestsAvailable) { - for (let id in Quests) { - let QuestData = Quests[id] - QuestData.conditions.AvailableForStart = [ + if (Config.Raids.RaidEvents.CultistBosses) { + const Cultists = Waves.Cultists; + Cultists.BossChance = Config.Raids.RaidEvents.CultistBossesChance + Cultists.OpenZones = locations["bigmap"].base.OpenZones + locations["bigmap"].base.BossLocationSpawn.push(Cultists) + Cultists.OpenZones = locations["shoreline"].base.OpenZones + locations["shoreline"].base.BossLocationSpawn.push(Cultists) + Cultists.OpenZones = locations["woods"].base.OpenZones + locations["woods"].base.BossLocationSpawn.push(Cultists) + Cultists.OpenZones = locations["lighthouse"].base.OpenZones + locations["lighthouse"].base.BossLocationSpawn.push(Cultists) + } + if (Config.Raids.RaidEvents.GoonsFactory) { + const Goons = Waves.Goons; + Goons.BossZone = "BotZone"; + Goons.BossChance = Config.Raids.RaidEvents.GoonsFactoryChance; + locations["factory4_day"].base.BossLocationSpawn.push(Goons) + locations["factory4_night"].base.BossLocationSpawn.push(Goons) + } + if (Config.Raids.RaidEvents.GlukharLabs) {//BossZone": "BotZoneFloor1,BotZoneFloor2", // "BossChance": 43, + const Glukhar = Waves.Glukhar + Glukhar.BossZone = "BotZoneFloor1,BotZoneFloor2" + locations["laboratory"].base.BossLocationSpawn.push(Glukhar) + } + for (let i in locations)//Bloodhounds events spawn chance - this is bad solution, but i made it on a quick hand, not sure this event lasts either. { - "_parent": "Level", - "_props": - { - "compareMethod": ">=", - "value": "1", - "index": 0, - "parentId": "", - "id": "683a4e6b255f7527fb05a0f6" - } - }] - } - } - if (Config.Traders.FIRRestrictsQuests) { - for (const id in Quests) { - let condition = Quests[id].conditions.AvailableForFinish - for (const requirements in condition) { - if (condition[requirements].onlyFoundInRaid !== undefined) { - condition[requirements].onlyFoundInRaid = false; - } - } - } - } - if (Config.Traders.RemoveTimeCondition) { - for (const id in Quests) { - let condition = Quests[id].conditions.AvailableForStart - for (const requirements in condition) { - if (condition[requirements].availableAfter !== undefined) { - condition[requirements].availableAfter = 0; - } - } - } - } - //Enable all traders 4 stars - if (Config.Traders.TradersLvl4) { - for (let traderID in traders) { - let loyaltyLevels = traders[traderID].base.loyaltyLevels; - for (let level in loyaltyLevels) { - loyaltyLevels[level].minLevel = 1 - loyaltyLevels[level].minSalesSum = 0 - loyaltyLevels[level].minStanding = 0 - } - } - } - if (Config.Traders.UnlockQuestAssort) { - for (let AssortR in traders) { - if (AssortR !== "ragfair" && AssortR !== "638f541a29ffd1183d187f57" && traders[AssortR].questassort.success !== undefined) { - traders[AssortR].questassort.success = {} - } - } - } - if (Config.Traders.RemoveTradeLimits) { - for (let AssortR in traders) { - if (AssortR !== "ragfair" && AssortR !== "638f541a29ffd1183d187f57") { - for (let level in traders[AssortR].assort.items) { - if (traders[AssortR].assort.items[level].upd !== undefined && traders[AssortR].assort.items[level].upd["BuyRestrictionMax"] !== undefined) { - traders[AssortR].assort.items[level].upd["BuyRestrictionMax"] = 999999; - } - } - } - } - } - if (Config.Traders.IncreaseAssort) { - for (let AssortR in traders) { - if (AssortR !== "ragfair" && AssortR !== "638f541a29ffd1183d187f57") { - for (let level in traders[AssortR].assort.items) { - if (traders[AssortR].assort.items[level].upd !== undefined && traders[AssortR].assort.items[level].upd["StackObjectsCount"] !== undefined) { - traders[AssortR].assort.items[level].upd["StackObjectsCount"] = 1337420; - } - } - } - } - } - //sell assort - const Sell = Config.Traders.TraderSell; - const SellArray = [Sell.Prapor, - Sell.Therapist, - Sell.Skier, - Sell.Peacekeeper, - Sell.Mechanic, - Sell.Ragman, - Sell.Jaeger - ] - let p = 0; - for (let CurTrader in Arrays.traderArray) { - for (let assortment in traders[Arrays.traderArray[CurTrader]].assort.barter_scheme) { - if (traders[Arrays.traderArray[CurTrader]].assort.barter_scheme[assortment][0][0]._tpl == "5449016a4bdc2d6f028b456f" || - traders[Arrays.traderArray[CurTrader]].assort.barter_scheme[assortment][0][0]._tpl == "569668774bdc2da2298b4568" || - traders[Arrays.traderArray[CurTrader]].assort.barter_scheme[assortment][0][0]._tpl == "5696686a4bdc2da3298b456a") { - let TempValue = (traders[Arrays.traderArray[CurTrader]].assort.barter_scheme[assortment][0][0].count * SellArray[p]).toFixed(2)//testing - traders[Arrays.traderArray[CurTrader]].assort.barter_scheme[assortment][0][0].count = parseFloat(TempValue) - } - } - p++; - } - if (Config.Traders.RemoveCurrencyOffers) { - for (let CurTrader in traders) { - if (CurTrader !== "ragfair" && CurTrader !== "638f541a29ffd1183d187f57" && CurTrader !== "579dc571d53a0658a154fbec") //avoid ragfair, lighthouse trader and fence - { - for (let assortment in traders[CurTrader].assort.barter_scheme) { - if (traders[CurTrader].assort.barter_scheme[assortment][0][0]._tpl == "5449016a4bdc2d6f028b456f" || - traders[CurTrader].assort.barter_scheme[assortment][0][0]._tpl == "569668774bdc2da2298b4568" || - traders[CurTrader].assort.barter_scheme[assortment][0][0]._tpl == "5696686a4bdc2da3298b456a") { - for (let DeletElem in traders[CurTrader].assort.items) {//3.10 rework instead of deleting assort - set everything to 0 instead. - if (traders[CurTrader].assort.items[DeletElem]._id == assortment) { - if (traders[CurTrader].assort.items[DeletElem].upd.UnlimitedCount !== undefined) { - traders[CurTrader].assort.items[DeletElem].upd.UnlimitedCount = false; + if (i !== "base" && locations[i].base.BossLocationSpawn) { + for (let x in locations[i].base.BossLocationSpawn) { + if (locations[i].base.BossLocationSpawn[x].BossName == "arenaFighterEvent" && i == "bigmap") { + locations[i].base.BossLocationSpawn[x].BossChance = Config.Raids.RaidEvents.HoundsCustoms + } + if (locations[i].base.BossLocationSpawn[x].BossName == "arenaFighterEvent" && i == "woods") { + locations[i].base.BossLocationSpawn[x].BossChance = Config.Raids.RaidEvents.HoundsWoods + } + if (locations[i].base.BossLocationSpawn[x].BossName == "peacemaker" && i == "shoreline") { + locations[i].base.BossLocationSpawn[x].BossChance = Config.Raids.RaidEvents.PeaceFighters + } + if (locations[i].base.BossLocationSpawn[x].BossName == "skier" && i == "bigmap") { + locations[i].base.BossLocationSpawn[x].BossChance = Config.Raids.RaidEvents.SkierFighters + } } - traders[CurTrader].assort.items[DeletElem].upd["StackObjectsCount"] = 0; - } } - } } - } - } - } - - if (Config.Traders.RemoveBarterOffers) { - for (let CurTrader in traders) { - if (CurTrader !== "ragfair" && CurTrader !== "638f541a29ffd1183d187f57" && CurTrader !== "579dc571d53a0658a154fbec") { - for (let assortment in traders[CurTrader].assort.barter_scheme) { - if (traders[CurTrader].assort.barter_scheme[assortment][0][0]._tpl !== "5449016a4bdc2d6f028b456f" && - traders[CurTrader].assort.barter_scheme[assortment][0][0]._tpl !== "569668774bdc2da2298b4568" && - traders[CurTrader].assort.barter_scheme[assortment][0][0]._tpl !== "5696686a4bdc2da3298b456a") { - for (let DeletElem in traders[CurTrader].assort.items) { - if (traders[CurTrader].assort.items[DeletElem]._id == assortment) { - if (traders[CurTrader].assort.items[DeletElem].upd.UnlimitedCount !== undefined) { - traders[CurTrader].assort.items[DeletElem].upd.UnlimitedCount = false; + if (Config.Raids.ForceTransitStash) { + for (let levels in globals.FenceSettings.Levels) { + globals.FenceSettings.Levels[levels].TransitGridSize["x"] = Config.Raids.TransitWidth + globals.FenceSettings.Levels[levels].TransitGridSize["y"] = Config.Raids.TransitHeight + } + } + //############## BTR STUFF + if (Config.Raids.EnableBTR) { + if (Config.Raids.ForceBTRFriendly) { + for (let levels in globals.FenceSettings.Levels) { + globals.FenceSettings.Levels[levels].CanInteractWithBtr = true; } - traders[CurTrader].assort.items[DeletElem].upd["StackObjectsCount"] = 0; - } } - } + if (Config.Raids.ForceBTRStash) { + for (let levels in globals.FenceSettings.Levels) { + globals.FenceSettings.Levels[levels].DeliveryGridSize["x"] = Config.Raids.BTRWidth + globals.FenceSettings.Levels[levels].DeliveryGridSize["y"] = Config.Raids.BTRHeight + } + } + globals.BTRSettings.BasePriceTaxi = Config.Raids.BTRTaxiPrice + globals.BTRSettings.CleanUpPrice = Config.Raids.BTRCoverPrice + globals.BTRSettings.BearPriceMod = Config.Raids.BearMults + globals.BTRSettings.UsecPriceMod = Config.Raids.UsecMult + globals.BTRSettings.ScavPriceMod = Config.Raids.ScavMult } - } } - } - } - //############## PMC SECTION ##################, - if (Config.PMC.EnablePMC) { - if (Config.PMC.EnableConvert) { - PMC.convertIntoPmcChance.default.assault.min = Config.PMC.AItoPMC.ScavToPMC; - PMC.convertIntoPmcChance.default.cursedassault.min = Config.PMC.AItoPMC.CursedToPMC; - PMC.convertIntoPmcChance.default.pmcbot.min = Config.PMC.AItoPMC.RaiderToPMC; - PMC.convertIntoPmcChance.default.exusec.min = Config.PMC.AItoPMC.RogueToPMC; - PMC.convertIntoPmcChance.default.marksman = {}; - PMC.convertIntoPmcChance.default.marksman.min = Config.PMC.AItoPMC.SnipertoPMC; + //############## TRADERS SECTION ############## + if (Config.Traders.EnableTraders) { + if (Config.Traders.Fence.EnableFence) { + trader.fence.assortSize = Config.Traders.Fence.AmountOnSale; + trader.fence.discountOptions.assortSize = Config.Traders.Fence.PremiumAmountOnSale; + trader.fence.weaponPresetMinMax.min = Config.Traders.Fence.PresetCount; + trader.fence.weaponPresetMinMax.max = Config.Traders.Fence.PresetCount; + trader.fence.presetPriceMult = Config.Traders.Fence.PresetMult; + trader.fence.itemPriceMult = Config.Traders.Fence.PriceMult; + for (let stock in trader.updateTime)//useless cycle for now, will remove later. + { + if (trader.updateTime[stock].traderId === "579dc571d53a0658a154fbec") { + trader.updateTime[stock].seconds.min = Config.Traders.Fence.StockTime_Min * 60; + trader.updateTime[stock].seconds.max = Config.Traders.Fence.StockTime_Max * 60; + } + } + trader.fence.weaponDurabilityPercentMinMax.current.min = Config.Traders.Fence.GunDurability_Min + trader.fence.weaponDurabilityPercentMinMax.current.max = Config.Traders.Fence.GunDurability_Max + trader.fence.armorMaxDurabilityPercentMinMax.current.min = Config.Traders.Fence.ArmorDurability_Min + trader.fence.armorMaxDurabilityPercentMinMax.current.max = Config.Traders.Fence.ArmorDurability_Max + let BlacklistArray = Config.Traders.Fence.Blacklist.split("\r\n"); + BlackItems.blacklist.push(BlacklistArray); + } + globals.TradingSettings.BuyoutRestrictions.MinDurability = Config.Traders.MinDurabSell / 100 - PMC.convertIntoPmcChance.default.assault.max = Config.PMC.AItoPMC.ScavToPMC; - PMC.convertIntoPmcChance.default.cursedassault.max = Config.PMC.AItoPMC.CursedToPMC; - PMC.convertIntoPmcChance.default.pmcbot.max = Config.PMC.AItoPMC.RaiderToPMC; - PMC.convertIntoPmcChance.default.exusec.max = Config.PMC.AItoPMC.RogueToPMC; - PMC.convertIntoPmcChance.default.marksman.max = Config.PMC.AItoPMC.SniperToPMC; - PMC.isUsec = Config.PMC.PMCRatio; - } - PMC.botRelativeLevelDeltaMax = Config.PMC.LevelUpMargin; - PMC.botRelativeLevelDeltaMin = Config.PMC.LevelDownMargin; - if (Config.PMC.ChancesEnable) { - PMC.chanceSameSideIsHostilePercent = Config.PMC.PMCChance.HostilePMC; - PMC.looseWeaponInBackpackChancePercent = Config.PMC.PMCChance.PMCLooseWep; - PMC.weaponHasEnhancementChancePercent = Config.PMC.PMCChance.PMCWepEnhance; - PMC.addPrefixToSameNamePMCAsPlayerChance = Config.PMC.PMCChance.PMCNamePrefix; - PMC.allPMCsHavePlayerNameWithRandomPrefixChance = Config.PMC.PMCChance.PMCAllNamePrefix; - } - //Lootable melees - for (const id in items) { - let base = items[id] - if (base._parent === "5447e1d04bdc2dff2f8b4567" && base._id !== "6087e570b998180e9f76dc24" && Config.PMC.LootableMelee) { - EditSimpleItemData(id, "Unlootable", false); - items[id]._props.UnlootableFromSide = []; - } - } - if (Config.PMC.DisableLowLevelPMC) { - Bots.equipment.pmc.randomisation[0].levelRange.max = 1; - Bots.equipment.pmc.randomisation[1].levelRange.min = 1; - Bots.equipment.pmc.randomisation[2].levelRange.min = 1; - Bots.equipment.pmc.randomisation[3].levelRange.min = 1; - //Bots.equipment.pmc.randomisation[4].levelRange.min = 1; - } - if (Config.PMC.NamesEnable) { - if (Config.PMC.NameOverride) { - let Names = Config.PMC.PMCNameList.split("\r\n") - Bot["pmcusec"].firstName = Names; - Bot["pmcbear"].firstName = Names; - Bot["usec"].firstName = Names; - Bot["bear"].firstName = Names; - } - else { - let Names = Config.PMC.PMCNameList.split("\r\n") - for (const name in Names)//I don't really remember should i even have this cycle here, but eh, cba. - { - Bot["pmcusec"].firstName.push(Names[name]) - Bot["pmcbear"].firstName.push(Names[name]) - Bot["usec"].firstName.push(Names[name]) - Bot["bear"].firstName.push(Names[name]) - } - } - } - } - //############## REPEATABLE QUESTS SECTION ############# - if (Config.Quests.EnableQuests) { - const Daily = Config.Quests.DailyQuests; - const Weekly = Config.Quests.WeeklyQuests; - const ScavDaily = Config.Quests.ScavQuests; - //Requirements - QuestDetails(Daily, "0") - QuestDetails(Weekly, "1") - QuestDetails(ScavDaily, "2") - //Rewards - QuestReward(Daily, "0") - QuestReward(Weekly, "1") - QuestReward(ScavDaily, "2") - } - //############## SCAV SECTION ############## I wish i never made one, but here we are - if (Config.Scav.EnableScav) { - //Base Fence rep given by car extract - Inraid.carExtractBaseStandingGain = Config.Scav.CarBaseStanding - //Allow Scav into Lab - locations["laboratory"].base.DisabledForScav = !Config.Scav.ScavLab; - //Scav Cooldown Timer - globals.SavagePlayCooldown = Config.Scav.ScavTimer; + Quest.mailRedeemTimeHours.default = Config.Traders.QuestRedeemDefault; + Quest.mailRedeemTimeHours.unheard_edition = Config.Traders.QuestRedeemUnheard; - for (let levels in globals.FenceSettings.Levels)//Damn it looks counter intuitive - { - if (Config.Scav.HostileScavs) { - globals.FenceSettings.Levels[levels].HostileScavs = Config.Scav.HostileScavs + trader.purchasesAreFoundInRaid = Config.Traders.FIRTrade; + traders["5c0647fdd443bc2504c2d371"].base.unlockedByDefault = Config.Traders.UnlockJaeger + traders["6617beeaa9cfa777ca915b7c"].base.unlockedByDefault = Config.Traders.UnlockRef + const Mark = Config.Traders.TraderMarkup; + const MarkArray = [Mark.Prapor, + Mark.Therapist, + Mark.Fence, + Mark.Skier, + Mark.Peacekeeper, + Mark.Mechanic, + Mark.Ragman, + Mark.Jaeger + ] + let i = 0; + for (let CurTrader in traders) {//Bad solution to avoid modded traders. + if (CurTrader !== "ragfair" && (CurTrader == "5a7c2eca46aef81a7ca2145d" || CurTrader == "5ac3b934156ae10c4430e83c" || + CurTrader == "5c0647fdd443bc2504c2d371" || CurTrader == "54cb50c76803fa8b248b4571" || CurTrader == "54cb57776803fa99248b456e" || + CurTrader == "579dc571d53a0658a154fbec" || CurTrader == "5935c25fb3acc3127c3d8cd9" || CurTrader == "58330581ace78e27b8b10cee")) { + for (let level in traders[CurTrader].base.loyaltyLevels) { + traders[CurTrader].base.loyaltyLevels[level].buy_price_coef = 100 - MarkArray[i] + } + i++ + } + } + //Enable all the quests + if (Config.Traders.AllQuestsAvailable) { + for (let id in Quests) { + let QuestData = Quests[id] + QuestData.conditions.AvailableForStart = [] + } + } + if (Config.Traders.FIRRestrictsQuests) { + for (const id in Quests) { + let condition = Quests[id].conditions.AvailableForFinish + for (const requirements in condition) { + if (condition[requirements].onlyFoundInRaid !== undefined) { + condition[requirements].onlyFoundInRaid = false; + } + } + } + } + if (Config.Traders.RemoveTimeCondition) { + for (const id in Quests) { + let condition = Quests[id].conditions.AvailableForStart + for (const requirements in condition) { + if (condition[requirements].availableAfter !== undefined) { + condition[requirements].availableAfter = 0; + } + } + } + } + //Enable all traders 4 stars + if (Config.Traders.TradersLvl4) { + for (let traderID in traders) { + let loyaltyLevels = traders[traderID].base.loyaltyLevels; + for (let level in loyaltyLevels) { + loyaltyLevels[level].minLevel = 1 + loyaltyLevels[level].minSalesSum = 0 + loyaltyLevels[level].minStanding = 0 + } + } + } + if (Config.Traders.UnlockQuestAssort) { + for (let AssortR in traders) { + if (AssortR !== "ragfair" && AssortR !== "638f541a29ffd1183d187f57" && traders[AssortR].questassort.success !== undefined) { + traders[AssortR].questassort.success = {} + } + } + } + if (Config.Traders.RemoveTradeLimits) { + for (let AssortR in traders) { + if (AssortR !== "ragfair" && AssortR !== "638f541a29ffd1183d187f57") { + for (let level in traders[AssortR].assort.items) { + if (traders[AssortR].assort.items[level].upd !== undefined && traders[AssortR].assort.items[level].upd["BuyRestrictionMax"] !== undefined) { + traders[AssortR].assort.items[level].upd["BuyRestrictionMax"] = 999999; + } + } + } + } + } + if (Config.Traders.IncreaseAssort) { + for (let AssortR in traders) { + if (AssortR !== "ragfair" && AssortR !== "638f541a29ffd1183d187f57") { + for (let level in traders[AssortR].assort.items) { + if (traders[AssortR].assort.items[level].upd !== undefined && traders[AssortR].assort.items[level].upd["StackObjectsCount"] !== undefined) { + traders[AssortR].assort.items[level].upd["StackObjectsCount"] = 1337420; + } + } + } + } + } + //sell assort + const Sell = Config.Traders.TraderSell; + const SellArray = [Sell.Prapor, + Sell.Therapist, + Sell.Skier, + Sell.Peacekeeper, + Sell.Mechanic, + Sell.Ragman, + Sell.Jaeger + ] + let p = 0; + for (let CurTrader in Arrays.traderArray) { + for (let assortment in traders[Arrays.traderArray[CurTrader]].assort.barter_scheme) { + let TradeAssort = traders[Arrays.traderArray[CurTrader]].assort.barter_scheme[assortment][0][0]; + switch (TradeAssort._tpl) { + case "5449016a4bdc2d6f028b456f": + case "569668774bdc2da2298b4568": + case "5696686a4bdc2da3298b456a": + if (TradeAssort.count !== undefined) { + TradeAssort.count = parseFloat((TradeAssort.count * SellArray[p]).toFixed(2)); + } + break; + } + } + p++; + } + if (Config.Traders.RemoveCurrencyOffers || Config.Traders.RemoveBarterOffers) { + for (let CurTrader in traders) { + if (CurTrader !== "ragfair" && CurTrader !== "638f541a29ffd1183d187f57" && CurTrader !== "579dc571d53a0658a154fbec") //avoid ragfair, lighthouse trader and fence + { + for (let assortment in traders[CurTrader].assort.barter_scheme) { + let TradeAssort = traders[CurTrader].assort.barter_scheme[assortment][0][0]; + switch (TradeAssort._tpl) { + case "5449016a4bdc2d6f028b456f": + case "569668774bdc2da2298b4568": + case "5696686a4bdc2da3298b456a": + if (Config.Traders.RemoveCurrencyOffers) { + for (let DeletElem in traders[CurTrader].assort.items) {//3.10 rework instead of deleting assort - set everything to 0 instead. + if (traders[CurTrader].assort.items[DeletElem]._id == assortment) { + if (traders[CurTrader].assort.items[DeletElem].upd.UnlimitedCount !== undefined) { + traders[CurTrader].assort.items[DeletElem].upd.UnlimitedCount = false; + } + traders[CurTrader].assort.items[DeletElem].upd["StackObjectsCount"] = 0; + } + } + } + break; + default: + if (Config.Traders.RemoveBarterOffers) { + for (let DeletElem in traders[CurTrader].assort.items) { + if (traders[CurTrader].assort.items[DeletElem]._id == assortment) { + if (traders[CurTrader].assort.items[DeletElem].upd.UnlimitedCount !== undefined) { + traders[CurTrader].assort.items[DeletElem].upd.UnlimitedCount = false; + } + traders[CurTrader].assort.items[DeletElem].upd["StackObjectsCount"] = 0; + } + } + } + break; + } + } + } + } + } } - if (Config.Scav.HostileBosses) { - globals.FenceSettings.Levels[levels].HostileBosses = Config.Scav.HostileScavs - } - if (Config.Scav.FriendlyScavs) { - globals.FenceSettings.Levels[levels].HostileScavs = !Config.Scav.FriendlyScavs - } - if (Config.Scav.FriendlyBosses) { - globals.FenceSettings.Levels[levels].HostileBosses = !Config.Scav.FriendlyBosses - } - } - if (Config.Scav.ScavCustomPockets) { - const JsonUtil = container.resolve("JsonUtil"); - let ScavCustomPocketItem = JsonUtil.clone(items["557ffd194bdc2d28148b457f"]) - let ScavPocketSize = Config.Scav.SCAVPockets - ScavCustomPocketItem._id = "a8edfb0bce53d103d3f6219b" - for (let cell in ScavCustomPocketItem._props.Grids)//tried to make less code, made more, smh. - { - ScavCustomPocketItem._props.Grids[cell]._parent = "a8edfb0bce53d103d3f6219b" - } - ScavCustomPocketItem._props.Grids[0]._id = "a8edfb0bce53d103d3f6229b" - ScavCustomPocketItem._props.Grids[0]._props.cellsH = ScavPocketSize.FirstWidth - ScavCustomPocketItem._props.Grids[0]._props.cellsV = ScavPocketSize.FirstHeight - ScavCustomPocketItem._props.Grids[1]._id = "a8edfb0bce53d103d3f6239b" - ScavCustomPocketItem._props.Grids[1]._props.cellsH = ScavPocketSize.SecondWidth - ScavCustomPocketItem._props.Grids[1]._props.cellsV = ScavPocketSize.SecondHeight - ScavCustomPocketItem._props.Grids[2]._id = "a8edfb0bce53d103d3f6249b" - ScavCustomPocketItem._props.Grids[2]._props.cellsH = ScavPocketSize.ThirdWidth - ScavCustomPocketItem._props.Grids[2]._props.cellsV = ScavPocketSize.ThirdHeight - ScavCustomPocketItem._props.Grids[3]._id = "a8edfb0bce53d103d3f6259b" - ScavCustomPocketItem._props.Grids[3]._props.cellsH = ScavPocketSize.FourthWidth - ScavCustomPocketItem._props.Grids[3]._props.cellsV = ScavPocketSize.FourthHeight - switch (true) { - case ScavPocketSize.FourthWidth == 0 || ScavPocketSize.FourthHeight == 0: - ScavCustomPocketItem._props.Grids.splice(3, 1) - case ScavPocketSize.ThirdWidth == 0 || ScavPocketSize.ThirdHeight == 0: - ScavCustomPocketItem._props.Grids.splice(2, 1); - case ScavPocketSize.SecondWidth == 0 || ScavPocketSize.SecondHeight == 0: - ScavCustomPocketItem._props.Grids.splice(1, 1); - case ScavPocketSize.FirstWidth == 0 || ScavPocketSize.FirstHeight == 0: - ScavCustomPocketItem._props.Grids.splice(0, 1); - break; - default: - break; - } - items["a8edfb0bce53d103d3f6219b"] = ScavCustomPocketItem; - } - } - //############## CUSTOM SECTION ############## - if (Config.Custom.EnableCustom) { - if (Config.Custom.LoggerIntoServer) { - Logger.warning("[SVM] PRESET IS BEING LOGGED INTO SERVER, DO NOT USE THIS FEATURE UNDER NORMAL CIRCUMSTANCES") - Logger.debug(Config) - } - const Core = configServer.getConfig("spt-core"); - Core.features.chatbotFeatures.sptFriendEnabled = !Config.Custom.DisableSPTFriend - Core.features.chatbotFeatures.commandoEnabled = !Config.Custom.DisableCommando - if (Config.Custom.DisablePMCMessages) { - const Chat = configServer.getConfig("spt-pmcchatresponse"); - Chat.victim.responseChancePercent = 0; - Chat.killer.responseChancePercent = 0; - } + //############## PMC SECTION ##################, + if (Config.PMC.EnablePMC) { + if (Config.PMC.EnableConvert) { + PMC.convertIntoPmcChance.default.assault.min = Config.PMC.AItoPMC.ScavToPMC; + PMC.convertIntoPmcChance.default.cursedassault.min = Config.PMC.AItoPMC.CursedToPMC; + PMC.convertIntoPmcChance.default.pmcbot.min = Config.PMC.AItoPMC.RaiderToPMC; + PMC.convertIntoPmcChance.default.exusec.min = Config.PMC.AItoPMC.RogueToPMC; + PMC.convertIntoPmcChance.default.marksman = {}; + PMC.convertIntoPmcChance.default.marksman.min = Config.PMC.AItoPMC.SnipertoPMC; - //If you're reading here, maybe you checked that custom fields exist now, - //feel free to use this place to run your own little scripts using SVM as a framework, Search word is `banana` - //Mind you, Custom section needs to be enabled, you can however write stuff after the bracket there to run the code if at least preset exist. - //Fields names are `CustomCheck1,2,3,4` and `CustomNumber1,2,3,4` - } - //##### + PMC.convertIntoPmcChance.default.assault.max = Config.PMC.AItoPMC.ScavToPMC; + PMC.convertIntoPmcChance.default.cursedassault.max = Config.PMC.AItoPMC.CursedToPMC; + PMC.convertIntoPmcChance.default.pmcbot.max = Config.PMC.AItoPMC.RaiderToPMC; + PMC.convertIntoPmcChance.default.exusec.max = Config.PMC.AItoPMC.RogueToPMC; + PMC.convertIntoPmcChance.default.marksman.max = Config.PMC.AItoPMC.SniperToPMC; - //############## FUNCTIONS ############## - //Set a Unique AI type spawn within selected location, with a lot of variables to come in. - function CreateBoss(role, chance, followers, escortAmount, zones) { - return { - "BossName": role, - "BossChance": chance, - "BossZone": zones, - "BossPlayer": false, - "BossDifficult": "normal", - "BossEscortType": followers, - "BossEscortDifficult": "normal", - "BossEscortAmount": escortAmount, - "Time": -1 - } - } - function Filter(value) { - let test = value.substring(1, value.length - 1) - let result = test.split(",") - return result - } - function EditSimpleItemData(id, data, value) { - if (isNaN(value) && value !== 'true' && value !== 'false') { - items[id]._props[data] = value - } - else { - items[id]._props[data] = JSON.parse(value) - } - } - function QuestDetails(Type, Digit) { - Quest.repeatableQuests[Digit].resetTime = Type.Lifespan * 60; - Quest.repeatableQuests[Digit].types = [] - if (Digit < 2) { - switch (Type.Types)//Horrible - { - case 0: Quest.repeatableQuests[Digit].types.push(Arrays.Types[0]) - break; - case 1: Quest.repeatableQuests[Digit].types.push(Arrays.Types[1]) - break; - case 2: Quest.repeatableQuests[Digit].types.push(Arrays.Types[2]) - break; - case 3: Quest.repeatableQuests[Digit].types.push(Arrays.Types[0], Arrays.Types[1]) - break; - case 4: Quest.repeatableQuests[Digit].types.push(Arrays.Types[1], Arrays.Types[2]) - break; - case 5: Quest.repeatableQuests[Digit].types.push(Arrays.Types[2], Arrays.Types[2]) - break; - case 6: Quest.repeatableQuests[Digit].types.push(Arrays.Types[0], Arrays.Types[1], Arrays.Types[2]) - break; + PMC.convertIntoPmcChance.factory4_day.assault.min = Config.PMC.AItoPMC.ScavToPMCFactory; + PMC.convertIntoPmcChance.factory4_day.assault.max = Config.PMC.AItoPMC.ScavToPMCFactory; + PMC.isUsec = Config.PMC.PMCRatio; + for (let i in locations) { + if (i !== "base" && locations[i].base.BossLocationSpawn !== undefined) {//I Really think this is overkill, but oh well. + for (let ai in locations[i].base.BossLocationSpawn) { + if (locations[i].base.BossLocationSpawn[ai].BossName == "pmcBEAR" || locations[i].base.BossLocationSpawn[ai].BossName == "pmcUSEC") { + let randnum = Math.floor(Math.random() * 100) + 1 + if (randnum > Config.PMC.PMCRatio) { + locations[i].base.BossLocationSpawn[ai].BossName = "pmcBEAR"; + } + else { + locations[i].base.BossLocationSpawn[ai].BossName = "pmcUSEC"; + } + } + } + } + } + } + PMC.botRelativeLevelDeltaMax = Config.PMC.LevelUpMargin; + PMC.botRelativeLevelDeltaMin = Config.PMC.LevelDownMargin; + if (Config.PMC.ChancesEnable) { + //1.10.1 Hostility + PMC.hostilitySettings.pmcbear.usecEnemyChance = Config.PMC.PMCChance.HostilePMC + PMC.hostilitySettings.pmcbear.bearEnemyChance = Config.PMC.PMCChance.HostileSamePMC + PMC.hostilitySettings.pmcusec.bearEnemyChance = Config.PMC.PMCChance.HostilePMC + PMC.hostilitySettings.pmcusec.usecEnemyChance = Config.PMC.PMCChance.HostileSamePMC + for (let diffs in Bot["pmcusec"].difficulty) { + Bot["pmcusec"].difficulty[diffs].Mind.DEFAULT_USEC_BEHAVIOUR = "ChancedEnemies";//Something that live dumps and SPT configs have in conflict + Bot["pmcusec"].difficulty[diffs].Mind.DEFAULT_BEAR_BEHAVIOUR = "ChancedEnemies"; + Bot["usec"].difficulty[diffs].Mind.DEFAULT_USEC_BEHAVIOUR = "ChancedEnemies";//No clue whether just 'usec' or 'bear' is required. + Bot["usec"].difficulty[diffs].Mind.DEFAULT_BEAR_BEHAVIOUR = "ChancedEnemies"; + } + for (let diffs in Bot["pmcbear"].difficulty) { + Bot["pmcbear"].difficulty[diffs].Mind.DEFAULT_USEC_BEHAVIOUR = "ChancedEnemies"; + Bot["pmcbear"].difficulty[diffs].Mind.DEFAULT_BEAR_BEHAVIOUR = "ChancedEnemies"; + Bot["bear"].difficulty[diffs].Mind.DEFAULT_USEC_BEHAVIOUR = "ChancedEnemies"; + Bot["bear"].difficulty[diffs].Mind.DEFAULT_BEAR_BEHAVIOUR = "ChancedEnemies"; + } + AIHostility("pmcBEAR", "pmcUSEC") + AIHostility("pmcUSEC", "pmcBEAR") + PMC.looseWeaponInBackpackChancePercent = Config.PMC.PMCChance.PMCLooseWep; + PMC.weaponHasEnhancementChancePercent = Config.PMC.PMCChance.PMCWepEnhance; + PMC.addPrefixToSameNamePMCAsPlayerChance = Config.PMC.PMCChance.PMCNamePrefix; + PMC.allPMCsHavePlayerNameWithRandomPrefixChance = Config.PMC.PMCChance.PMCAllNamePrefix; + } + //Lootable melees + for (const id in items) { + let base = items[id] + if (base._parent === "5447e1d04bdc2dff2f8b4567" && base._id !== "6087e570b998180e9f76dc24" && Config.PMC.LootableMelee) { + EditSimpleItemData(id, "Unlootable", false); + items[id]._props.UnlootableFromSide = []; + } + } + if (Config.PMC.DisableLowLevelPMC) { + Bots.equipment.pmc.randomisation[0].levelRange.max = 1; + Bots.equipment.pmc.randomisation[1].levelRange.min = 1; + Bots.equipment.pmc.randomisation[2].levelRange.min = 1; + Bots.equipment.pmc.randomisation[3].levelRange.min = 1; + //Bots.equipment.pmc.randomisation[4].levelRange.min = 1; + } + if (Config.PMC.NamesEnable) { + if (Config.PMC.NameOverride) { + let Names = Config.PMC.PMCNameList.split("\r\n") + Bot["pmcusec"].firstName = Names; + Bot["pmcbear"].firstName = Names; + Bot["usec"].firstName = Names; + Bot["bear"].firstName = Names; + } + else { + let Names = Config.PMC.PMCNameList.split("\r\n") + for (const name in Names)//I don't really remember should i even have this cycle here, but eh, cba. + { + Bot["pmcusec"].firstName.push(Names[name]) + Bot["pmcbear"].firstName.push(Names[name]) + Bot["usec"].firstName.push(Names[name]) + Bot["bear"].firstName.push(Names[name]) + } + } + } } - } - else { - switch (Type.Types) { - case 0: Quest.repeatableQuests[2].types.push(Arrays.Types[0]) - break; - case 1: Quest.repeatableQuests[2].types.push(Arrays.Types[1]) - break; - case 2: Quest.repeatableQuests[2].types.push(Arrays.Types[0], Arrays.Types[1]) + //############## REPEATABLE QUESTS SECTION ############# + if (Config.Quests.EnableQuests) { + const Daily = Config.Quests.DailyQuests; + const Weekly = Config.Quests.WeeklyQuests; + const ScavDaily = Config.Quests.ScavQuests; + //Requirements + QuestDetails(Daily, "0") + QuestDetails(Weekly, "1") + QuestDetails(ScavDaily, "2") + //Rewards + QuestReward(Daily, "0") + QuestReward(Weekly, "1") + QuestReward(ScavDaily, "2") } - } + //############## SCAV SECTION ############## I wish i never made one, but here we are + if (Config.Scav.EnableScav) { + //Base Fence rep given by car extract + Inraid.carExtractBaseStandingGain = Config.Scav.CarBaseStanding + //Allow Scav into Lab + locations["laboratory"].base.DisabledForScav = !Config.Scav.ScavLab; + //Scav Cooldown Timer + globals.SavagePlayCooldown = Config.Scav.ScavTimer; - Quest.repeatableQuests[Digit].numQuests = Type.QuestAmount; - - Quest.repeatableQuests[Digit].minPlayerLevel = Type.Access - Quest.repeatableQuests[Digit].rewardScaling.rewardSpread = Type.Spread; - Quest.repeatableQuests[Digit].questConfig.Exploration.maxExtracts = Type.Extracts; - Quest.repeatableQuests[Digit].questConfig.Completion.minRequestedAmount = Type.MinItems; - Quest.repeatableQuests[Digit].questConfig.Completion.maxRequestedAmount = Type.MaxItems; - Quest.repeatableQuests[Digit].questConfig.Elimination[0].minKills = Type.MinKillsLR1; - Quest.repeatableQuests[Digit].questConfig.Elimination[0].maxKills = Type.MaxKillsLR1; - Quest.repeatableQuests[Digit].questConfig.Elimination[1].minKills = Type.MinKillsLR2; - Quest.repeatableQuests[Digit].questConfig.Elimination[1].maxKills = Type.MaxKillsLR2; - if (Digit < 2) { - Quest.repeatableQuests[Digit].questConfig.Elimination[2].minKills = Type.MinKillsLR3; - Quest.repeatableQuests[Digit].questConfig.Elimination[2].maxKills = Type.MaxKillsLR3; - } - } - function AirdropContents(DBType, Type) { - if (Airdrop.loot[DBType] != undefined) { - Airdrop.loot[DBType].itemCount.min = Type.BarterMin - Airdrop.loot[DBType].itemCount.max = Type.BarterMax - Airdrop.loot[DBType].weaponPresetCount.min = Type.PresetMin - Airdrop.loot[DBType].weaponPresetCount.max = Type.PresetMax - Airdrop.loot[DBType].armorPresetCount.min = Type.ArmorMin - Airdrop.loot[DBType].armorPresetCount.max = Type.ArmorMax - Airdrop.loot[DBType].weaponCrateCount.min = Type.CratesMin - Airdrop.loot[DBType].weaponCrateCount.max = Type.CratesMax - } - } - function QuestReward(Type, Digit) { - try { - let Levels = Type.Levels.split(","); - let Exp = Type.Experience.split(","); - let Reputation = Type.Reputation.split(","); - let ItemsReward = Type.ItemsReward.split(","); - let Roubles = Type.Roubles.split(","); - let GPcoins = Type.GPcoins.split(","); - let SkillChance = Type.SkillChance.split(","); - let SkillPoint = Type.SkillPoint.split(","); - - if ((Levels.length == Exp.length) && (Levels.length == Reputation.length) && - (Levels.length == ItemsReward.length) && (Levels.length == Roubles.length) && - (Levels.length == GPcoins.length) && (Levels.length == SkillChance.length) && (Levels.length == SkillPoint.length)) { - Quest.repeatableQuests[Digit].rewardScaling.levels = Levels.map(Number); - Quest.repeatableQuests[Digit].rewardScaling.experience = Exp.map(Number); - Quest.repeatableQuests[Digit].rewardScaling.reputation = Reputation.map(Number); - Quest.repeatableQuests[Digit].rewardScaling.items = ItemsReward.map(Number); - Quest.repeatableQuests[Digit].rewardScaling.roubles = Roubles.map(Number); - Quest.repeatableQuests[Digit].rewardScaling.gpCoins = GPcoins.map(Number); - Quest.repeatableQuests[Digit].rewardScaling.skillRewardChance = SkillChance.map(Number); - Quest.repeatableQuests[Digit].rewardScaling.skillPointReward = SkillPoint.map(Number); + for (let levels in globals.FenceSettings.Levels)//Damn it looks counter intuitive + { + if (Config.Scav.HostileScavs) { + globals.FenceSettings.Levels[levels].HostileScavs = Config.Scav.HostileScavs + } + if (Config.Scav.HostileBosses) { + globals.FenceSettings.Levels[levels].HostileBosses = Config.Scav.HostileScavs + } + if (Config.Scav.FriendlyScavs) { + globals.FenceSettings.Levels[levels].HostileScavs = !Config.Scav.FriendlyScavs + } + if (Config.Scav.FriendlyBosses) { + globals.FenceSettings.Levels[levels].HostileBosses = !Config.Scav.FriendlyBosses + } + } + if (Config.Scav.ScavCustomPockets) { + const JsonUtil = container.resolve("JsonUtil"); + let ScavCustomPocketItem = JsonUtil.clone(items["557ffd194bdc2d28148b457f"]) + let ScavPocketSize = Config.Scav.SCAVPockets + ScavCustomPocketItem._id = "a8edfb0bce53d103d3f6219b" + for (let cell in ScavCustomPocketItem._props.Grids)//tried to make less code, made more, smh. + { + ScavCustomPocketItem._props.Grids[cell]._parent = "a8edfb0bce53d103d3f6219b" + } + ScavCustomPocketItem._props.Grids[0]._id = "a8edfb0bce53d103d3f6229b" + ScavCustomPocketItem._props.Grids[0]._props.cellsH = ScavPocketSize.FirstWidth + ScavCustomPocketItem._props.Grids[0]._props.cellsV = ScavPocketSize.FirstHeight + ScavCustomPocketItem._props.Grids[1]._id = "a8edfb0bce53d103d3f6239b" + ScavCustomPocketItem._props.Grids[1]._props.cellsH = ScavPocketSize.SecondWidth + ScavCustomPocketItem._props.Grids[1]._props.cellsV = ScavPocketSize.SecondHeight + ScavCustomPocketItem._props.Grids[2]._id = "a8edfb0bce53d103d3f6249b" + ScavCustomPocketItem._props.Grids[2]._props.cellsH = ScavPocketSize.ThirdWidth + ScavCustomPocketItem._props.Grids[2]._props.cellsV = ScavPocketSize.ThirdHeight + ScavCustomPocketItem._props.Grids[3]._id = "a8edfb0bce53d103d3f6259b" + ScavCustomPocketItem._props.Grids[3]._props.cellsH = ScavPocketSize.FourthWidth + ScavCustomPocketItem._props.Grids[3]._props.cellsV = ScavPocketSize.FourthHeight + switch (true) { + case ScavPocketSize.FourthWidth == 0 || ScavPocketSize.FourthHeight == 0: + ScavCustomPocketItem._props.Grids.splice(3, 1) + case ScavPocketSize.ThirdWidth == 0 || ScavPocketSize.ThirdHeight == 0: + ScavCustomPocketItem._props.Grids.splice(2, 1); + case ScavPocketSize.SecondWidth == 0 || ScavPocketSize.SecondHeight == 0: + ScavCustomPocketItem._props.Grids.splice(1, 1); + case ScavPocketSize.FirstWidth == 0 || ScavPocketSize.FirstHeight == 0: + ScavCustomPocketItem._props.Grids.splice(0, 1); + break; + default: + break; + } + items["a8edfb0bce53d103d3f6219b"] = ScavCustomPocketItem; + } } - else { - Logger.error("[SVM] REPEATABLE QUESTS - Daily rewards scales written wrongly, read FAQ, changes ignored.") + //############## CUSTOM SECTION ############## + if (Config.Custom.EnableCustom) { + if (Config.Custom.LoggerIntoServer) { + Logger.warning("[SVM] PRESET IS BEING LOGGED INTO SERVER, DO NOT USE THIS FEATURE UNDER NORMAL CIRCUMSTANCES") + Logger.debug(Config) + } + const Core = configServer.getConfig("spt-core"); + Core.features.chatbotFeatures.sptFriendEnabled = !Config.Custom.DisableSPTFriend + Core.features.chatbotFeatures.commandoEnabled = !Config.Custom.DisableCommando + if (Config.Custom.DisablePMCMessages) { + const Chat = configServer.getConfig("spt-pmcchatresponse"); + Chat.victim.responseChancePercent = 0; + Chat.killer.responseChancePercent = 0; + } + + //If you're reading here, maybe you checked that custom fields exist now, + //feel free to use this place to run your own little scripts using SVM as a framework, Search word is `banana` + //Mind you, Custom section needs to be enabled, you can however write stuff after the bracket there to run the code if at least preset exist. + //Fields names are `CustomCheck1,2,3,4` and `CustomNumber1,2,3,4` } - } - catch { - Logger.error("[SVM] REPEATABLE QUESTS - Daily rewards scales written wrongly, read FAQ, changes ignored.") - } - } - function isJSONValueDefined(value) { - return value !== undefined && !value.isNaN; - } - function FreeExit(Exit) { - Exit.PassageRequirement = "None"; - Exit.ExfiltrationType = "Individual"; - Exit.Id = ''; - Exit.Count = 0; - Exit.PlayersCount = 0; - Exit.RequirementTip = ''; - if (Exit.RequiredSlot) { - delete Exit.RequiredSlot; - } - } - function IDChanger(Variables) { - try { - switch (Variables.length) { - case 3: - items[Variables[0]]._props[Variables[1]] = CheckType(Variables[2]) - break; - case 4: - if (SymbolCheck(Variables[2])) { - items[Variables[0]]._props[Variables[1]] = Calculus(items[Variables[0]]._props[Variables[1]], Variables[2], Variables[3]) + //##### + + //############## FUNCTIONS ############## + //Set a Unique AI type spawn within selected location, with a lot of variables to come in. + function AIHostility(First, Second) { + let temp; + if (First == "pmcUSEC") { + temp = "pmcusec" } else { - items[Variables[0]]._props[Variables[1]][Variables[2]] = CheckType(Variables[3]) + temp = "pmcbear" } - break; - case 5: - if (SymbolCheck(Variables[3])) { - items[Variables[0]]._props[Variables[1]][Variables[2]] = Calculus(items[Variables[0]]._props[Variables[1]][Variables[2]], Variables[3], Variables[4]) + for (let ai in PMC.hostilitySettings[temp].chancedEnemies) { + if (PMC.hostilitySettings[temp].chancedEnemies[ai].Role == Second) { + PMC.hostilitySettings[temp].chancedEnemies[ai].EnemyChance = Config.PMC.PMCChance.HostilePMC; + } + if (PMC.hostilitySettings[temp].chancedEnemies[ai].Role == First) { + PMC.hostilitySettings[temp].chancedEnemies[ai].EnemyChance = Config.PMC.PMCChance.HostileSamePMC; + } + } + for (let i in locations) { + if (i !== "base" && locations[i].base.BotLocationModifier.AdditionalHostilitySettings !== undefined) { + for (let ai in locations[i].base.BotLocationModifier.AdditionalHostilitySettings) { + if (locations[i].base.BotLocationModifier.AdditionalHostilitySettings[ai].BotRole == First) { + locations[i].base.BotLocationModifier.AdditionalHostilitySettings[ai].bearEnemyChance = Config.PMC.PMCChance.HostilePMC + locations[i].base.BotLocationModifier.AdditionalHostilitySettings[ai].usecEnemyChance = Config.PMC.PMCChance.HostileSamePMC + for (let hostility in locations[i].base.BotLocationModifier.AdditionalHostilitySettings[ai].ChancedEnemies) { + if (locations[i].base.BotLocationModifier.AdditionalHostilitySettings[ai].ChancedEnemies[hostility].Role == Second) {//Because one PMC type has entry of other type and not themselves + locations[i].base.BotLocationModifier.AdditionalHostilitySettings[ai].ChancedEnemies[hostility].EnemyChance = Config.PMC.PMCChance.HostilePMC + } + } + } + else//Due to namings of the variables, this extra thing goes + { + locations[i].base.BotLocationModifier.AdditionalHostilitySettings[ai].usecEnemyChance = Config.PMC.PMCChance.HostilePMC + locations[i].base.BotLocationModifier.AdditionalHostilitySettings[ai].bearEnemyChance = Config.PMC.PMCChance.HostileSamePMC + } + } + } + } + + + } + function CreateBoss(role, chance, followers, escortAmount, zones) { + return { + "BossName": role, + "BossChance": chance, + "BossZone": zones, + "BossPlayer": false, + "BossDifficult": "normal", + "BossEscortType": followers, + "BossEscortDifficult": "normal", + "BossEscortAmount": escortAmount, + "Time": -1 + } + } + function Filter(value) { + let test = value.substring(1, value.length - 1) + let result = test.split(",") + return result + } + function EditSimpleItemData(id, data, value) { + if (isNaN(value) && value !== 'true' && value !== 'false') { + items[id]._props[data] = value } else { - items[Variables[0]]._props[Variables[1]][Variables[2]][Variables[3]] = CheckType(Variables[4]) + items[id]._props[data] = JSON.parse(value) } - break; - case 6: - if (SymbolCheck(Variables[4])) { - items[Variables[0]]._props[Variables[1]][Variables[2]][Variables[3]] = Calculus(items[Variables[0]]._props[Variables[1]][Variables[2]][Variables[3]], Variables[4], Variables[5]) + } + function QuestDetails(Type, Digit) { + Quest.repeatableQuests[Digit].resetTime = Type.Lifespan * 60; + Quest.repeatableQuests[Digit].types = [] + if (Digit < 2) { + switch (Type.Types)//Horrible + { + case 0: Quest.repeatableQuests[Digit].types.push(Arrays.Types[0]) + break; + case 1: Quest.repeatableQuests[Digit].types.push(Arrays.Types[1]) + break; + case 2: Quest.repeatableQuests[Digit].types.push(Arrays.Types[2]) + break; + case 3: Quest.repeatableQuests[Digit].types.push(Arrays.Types[0], Arrays.Types[1]) + break; + case 4: Quest.repeatableQuests[Digit].types.push(Arrays.Types[1], Arrays.Types[2]) + break; + case 5: Quest.repeatableQuests[Digit].types.push(Arrays.Types[0], Arrays.Types[2]) + break; + case 6: Quest.repeatableQuests[Digit].types.push(Arrays.Types[0], Arrays.Types[1], Arrays.Types[2]) + break; + } } else { - items[Variables[0]]._props[Variables[1]][Variables[2]][Variables[3]][Variables[4]] = CheckType(Variables[5]) + switch (Type.Types) { + case 0: Quest.repeatableQuests[2].types.push(Arrays.Types[0]) + break; + case 1: Quest.repeatableQuests[2].types.push(Arrays.Types[1]) + break; + case 2: Quest.repeatableQuests[2].types.push(Arrays.Types[0], Arrays.Types[1]) + } + } + + Quest.repeatableQuests[Digit].numQuests = Type.QuestAmount; + + Quest.repeatableQuests[Digit].minPlayerLevel = Type.Access + Quest.repeatableQuests[Digit].rewardScaling.rewardSpread = Type.Spread; + Quest.repeatableQuests[Digit].questConfig.Exploration.maxExtracts = Type.Extracts; + Quest.repeatableQuests[Digit].questConfig.Completion.minRequestedAmount = Type.MinItems; + Quest.repeatableQuests[Digit].questConfig.Completion.maxRequestedAmount = Type.MaxItems; + Quest.repeatableQuests[Digit].questConfig.Elimination[0].minKills = Type.MinKillsLR1; + Quest.repeatableQuests[Digit].questConfig.Elimination[0].maxKills = Type.MaxKillsLR1; + Quest.repeatableQuests[Digit].questConfig.Elimination[1].minKills = Type.MinKillsLR2; + Quest.repeatableQuests[Digit].questConfig.Elimination[1].maxKills = Type.MaxKillsLR2; + if (Digit < 2) { + Quest.repeatableQuests[Digit].questConfig.Elimination[2].minKills = Type.MinKillsLR3; + Quest.repeatableQuests[Digit].questConfig.Elimination[2].maxKills = Type.MaxKillsLR3; } - break; - case 7: - items[Variables[0]]._props[Variables[1]][Variables[2]][Variables[3]][Variables[4]][Variables[5]] = CheckType(Variables[6]) - break; - case 8: - items[Variables[0]]._props[Variables[1]][Variables[2]][Variables[3]][Variables[4]][Variables[5]][Variables[6]] = CheckType(Variables[7]) - break; - case 9: - items[Variables[0]]._props[Variables[1]][Variables[2]][Variables[3]][Variables[4]][Variables[5]][Variables[6]][Variables[7]] = CheckType(Variables[8]) - break; - case 10: - items[Variables[0]]._props[Variables[1]][Variables[2]][Variables[3]][Variables[4]][Variables[5]][Variables[6]][Variables[7]][Variables[8]] = CheckType(Variables[9]) - break; - default: - Logger.error("[SVM] INVENTORY AND ITEMS - Custom properties line failed, More than 10 or less than 3 variables?") - break; } - } - catch (e) { - Logger.error("[SVM] INVENTORY AND ITEMS - Custom properties line failed, something ain't right\n" + e) - } - } - function CheckType(object) { - if (object.includes(",") || object.includes("[")) { - return Filter(object) - } - else if (isNaN(object) && object !== 'true' && object !== 'false') { - return object; - } - else { - return JSON.parse(object) - } - } - function SymbolCheck(Value) { - return (Value == "*" || Value == "/" || Value == "+" || Value == "-"); - } - function Calculus(Field, Operand, Value) { - switch (Operand) { - case "/": - Field = parseInt(parseInt(Field) / parseFloat(Value)) - break; - case "*": - Field = parseInt(parseInt(Field) * parseFloat(Value)) - break; - case "+": - Field = parseInt(parseInt(Field) + parseFloat(Value)) - break; - case "-": - Field = parseInt(parseInt(Field) - parseFloat(Value)) - break; - } - return Field - } - function AmmoFilter(AID, Comp) { - for (let ID in AID) { - if (Comp.includes(AID[ID])) { - return true; + function AirdropContents(DBType, Type) { + if (Airdrop.loot[DBType] != undefined) { + Airdrop.loot[DBType].itemCount.min = Type.BarterMin + Airdrop.loot[DBType].itemCount.max = Type.BarterMax + Airdrop.loot[DBType].weaponPresetCount.min = Type.PresetMin + Airdrop.loot[DBType].weaponPresetCount.max = Type.PresetMax + Airdrop.loot[DBType].armorPresetCount.min = Type.ArmorMin + Airdrop.loot[DBType].armorPresetCount.max = Type.ArmorMax + Airdrop.loot[DBType].weaponCrateCount.min = Type.CratesMin + Airdrop.loot[DBType].weaponCrateCount.max = Type.CratesMax + } + } + function QuestReward(Type, Digit) { + try { + let Levels = Type.Levels.split(","); + let Exp = Type.Experience.split(","); + let Reputation = Type.Reputation.split(","); + let ItemsReward = Type.ItemsReward.split(","); + let Roubles = Type.Roubles.split(","); + let GPcoins = Type.GPcoins.split(","); + let SkillChance = Type.SkillChance.split(","); + let SkillPoint = Type.SkillPoint.split(","); + + if ((Levels.length == Exp.length) && (Levels.length == Reputation.length) && + (Levels.length == ItemsReward.length) && (Levels.length == Roubles.length) && + (Levels.length == GPcoins.length) && (Levels.length == SkillChance.length) && (Levels.length == SkillPoint.length)) { + Quest.repeatableQuests[Digit].rewardScaling.levels = ApplyQuestRewardChange(Levels) + Quest.repeatableQuests[Digit].rewardScaling.experience = ApplyQuestRewardChange(Exp) + Quest.repeatableQuests[Digit].rewardScaling.reputation = ApplyQuestRewardChange(Reputation) + Quest.repeatableQuests[Digit].rewardScaling.ItemsReward = ApplyQuestRewardChange(ItemsReward) + Quest.repeatableQuests[Digit].rewardScaling.roubles = ApplyQuestRewardChange(Roubles) + Quest.repeatableQuests[Digit].rewardScaling.gpCoins = ApplyQuestRewardChange(GPcoins) + Quest.repeatableQuests[Digit].rewardScaling.SkillChance = ApplyQuestRewardChange(SkillChance) + Quest.repeatableQuests[Digit].rewardScaling.SkillPoint = ApplyQuestRewardChange(SkillPoint) + } + else {//I think at this point this one is redundant. + Logger.error("[SVM] REPEATABLE QUESTS - Daily rewards scales written wrongly, read FAQ, changes ignored.") + } + } + catch { + Logger.error("[SVM] REPEATABLE QUESTS - Daily rewards scales written wrongly, read FAQ, changes ignored.") + } + } + function ApplyQuestRewardChange(Item) { + if (!Item.map(Number).includes(NaN)) { + return Item.map(Number) + } + else { + Logger.error("[SVM] REPEATABLE QUESTS - Certain field is not a number: " + Item) + throw new Error() + } + } + function isJSONValueDefined(value) { + return value !== undefined && !value.isNaN; + } + function FreeExit(Exit) { + Exit.PassageRequirement = "None"; + Exit.ExfiltrationType = "Individual"; + Exit.Id = ''; + Exit.Count = 0; + Exit.PlayersCount = 0; + Exit.RequirementTip = ''; + if (Exit.RequiredSlot) { + delete Exit.RequiredSlot; + } + } + function IDChanger(Variables) { + try { + switch (Variables.length) { + case 3: + items[Variables[0]]._props[Variables[1]] = CheckType(Variables[2]) + break; + case 4: + if (SymbolCheck(Variables[2])) { + items[Variables[0]]._props[Variables[1]] = Calculus(items[Variables[0]]._props[Variables[1]], Variables[2], Variables[3]) + } + else { + items[Variables[0]]._props[Variables[1]][Variables[2]] = CheckType(Variables[3]) + } + break; + case 5: + if (SymbolCheck(Variables[3])) { + items[Variables[0]]._props[Variables[1]][Variables[2]] = Calculus(items[Variables[0]]._props[Variables[1]][Variables[2]], Variables[3], Variables[4]) + } + else { + items[Variables[0]]._props[Variables[1]][Variables[2]][Variables[3]] = CheckType(Variables[4]) + } + break; + case 6: + if (SymbolCheck(Variables[4])) { + items[Variables[0]]._props[Variables[1]][Variables[2]][Variables[3]] = Calculus(items[Variables[0]]._props[Variables[1]][Variables[2]][Variables[3]], Variables[4], Variables[5]) + } + else { + items[Variables[0]]._props[Variables[1]][Variables[2]][Variables[3]][Variables[4]] = CheckType(Variables[5]) + } + break; + case 7: + items[Variables[0]]._props[Variables[1]][Variables[2]][Variables[3]][Variables[4]][Variables[5]] = CheckType(Variables[6]) + break; + case 8: + items[Variables[0]]._props[Variables[1]][Variables[2]][Variables[3]][Variables[4]][Variables[5]][Variables[6]] = CheckType(Variables[7]) + break; + case 9: + items[Variables[0]]._props[Variables[1]][Variables[2]][Variables[3]][Variables[4]][Variables[5]][Variables[6]][Variables[7]] = CheckType(Variables[8]) + break; + case 10: + items[Variables[0]]._props[Variables[1]][Variables[2]][Variables[3]][Variables[4]][Variables[5]][Variables[6]][Variables[7]][Variables[8]] = CheckType(Variables[9]) + break; + default: + Logger.error("[SVM] INVENTORY AND ITEMS - Custom properties line failed, More than 10 or less than 3 variables?") + break; + } + } + catch (e) { + Logger.error("[SVM] INVENTORY AND ITEMS - Custom properties line failed, something ain't right\n" + e) + } + } + function CheckType(object) { + if (object.includes(",") || object.includes("[")) { + return Filter(object) + } + else if (isNaN(object) && object !== 'true' && object !== 'false') { + return object; + } + else { + return JSON.parse(object) + } + } + function SymbolCheck(Value) { + return (Value == "*" || Value == "/" || Value == "+" || Value == "-"); + } + function Calculus(Field, Operand, Value) { + switch (Operand) { + case "/": + Field = parseInt(parseInt(Field) / parseFloat(Value)) + break; + case "*": + Field = parseInt(parseInt(Field) * parseFloat(Value)) + break; + case "+": + Field = parseInt(parseInt(Field) + parseFloat(Value)) + break; + case "-": + Field = parseInt(parseInt(Field) - parseFloat(Value)) + break; + case "=": + Field = parseFloat(Value) + break; + } + return Field + } + function AmmoFilter(AID, Comp) { + for (let ID in AID) { + if (Comp.includes(AID[ID])) { + return true; + } + } + return false; + } + //initialise complete logger + const Misc = require('../src/Misc.json'); + Logger.log(`[SVM] Initialization complete. ` + Misc.funni[Math.floor(Math.random() * Misc.funni.length)], "blue"); + if (PresetLoader.CurrentlySelectedPreset != "" && PresetLoader.CurrentlySelectedPreset != undefined) { + Logger.log("[SVM] Preset - " + PresetLoader.CurrentlySelectedPreset + " - successfully loaded", "blue"); } - } - return false; } - //initialise complete logger - const Misc = require('../src/Misc.json'); - Logger.log(`[SVM] Initialization complete. ` + Misc.funni[Math.floor(Math.random() * Misc.funni.length)], "blue"); - if (PresetLoader.CurrentlySelectedPreset != "" && PresetLoader.CurrentlySelectedPreset != undefined) { - Logger.log("[SVM] Preset - " + PresetLoader.CurrentlySelectedPreset + " - successfully loaded", "blue"); - } - } } module.exports = { - mod: new MainSVM + mod: new MainSVM }; \ No newline at end of file diff --git a/mods/Server Value Modifier/User/Mods/[SVM] Server Value Modifier/src/Waves.json b/mods/Server Value Modifier/User/Mods/[SVM] Server Value Modifier/src/Waves.json index 19c5b18..6c67933 100644 --- a/mods/Server Value Modifier/User/Mods/[SVM] Server Value Modifier/src/Waves.json +++ b/mods/Server Value Modifier/User/Mods/[SVM] Server Value Modifier/src/Waves.json @@ -1,51 +1,49 @@ { -"Glukhar": -{ - "BossChance": 100, - "BossDifficult": "normal", - "BossEscortAmount": "2", - "BossEscortDifficult": "normal", - "BossEscortType": "followerGluharSecurity", - "BossName": "bossGluhar", - "BossPlayer": false, - "BossZone": "", - "Delay": 0, - "ForceSpawn": false, - "IgnoreMaxBots": true, - "RandomTimeSpawn": false, - "SpawnMode": [ - "regular", - "pve" - ], - "Supports": [ - { - "BossEscortAmount": "2", - "BossEscortDifficult": [ - "normal" - ], - "BossEscortType": "followerGluharAssault" - }, - { - "BossEscortAmount": "2", - "BossEscortDifficult": [ - "normal" - ], - "BossEscortType": "followerGluharSecurity" - }, - { - "BossEscortAmount": "2", - "BossEscortDifficult": [ - "normal" - ], - "BossEscortType": "followerGluharScout" - } - ], - "Time": -1, - "TriggerId": "", - "TriggerName": "" -}, - "Kaban": - { + "Glukhar": { + "BossChance": 100, + "BossDifficult": "normal", + "BossEscortAmount": "2", + "BossEscortDifficult": "normal", + "BossEscortType": "followerGluharSecurity", + "BossName": "bossGluhar", + "BossPlayer": false, + "BossZone": "", + "Delay": 0, + "ForceSpawn": false, + "IgnoreMaxBots": true, + "RandomTimeSpawn": false, + "SpawnMode": [ + "regular", + "pve" + ], + "Supports": [ + { + "BossEscortAmount": "2", + "BossEscortDifficult": [ + "normal" + ], + "BossEscortType": "followerGluharAssault" + }, + { + "BossEscortAmount": "2", + "BossEscortDifficult": [ + "normal" + ], + "BossEscortType": "followerGluharSecurity" + }, + { + "BossEscortAmount": "2", + "BossEscortDifficult": [ + "normal" + ], + "BossEscortType": "followerGluharScout" + } + ], + "Time": -1, + "TriggerId": "", + "TriggerName": "" + }, + "Kaban": { "BossChance": 100, "BossDifficult": "normal", "BossEscortAmount": "6", @@ -89,95 +87,126 @@ "TriggerId": "", "TriggerName": "" }, - "Kolontay": - { - "BossChance": 100, - "BossDifficult": "normal", - "BossEscortAmount": "2", - "BossEscortDifficult": "normal", - "BossEscortType": "followerKolontaySecurity", - "BossName": "bossKolontay", - "BossPlayer": false, - "BossZone": "", - "Delay": 0, - "ForceSpawn": false, - "IgnoreMaxBots": true, - "RandomTimeSpawn": false, - "SpawnMode": [ - "regular", - "pve" - ], - "Supports": [ - { - "BossEscortAmount": "2", - "BossEscortDifficult": [ - "normal" - ], - "BossEscortType": "followerKolontayAssault" - }, - { - "BossEscortAmount": "2", - "BossEscortDifficult": [ - "normal" - ], - "BossEscortType": "followerKolontaySecurity" - }, - { - "BossEscortAmount": "0", - "BossEscortDifficult": [ - "normal" - ], - "BossEscortType": "followerGluharScout" - } - ], - "Time": -1, - "TriggerId": "", - "TriggerName": "" - }, - "Goons":{ - "BossChance": 100, - "BossDifficult": "normal", - "BossEscortAmount": "2", - "BossEscortDifficult": "normal", - "BossEscortType": "exUsec", - "BossName": "bossKnight", - "BossPlayer": false, - "BossZone": "", - "Delay": 0, - "DependKarma": false, - "DependKarmaPVE": false, - "ForceSpawn": false, - "IgnoreMaxBots": true, - "RandomTimeSpawn": true, - "SpawnMode": [ - "regular", - "pve" - ], - "Supports": [ - { - "BossEscortAmount": "1", - "BossEscortDifficult": [ - "normal" - ], - "BossEscortType": "followerBigPipe" - }, - { - "BossEscortAmount": "1", - "BossEscortDifficult": [ - "normal" - ], - "BossEscortType": "followerBirdEye" - }, - { - "BossEscortAmount": "0", - "BossEscortDifficult": [ - "normal" - ], - "BossEscortType": "followerGluharScout" - } - ], - "Time": -1, - "TriggerId": "", - "TriggerName": "" - } + "Kolontay": { + "BossChance": 100, + "BossDifficult": "normal", + "BossEscortAmount": "2", + "BossEscortDifficult": "normal", + "BossEscortType": "followerKolontaySecurity", + "BossName": "bossKolontay", + "BossPlayer": false, + "BossZone": "", + "Delay": 0, + "ForceSpawn": false, + "IgnoreMaxBots": true, + "RandomTimeSpawn": false, + "SpawnMode": [ + "regular", + "pve" + ], + "Supports": [ + { + "BossEscortAmount": "2", + "BossEscortDifficult": [ + "normal" + ], + "BossEscortType": "followerKolontayAssault" + }, + { + "BossEscortAmount": "2", + "BossEscortDifficult": [ + "normal" + ], + "BossEscortType": "followerKolontaySecurity" + }, + { + "BossEscortAmount": "0", + "BossEscortDifficult": [ + "normal" + ], + "BossEscortType": "followerGluharScout" + } + ], + "Time": -1, + "TriggerId": "", + "TriggerName": "" + }, + "Goons": { + "BossChance": 100, + "BossDifficult": "normal", + "BossEscortAmount": "2", + "BossEscortDifficult": "normal", + "BossEscortType": "exUsec", + "BossName": "bossKnight", + "BossPlayer": false, + "BossZone": "", + "Delay": 0, + "DependKarma": false, + "DependKarmaPVE": false, + "ForceSpawn": false, + "IgnoreMaxBots": true, + "RandomTimeSpawn": true, + "SpawnMode": [ + "regular", + "pve" + ], + "Supports": [ + { + "BossEscortAmount": "1", + "BossEscortDifficult": [ + "normal" + ], + "BossEscortType": "followerBigPipe" + }, + { + "BossEscortAmount": "1", + "BossEscortDifficult": [ + "normal" + ], + "BossEscortType": "followerBirdEye" + } + ], + "Time": -1, + "TriggerId": "", + "TriggerName": "" + }, + "Cultists": { + "BossChance": 100, + "BossDifficult": "normal", + "BossEscortAmount": "2", + "BossEscortDifficult": "normal", + "BossEscortType": "sectantWarrior", + "BossName": "sectantPredvestnik", + "BossPlayer": false, + "BossZone": "", + "Delay": 0, + "DependKarma": false, + "DependKarmaPVE": false, + "ForceSpawn": false, + "IgnoreMaxBots": true, + "RandomTimeSpawn": true, + "SpawnMode": [ + "regular", + "pve" + ], + "Supports": [ + { + "BossEscortAmount": "1", + "BossEscortDifficult": [ + "normal" + ], + "BossEscortType": "sectantOni" + }, + { + "BossEscortAmount": "1", + "BossEscortDifficult": [ + "normal" + ], + "BossEscortType": "sectantPrizrak" + } + ], + "Time": -1, + "TriggerId": "", + "TriggerName": "" + } } \ No newline at end of file diff --git a/mods/Server Value Modifier/meta.ini b/mods/Server Value Modifier/meta.ini index c204006..7967a66 100644 --- a/mods/Server Value Modifier/meta.ini +++ b/mods/Server Value Modifier/meta.ini @@ -1,12 +1,12 @@ [General] gameName=spt modid=0 -version=d2024.12.19.0 +version=d2025.1.12.0 newestVersion= category="1,2" nexusFileStatus=1 -installationFile=SVM.Server.Value.Modifier1.10H4.zip -repository= +installationFile=SVM.Server.Value.Modifier1.10.1.zip +repository=Nexus ignoredVersion= comments= notes= diff --git a/mods/Server Value Modifier_backup/User/Mods/[SVM] Server Value Modifier/Disclaimer.url b/mods/Server Value Modifier_backup/User/Mods/[SVM] Server Value Modifier/Disclaimer.url new file mode 100644 index 0000000..78491a0 --- /dev/null +++ b/mods/Server Value Modifier_backup/User/Mods/[SVM] Server Value Modifier/Disclaimer.url @@ -0,0 +1,5 @@ +[{000214A0-0000-0000-C000-000000000046}] +Prop3=19,11 +[InternetShortcut] +IDList= +URL=https://hub.sp-tarkov.com/advertising-disclaimer/ diff --git a/mods/Server Value Modifier_backup/User/Mods/[SVM] Server Value Modifier/Greed.exe b/mods/Server Value Modifier_backup/User/Mods/[SVM] Server Value Modifier/Greed.exe new file mode 100644 index 0000000..9707908 Binary files /dev/null and b/mods/Server Value Modifier_backup/User/Mods/[SVM] Server Value Modifier/Greed.exe differ diff --git a/mods/Server Value Modifier_backup/User/Mods/[SVM] Server Value Modifier/LICENSE b/mods/Server Value Modifier_backup/User/Mods/[SVM] Server Value Modifier/LICENSE new file mode 100644 index 0000000..0a37488 --- /dev/null +++ b/mods/Server Value Modifier_backup/User/Mods/[SVM] Server Value Modifier/LICENSE @@ -0,0 +1,26 @@ +Personal Use Source License (PUSL) +Version 1.0 + +Copyright © 2024, GhostFenixx + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), +to use the Software for personal, non-commercial purposes only, subject to the following conditions: + + Usage Rights: + The Software may only be used for personal purposes. Commercial use of the Software is strictly prohibited without prior written permission from the author. + + Source Code Access: + The source code of the Software is made available for viewing, but modifications to the Software are restricted as follows: + You may modify the Software for personal use only. + You are not permitted to distribute or share any modified versions of the Software in any form. + + Redistribution: + You may not redistribute the Software, whether in its original or modified form, without obtaining explicit permission from the copyright holder. + + Non-Commercial Use: + This Software is provided for non-commercial use only. + Any use of the Software for commercial purposes, including but not limited to commercial distribution, is prohibited without a commercial license agreement obtained from the copyright holder. + + No Warranty: + The Software is provided “as is”, without warranty of any kind, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose, and non-infringement. + In no event shall the author or copyright holder be liable for any claim, damages, or other liability, whether in an action of contract, tort, or otherwise, arising from, out of, or in connection with the Software or the use or other dealings in the Software \ No newline at end of file diff --git a/mods/Server Value Modifier_backup/User/Mods/[SVM] Server Value Modifier/Loader/loader.json b/mods/Server Value Modifier_backup/User/Mods/[SVM] Server Value Modifier/Loader/loader.json new file mode 100644 index 0000000..a1b632c --- /dev/null +++ b/mods/Server Value Modifier_backup/User/Mods/[SVM] Server Value Modifier/Loader/loader.json @@ -0,0 +1,3 @@ +{ +"CurrentlySelectedPreset":"Default" +} \ No newline at end of file diff --git a/mods/Server Value Modifier_backup/User/Mods/[SVM] Server Value Modifier/package.json b/mods/Server Value Modifier_backup/User/Mods/[SVM] Server Value Modifier/package.json new file mode 100644 index 0000000..d151a8d --- /dev/null +++ b/mods/Server Value Modifier_backup/User/Mods/[SVM] Server Value Modifier/package.json @@ -0,0 +1,9 @@ +{ + "name": "SVM", + "author": "GhostFenixx", + "version": "1.10.0", + "sptVersion": "3.10.x", + "license": "PUSL", + "devdependencies": {}, + "main": "src/SVM.js" +} \ No newline at end of file diff --git a/mods/Server Value Modifier_backup/User/Mods/[SVM] Server Value Modifier/src/Arrays.json b/mods/Server Value Modifier_backup/User/Mods/[SVM] Server Value Modifier/src/Arrays.json new file mode 100644 index 0000000..2752bbe --- /dev/null +++ b/mods/Server Value Modifier_backup/User/Mods/[SVM] Server Value Modifier/src/Arrays.json @@ -0,0 +1,13 @@ +{ + "Pistol":["9x19", "9x18pm", "9x21", "762x25tt", "46x30", "57x28", "1143x23", "127x33", "9x33r", "10MM", "40SW", "357SIG", "9MM", "45ACP", "50AE", "380AUTO"], + "ARifle":["762x39", "545x39", "556x45", "9x39", "366", "762x35", "300blk", "ATL15", "GRENDEL", "50WLF", "KURZ"], + "Shotgun":["12x70", "20x70", "23x75"], + "MRifle":["762x51", "68x51", "762х54R", "762x54r", "86x70", "127x55", "277", "BMG"], + "MarkedKeys":["5780cf7f2459777de4559322", "5d80c60f86f77440373c4ece", "5d80c62a86f7744036212b3f", "5ede7a8229445733cb4c18e2", "63a3a93f8a56922e82001f5d", "64ccc25f95763a1ae376e447", "62987dfc402c7f69bf010923"], + "traderArray": ["54cb50c76803fa8b248b4571", "54cb57776803fa99248b456e", "58330581ace78e27b8b10cee", "5935c25fb3acc3127c3d8cd9", "5a7c2eca46aef81a7ca2145d", "5ac3b934156ae10c4430e83c", "5c0647fdd443bc2504c2d371"], + "CasesID":["59fb016586f7746d0d4b423a","5783c43d2459774bbe137486","60b0f6c058e0b0481a09ad11","5e2af55f86f7746d4159f07c","59fb042886f7746c5005a7b2","59fb023c86f7746d0d4b423c","5b7c710788a4506dec015957","5aafbde786f774389d0cbc0f","5c127c4486f7745625356c13","5c093e3486f77430cb02e593","5aafbcd986f7745e590fff23","5c0a840b86f7742ffa4f2482","5b6d9ce188a4501afc1b2b25","5d235bb686f77443f4331278","59fafd4b86f7745ca07e1232","590c60fc86f77412b13fddcf","567143bf4bdc2d1a0f8b4567","5c093db286f7740a1b2617e3","619cbf7d23893217ec30b689","619cbf9e0a7c3a1a2731940a","62a09d3bcf4a99369e262447"], + "SecConID":["544a11ac4bdc2d470e8b456a","5c093ca986f7740a1867ab12","5857a8b324597729ab0a0e7d","59db794186f77448bc595262","5857a8bc2459772bad15db29","665ee77ccf2d642e98220bca","5732ee6a24597719ae0c0281","64f6f4c5911bcdfe8b03b0dc"], + "AIAmount":["AsOnline","Low","Medium","High","Horde","NoBots"], + "AIDifficulty":["AsOnline","Easy","Medium","Hard","Impossible","Random"], + "Types":["Elimination","Completion","Exploration"] +} \ No newline at end of file diff --git a/mods/Server Value Modifier_backup/User/Mods/[SVM] Server Value Modifier/src/Misc.json b/mods/Server Value Modifier_backup/User/Mods/[SVM] Server Value Modifier/src/Misc.json new file mode 100644 index 0000000..ca63ab8 --- /dev/null +++ b/mods/Server Value Modifier_backup/User/Mods/[SVM] Server Value Modifier/src/Misc.json @@ -0,0 +1,120 @@ +{ +"funni":[ + "So, how's Erdtree? Or maybe you're into Dawntrail?", + "Have you tried Minecraft though?", + "I hope Nikita is proud of me", + "This release provides you 16x time the details according to Todd Howard", + "Bears are based but cringe, Usecs are cringe but based", + "69.6969% of the update time were wasted for this specific line you're reading", + "Still not enough tooltips added, slight chance to get stuck in a toaster", + "Kept ya waiting huh?", + "You're finally awake, you were trying to play like a chad, right?", + "It's here, lurking in the shadows", + "Chomp goes Caw Caw", + "Goose goes Honk Honk", + "GhostFenixx goes 'Not again'", + "No more KMC ;-;", + "Hello, how's your day? :]", + "I hope you have enough RAM to play this", + "Wipe at Thursday", + "Tagilla locked me up in the basement to write mods for Tarkov, send help", + "If you're reading this, you're capable of reading!", + "Who wrote this stuff anyway?", + "Hot single SCAVs in you area!", + "These lines are such a waste of space", + "I know you are reading this", + "Do you like hurting other people?", + "Don't play Gaijin games, such a cash grab, good source of classified data tho", + "YOU, YES YOU, YOU ARE AWESOME, NOW LIVE WITH THAT!", + "Did you wash your dishes?", + "Sanitar did nothing wrong", + "I actually played tarkov, finally", + "rat attac", + "Don't worry, I won't judge your preferences, you're my favorite casual <3", + "Me (Head-Eyes) You", + "HE DID THE WIGGLE!", + "Are you sure you enabled sections?", + "Did you know? If you kill guys with guns, there will be no one to kill you!", + "The all consuming gluttony is approaching", + "I swear if I forgot to remove a logger somewhere i'll choke someone", + "Go on, tell me you're trying to run EFT with 8GB of ram", + "Are you seriously playing SPT by yourself?", + "No, Putting 16x Scope onto TOZ is not a great idea", + "Don't dissapoint the Glock Daddy", + "Still can't play streets, right? I feel ya", + "Go on, take SVD into factory, see if I care", + "RFB AND VPO FOR THE WIN!", + "Makes your experience better since 2021!", + "Dear diary, today I died with LEDX not in the secure container", + "ALL SCREWS, NO NUTS, WHY?", + "One does not simply launch flare properly", + "Noooo, don't go that corridor, there is a mine in the room!", + "No more Autumn in Tarkov", + "The Holy Fox is gone", + "Don't play MMO's, those are unhealthy", + "I swear, stop putting those lines on Reddit", + "I really hope you do not restart the server to read those", + "There will be Up. Date. A creator on website nodes his head.", + "Stay Hydrated", + "Have you tried Gray Zone Warfare? :D", + "Still filled with bugs, don't worry", + "Pls leave a like an subscribe, don't forget to click a bell button", + "Google Clearly doesn't like me ;-;", + "Name of your PMC is disgusting, please revaluate your life choices", + "Why do you want to carry 2000 rounds in one slot?", + "Really? 20x2 cell sized pockets?", + "Extremis malis extrema remedia, effugere non potes", + "You're a PMC, Harry!", + "Join the Dark side, we have Igolniks", + "Imagine how many people died stepping on mines in Woods because they can't read the signs", + "Each new line added in message of the day is increasing the load on your CPU, let that sink in", + "Totally against Nikita(tm) vision(tm).", + "3 HEAVY BLEEDS IN ONE SHOT, THANKS SCAV!", + "What else can be so joyful than making a mod on my birthday? Not playing SPT afterwards!", + "Nice work bitch!", + "You can never go wrong loading .366 into 7.62x39 chamber", + "There was a blue sky and bright yellow field, but now it is always dark and gray", + "This mod probably works...Mostly? Hopefully?", + "I have 59 bazillion mods, why X field doesn't work?", + "What?", + "Really, stop looking here, play the game already >:C", + "Someday I'll paste whole Bee movie script here", + "Seriously, Roseheart, stop posting those on r/sptarkov.", + "They added a Deagle in the game...Makes me miss KMC once again", + "Swedish siesta is fun ngl", + "Yep, people still seem to fail to install this mod", + "3.9.8 huh? SPT lads do stack those numbers high", + "Cats are still superior than dogs, CWX.", + "Someday the war will be over and world won't be the same...", + "Damn, Stalker 2 footage is juicy", + "Do yourself a favor, stop shitposting", + "If SPT can go 3.10, so is SVM can go 1.10", + "Show must go on!", + ">Are You Happy? >No. >Why? >I play Escape from Tarkov", + "Deagle or Rsh12? That's the question.", + "You know, if you won't report issues to GhostFenixx, they won't be fixed.", + "Your AD could be here", + "А Я і досі у пошуках щастя", + "Вышел, блин, за хлебушком", + "Angel, save us!", + "You, Me, Factory, Full of nades", + "Damn bruv, your profile name is cringe", + "You're pretty good", + "ПРОДАМ ГАРАЖ", + "Fuck you, multitool", + "Just one more run to labs, it will be fine, i promise", + "ERROR, THE USER IS TOO HANDSOME TO PLAY THIS GAME!", + "Going for the resort for a red card is like a definition of insanity", + "I hope this app won't end in torrents", + "Сподіваюсь, з тобою все гаразд", + "[Insert Fun stuff for ADHD kiddos]", + "Want some game recommendation? Well I've got none, otherwise I wouldn't play EFT", + "Want some music recommendation? Check Solence.", + "Want some music recommendation? Check Architects.", + "Want some music recommendation? Check Bad Omens.", + "Want some music recommendation? Check Geneburn... Nah, i'm joking, Check Motionless in White.", + "Want some music recommendation? Check Imminence.", + "Want some music recommendation? Check Cantervice.", + "You better not forget to take splint with you this time", + "You cannot Escape From -REDACTED BY LICENSE VIOLATION-"] +} \ No newline at end of file diff --git a/mods/Server Value Modifier_backup/User/Mods/[SVM] Server Value Modifier/src/SVM.js b/mods/Server Value Modifier_backup/User/Mods/[SVM] Server Value Modifier/src/SVM.js new file mode 100644 index 0000000..13b0a60 --- /dev/null +++ b/mods/Server Value Modifier_backup/User/Mods/[SVM] Server Value Modifier/src/SVM.js @@ -0,0 +1,2407 @@ +"use strict"; + +class MainSVM { + preSptLoad(container) { + const Logger = container.resolve("WinstonLogger"); + try { //Checking for loader.json, if doesn't exist - throw a message, disable the mod. + const PresetLoader = require('../Loader/loader.json'); + if (PresetLoader.CurrentlySelectedPreset == null || PresetLoader.CurrentlySelectedPreset == "null") { + Logger.warning("[SVM] Null Preset detected, SVM is disabled, Most likely you're running this mod for the first time, head to the SVM mod folder and run the Greed.exe"); + return + } + const Config = require('../Presets/' + PresetLoader.CurrentlySelectedPreset + '.json'); + } + catch (e) { + const Logger = container.resolve("WinstonLogger"); + Logger.warning("\n[SVM] SVM is lacking loader file or there is an error, mod is disabled\n" + + "Most likely you're running this mod for the first time, head to the SVM mod folder and run the Greed.exe\n" + + "Don't forget to apply your changes...Really, hit that Apply button, it will create loader file\n" + + "[SVM] If it's Syntax error, edit it manually in loader.json or/and edit values with UIs properly\n" + + "Exception message below may help you distinguish what went wrong:\n"); + Logger.error(e.message + "\n"); + return + } + + const PresetLoader = require('../Loader/loader.json'); + const Config = require('../Presets/' + PresetLoader.CurrentlySelectedPreset + '.json'); + const StaticRouterModService = container.resolve("StaticRouterModService"); + const HttpResponse = container.resolve("HttpResponseUtil"); + const repeatableQuestController = container.resolve("RepeatableQuestController"); + + //PRE LOAD - QUESTS SECTION + if (Config.Quests.EnableQuests && Config.Quests.EnableQuestsMisc)//Horrible, as usual + { + try { + container.afterResolution("QuestCallbacks", (_t, result) => { + result.activityPeriods = (url, info, sessionID) => { + let Edited = repeatableQuestController.getClientRepeatableQuests(sessionID); + for (let quests in Edited) { + for (let act in Edited[quests].activeQuests) {//this needs to be trimmed as well, eventually. + if (Edited[quests].activeQuests[act].changeCost[0].count !== undefined) { + Edited[quests].activeQuests[act].changeCost[0].count = 5000 * Config.Quests.QuestCostMult; + } + if (Config.Quests.QuestRepToZero) { + Edited[quests].activeQuests[act].changeStandingCost = 0; + } + } + for (let inact in Edited[quests].inactiveQuests) { + if (Edited[quests].inactiveQuests[inact].changeCost[0].count !== undefined) { + Edited[quests].inactiveQuests[inact].changeCost[0].count = 5000 * Config.Quests.QuestCostMult; + } + if (Config.Quests.QuestRepToZero) { + Edited[quests].inactiveQuests[inact].changeStandingCost = 0; + } + } + for (let req in Edited[quests].changeRequirement) { + Edited[quests].changeRequirement[req].changeCost[0].count = 5000 * Config.Quests.QuestCostMult; + if (Config.Quests.QuestRepToZero) { + Edited[quests].changeRequirement[req].changeStandingCost = 0; + } + } + } + return HttpResponse.getBody(Edited); + } + }, { frequency: "Always" }); + + container.afterResolution("QuestCallbacks", (_t, result) => { + result.changeRepeatableQuest = (pmcData, body, sessionID) => { + //const repeatableQuestController = container.resolve("RepeatableQuestController"); + let Edited = repeatableQuestController.changeRepeatableQuest(pmcData, body, sessionID); + for (let quests in Edited.profileChanges) { + for (let test in Edited.profileChanges[quests].repeatableQuests[0].changeRequirement) { + Edited.profileChanges[quests].repeatableQuests[0].changeRequirement[test].changeCost[0].count = 5000 * Config.Quests.QuestCostMult; + if (Config.Quests.QuestRepToZero) { + Edited.profileChanges[quests].repeatableQuests[0].changeRequirement[test].changeStandingCost = 0; + } + } + } + return Edited; + } + }, { frequency: "Always" }); + } + catch (e) { + Logger.error("[SVM] REPEATABLE QUEST HANDLED EXCEPTION - Something wrong attempting to change quest reroll price\n" + e.message + "\n"); + } + } + //PRE LOAD - RAIDS SECTION + if (Config.Raids.RaidEvents.Halloween || Config.Raids.RaidEvents.Christmas)//Extra check, just in case + { + StaticRouterModService.registerStaticRouter("EventOverride", + [ + { + url: "/client/game/version/validate", + action: (url, info, sessionID) => { + const DB = container.resolve("DatabaseService"); + const globalConfig = DB.getGlobals().config; + const configServer = container.resolve("ConfigServer"); + const SeasonalEventService = container.resolve("SeasonalEventService"); + const Events = configServer.getConfig("spt-seasonalevents"); + + //let event = []; + if (Config.Raids.RaidEvents.Christmas) { + SeasonalEventService.updateGlobalEvents(globalConfig, Events.events[1]); + } + if (Config.Raids.RaidEvents.Halloween) { + SeasonalEventService.updateGlobalEvents(globalConfig, Events.events[0]); + } + return HttpResponse.nullResponse(); + } + } + ], "spt"); + } + if (Config.Hideout.EnableHideout) { + if (Config.Hideout.Regeneration.OfflineRegen) { + container.afterResolution("GameController", (_t, result) => { + result.updateProfileHealthValues = (url, info, sessionID) => { + } + }, { frequency: "Always" }); + } + } + + if (Config.Raids.SafeExit) { + container.afterResolution("MatchCallbacks", (_t, result) => { + result.endLocalRaid = (url, info, sessionID) => { + if (info.results.result == "Left") { + info.results.result = "Runner" + } + const MatchController = container.resolve("MatchController"); + MatchController.endLocalRaid(sessionID, info); + return HttpResponse.nullResponse(); + } + }, { frequency: "Always" }); + } + if (Config.Raids.SaveGearAfterDeath) { + container.afterResolution("MatchCallbacks", (_t, result) => { + result.endLocalRaid = (url, info, sessionID) => { + if (info.results.result !== "Survived") { + info.results.result = "Runner" + } + const MatchController = container.resolve("MatchController"); + MatchController.endLocalRaid(sessionID, info); + return HttpResponse.nullResponse(); + } + }, { frequency: "Always" }); + } + //PRE LOAD - CSM SECTION + //Attempt to fix pockets if custom is not present + StaticRouterModService.registerStaticRouter("Revive Pockets", + [ + { + url: "/client/game/version/validate", + action: (url, info, sessionID) => { + let pmcData = container.resolve("ProfileHelper").getPmcProfile(sessionID); + let pockets; + try { + if (pmcData.Info.GameVersion == "unheard_edition") { + pockets = "65e080be269cbd5c5005e529"; + } + else { + pockets = "627a4e6b255f7527fb05a0f6"; + } + pmcData.Inventory.items.forEach((item) => { + if (item.slotId == "Pockets" && item._tpl == "a8edfb0bce53d103d3f62b9b") { + item._tpl = pockets; + } + }) + return HttpResponse.nullResponse(); + } + catch (e) { + Logger.error("[SVM] CSM CUSTOM POCKETS - New profile detected, Cancelling function, restart the game to fix it.\n" + e.message) + return HttpResponse.nullResponse(); + } + } + }], "spt"); + if (Config.CSM.EnableCSM && Config.CSM.CustomPocket) { + StaticRouterModService.registerStaticRouter("CustomPocket", + [ + { + url: "/client/game/version/validate", + action: (url, info, sessionID) => { + let pmcData = container.resolve("ProfileHelper").getPmcProfile(sessionID); + try { + pmcData.Inventory.items.forEach((item) => { + if (item.slotId == "Pockets") { + item._tpl = "a8edfb0bce53d103d3f62b9b"; + } + }) + return HttpResponse.nullResponse(); + } + catch (e) { + Logger.error("[SVM] CSM CUSTOM POCKETS - New profile detected, Cancelling function, restart the game to fix it.\n" + e.message) + return HttpResponse.nullResponse(); + } + } + }], "spt"); + } + //HEALTH + SCAV FUNCTIONS + if (Config.Player.EnableHealth || Config.Scav.EnableScavHealth || Config.Scav.ScavCustomPockets || Config.Player.EnableStats || Config.Scav.EnableStats) //TO OVERRIDE HEALTH, STATS + CURRENT SCAV HEALTH, STATS AND POCKETS BEFORE RAID + { + StaticRouterModService.registerStaticRouter("EditHealth", + [ + { + url: "/client/game/version/validate", + action: (url, info, sessionID) => { + try { + let pmcData = container.resolve("ProfileHelper").getPmcProfile(sessionID); + let scavData = container.resolve("ProfileHelper").getScavProfile(sessionID); + if (Config.Player.EnableStats) { + pmcData.Health.Energy.Maximum = Config.Player.PMCStats.MaxEnergy; + pmcData.Health.Hydration.Maximum = Config.Player.PMCStats.MaxHydration; + } + if (Config.Scav.EnableStats) { + scavData.Health.Energy.Maximum = Config.Scav.ScavStats.MaxEnergy; + scavData.Health.Hydration.Maximum = Config.Scav.ScavStats.MaxHydration; + } + if (Config.Player.EnableHealth) { + HealthEdit(pmcData, Config.Player.Health.Head, Config.Player.Health.Chest, Config.Player.Health.Stomach, Config.Player.Health.LeftArm, Config.Player.Health.LeftLeg, Config.Player.Health.RightArm, Config.Player.Health.RightLeg, "Maximum"); + } + if (Config.Scav.EnableScavHealth) { + HealthEdit(scavData, Config.Scav.Health.Head, Config.Scav.Health.Chest, Config.Scav.Health.Stomach, Config.Scav.Health.LeftArm, Config.Scav.Health.LeftLeg, Config.Scav.Health.RightArm, Config.Scav.Health.RightLeg, "Current"); + HealthEdit(scavData, Config.Scav.Health.Head, Config.Scav.Health.Chest, Config.Scav.Health.Stomach, Config.Scav.Health.LeftArm, Config.Scav.Health.LeftLeg, Config.Scav.Health.RightArm, Config.Scav.Health.RightLeg, "Maximum"); + } + if (Config.Scav.ScavCustomPockets) { + scavData.Inventory.items.forEach((item) => { + if (item.slotId == "Pockets") { + item._tpl = "a8edfb0bce53d103d3f6219b"; + } + }) + } + return HttpResponse.nullResponse(); + } + catch (e) { + Logger.error("[SVM] PMC/SCAV HEALTH/STATS - Didn't manage to apply settings, new profile?\n" + e) + return HttpResponse.nullResponse(); + } + } + }], "spt"); + } + if (Config.Scav.EnableScavHealth || Config.Scav.ScavCustomPockets) { // TO OVERRIDE NEXT SCAVS HEALTH + POCKETS + //May Omnissiah save our souls, have to use both because register affects deaths and resolution affects extracts. Don't ask + container.afterResolution("ProfileController", (_t, result) => { + result.generatePlayerScav = (sessionID) => { + const playerScavGenerator = container.resolve("PlayerScavGenerator"); + const scavData = playerScavGenerator.generate(sessionID); + if (Config.Scav.EnableStats) { + scavData.Health.Energy.Maximum = Config.Scav.ScavStats.MaxEnergy; + scavData.Health.Hydration.Maximum = Config.Scav.ScavStats.MaxHydration; + } + HealthEdit(scavData, Config.Scav.Health.Head, Config.Scav.Health.Chest, Config.Scav.Health.Stomach, Config.Scav.Health.LeftArm, Config.Scav.Health.LeftLeg, Config.Scav.Health.RightArm, Config.Scav.Health.RightLeg, "Current"); + HealthEdit(scavData, Config.Scav.Health.Head, Config.Scav.Health.Chest, Config.Scav.Health.Stomach, Config.Scav.Health.LeftArm, Config.Scav.Health.LeftLeg, Config.Scav.Health.RightArm, Config.Scav.Health.RightLeg, "Maximum"); + if (Config.Scav.ScavCustomPockets) { + scavData.Inventory.items.forEach((item) => { + if (item.slotId == "Pockets") { + item._tpl = "a8edfb0bce53d103d3f6219b"; + } + }) + } + return scavData; + } + }, { frequency: "Always" }); + + StaticRouterModService.registerStaticRouter("EditHealthv2", + [ + { + url: "/raid/profile/save", + action: (url, info, sessionID) => { + if (info.exit !== "survived" && info.exit !== "runner" && info.isPlayerScav) // 3.9.0 If statement for avoiding rerolling survived SCAV, biggest issue of 1.8.3 + { + const saveServer = container.resolve("SaveServer"); + const playerScavGenerator = container.resolve("PlayerScavGenerator"); + const scavData = playerScavGenerator.generate(sessionID); + HealthEdit(scavData, Config.Scav.Health.Head, Config.Scav.Health.Chest, Config.Scav.Health.Stomach, Config.Scav.Health.LeftArm, Config.Scav.Health.LeftLeg, Config.Scav.Health.RightArm, Config.Scav.Health.RightLeg, "Current"); + HealthEdit(scavData, Config.Scav.Health.Head, Config.Scav.Health.Chest, Config.Scav.Health.Stomach, Config.Scav.Health.LeftArm, Config.Scav.Health.LeftLeg, Config.Scav.Health.RightArm, Config.Scav.Health.RightLeg, "Maximum"); + if (Config.Scav.ScavCustomPockets) { + scavData.Inventory.items.forEach((item) => { + if (item.slotId == "Pockets") { + item._tpl = "a8edfb0bce53d103d3f6219b"; + } + }) + } + saveServer.getProfile(sessionID).characters.scav = scavData; + } + return HttpResponse.nullResponse(); + } + }], "spt"); + } + function HealthEdit(Data, Head, Chest, Stomach, LeftArm, LeftLeg, RightArm, RightLeg, CurMax) { + try { + Data.Health.BodyParts["Head"].Health[CurMax] = Head + Data.Health.BodyParts["Chest"].Health[CurMax] = Chest + Data.Health.BodyParts["Stomach"].Health[CurMax] = Stomach + Data.Health.BodyParts["LeftArm"].Health[CurMax] = LeftArm + Data.Health.BodyParts["LeftLeg"].Health[CurMax] = LeftLeg + Data.Health.BodyParts["RightArm"].Health[CurMax] = RightArm + Data.Health.BodyParts["RightLeg"].Health[CurMax] = RightLeg + } + catch { + Logger.error("[SVM] HEALTH EDIT - Something went wrong with trying to generate custom maximum health, new profile? \n" + e) + } + } + } + postDBLoad(container) { + const PreDBStart = performance.now(); + const Logger = container.resolve("WinstonLogger"); + try {//This is dumb piece of code is a handler so PostDB won't run after PreDB did throw a message that something ain't right with the loader. + const PresetLoader = require('../Loader/loader.json'); + const Config = require('../Presets/' + PresetLoader.CurrentlySelectedPreset + '.json'); + } + catch (e) { + return + } + //Config variables to asset for funcs. + const PresetLoader = require('../Loader/loader.json'); + const Config = require('../Presets/' + PresetLoader.CurrentlySelectedPreset + '.json'); + const Arrays = require('../src/Arrays.json'); + //DB redirects + const DB = container.resolve("DatabaseService").getTables(); + const hideout = DB.hideout; + const locations = DB.locations; + const traders = DB.traders; + const Quests = DB.templates.quests; + const suits = DB.templates.customization; + const items = DB.templates.items; + const globals = DB.globals.config; + const Bot = DB.bots.types + // Redirects to server internal configs. + const configServer = container.resolve("ConfigServer"); + const Inraid = configServer.getConfig("spt-inraid"); + const Repair = configServer.getConfig("spt-repair"); + const locs = configServer.getConfig("spt-location"); + const Airdrop = configServer.getConfig("spt-airdrop"); + const Ragfair = configServer.getConfig("spt-ragfair"); + const Insurance = configServer.getConfig("spt-insurance"); + const Health = configServer.getConfig("spt-health"); + const Bots = configServer.getConfig("spt-bot"); + const Quest = configServer.getConfig("spt-quest"); + const WeatherValues = configServer.getConfig("spt-weather"); + const trader = configServer.getConfig("spt-trader"); + const Events = configServer.getConfig("spt-seasonalevents"); + //const Inventory = configServer.getConfig("aki-inventory"); + const BlackItems = configServer.getConfig("spt-item"); + const PMC = configServer.getConfig("spt-pmc") + //############## FLEAMARKET SECTION ########### + if (Config.Fleamarket.EnableFleamarket) { + if (Config.Fleamarket.EnablePlayerOffers) { + globals.RagFair.minUserLevel = Config.Fleamarket.FleaMarketLevel; + Ragfair.dynamic.purchasesAreFoundInRaid = Config.Fleamarket.FleaFIR; + globals.RagFair.isOnlyFoundInRaidAllowed = Config.Fleamarket.FleaNoFIRSell; + Ragfair.dynamic.blacklist.enableBsgList = !Config.Fleamarket.DisableBSGList; + Ragfair.sell.fees = Config.Fleamarket.EnableFees; + Ragfair.sell.chance.base = Config.Fleamarket.Sell_chance; + Ragfair.sell.chance.sellMultiplier = Config.Fleamarket.Sell_mult; + Ragfair.sell.time.max = Config.Fleamarket.Tradeoffer_max; + Ragfair.sell.time.min = Config.Fleamarket.Tradeoffer_min; + globals.RagFair.ratingIncreaseCount = Config.Fleamarket.Rep_gain; + globals.RagFair.ratingDecreaseCount = Config.Fleamarket.Rep_loss; + + if (Config.Fleamarket.OverrideOffers) { + const offer = { + "from": -100000, + "to": 100000, + "count": Config.Fleamarket.SellOffersAmount + } + globals.RagFair.maxActiveOfferCount = [] + globals.RagFair.maxActiveOfferCount.push(offer) + } + } + //Bundle Chance + Ragfair.dynamic.pack.chancePercent = Config.Fleamarket.DynamicOffers.BundleOfferChance; + //Dynamic offers + Ragfair.dynamic.expiredOfferThreshold = Config.Fleamarket.DynamicOffers.ExpireThreshold; + //Min-Max + Ragfair.dynamic.offerItemCount.min = Config.Fleamarket.DynamicOffers.PerOffer_min; + Ragfair.dynamic.offerItemCount.max = Config.Fleamarket.DynamicOffers.PerOffer_max; + //Unifying the multiplier, not the best case scenario, but it is rather simple to comprehend and modify for common user, they'll never know >_> + Ragfair.dynamic.priceRanges.default.min = Config.Fleamarket.DynamicOffers.Price_min; + Ragfair.dynamic.priceRanges.default.max = Config.Fleamarket.DynamicOffers.Price_max; + Ragfair.dynamic.priceRanges.pack.min = Config.Fleamarket.DynamicOffers.Price_min; + Ragfair.dynamic.priceRanges.pack.max = Config.Fleamarket.DynamicOffers.Price_max; + Ragfair.dynamic.priceRanges.preset.min = Config.Fleamarket.DynamicOffers.Price_min; + Ragfair.dynamic.priceRanges.preset.max = Config.Fleamarket.DynamicOffers.Price_max; + Ragfair.dynamic.endTimeSeconds.min = Config.Fleamarket.DynamicOffers.Time_min * 60; + Ragfair.dynamic.endTimeSeconds.max = Config.Fleamarket.DynamicOffers.Time_max * 60; + Ragfair.dynamic.nonStackableCount.min = Config.Fleamarket.DynamicOffers.NonStack_min; + Ragfair.dynamic.nonStackableCount.max = Config.Fleamarket.DynamicOffers.NonStack_max; + Ragfair.dynamic.stackablePercent.min = Config.Fleamarket.DynamicOffers.Stack_min; + Ragfair.dynamic.stackablePercent.max = Config.Fleamarket.DynamicOffers.Stack_max; + //Currencies + Ragfair.dynamic.currencies["5449016a4bdc2d6f028b456f"] = Config.Fleamarket.DynamicOffers.Roubleoffers; + Ragfair.dynamic.currencies["5696686a4bdc2da3298b456a"] = Config.Fleamarket.DynamicOffers.Dollaroffers; + Ragfair.dynamic.currencies["569668774bdc2da2298b4568"] = Config.Fleamarket.DynamicOffers.Eurooffers; + //Wear condition in offers + if (Config.Fleamarket.EnableFleaConditions) + Ragfair.dynamic.condition["5422acb9af1c889c16000029"].max.min = parseFloat((Config.Fleamarket.FleaConditions.FleaWeapons_Min / 100).toFixed(2)) + Ragfair.dynamic.condition["543be5664bdc2dd4348b4569"].max.min = parseFloat((Config.Fleamarket.FleaConditions.FleaMedical_Min / 100).toFixed(2)) + Ragfair.dynamic.condition["5447e0e74bdc2d3c308b4567"].max.min = parseFloat((Config.Fleamarket.FleaConditions.FleaSpec_Min / 100).toFixed(2)) + Ragfair.dynamic.condition["543be5e94bdc2df1348b4568"].max.min = parseFloat((Config.Fleamarket.FleaConditions.FleaKeys_Min / 100).toFixed(2)) + Ragfair.dynamic.condition["5448e5284bdc2dcb718b4567"].max.min = parseFloat((Config.Fleamarket.FleaConditions.FleaVests_Min / 100).toFixed(2)) + Ragfair.dynamic.condition["57bef4c42459772e8d35a53b"].max.min = parseFloat((Config.Fleamarket.FleaConditions.FleaArmor_Min / 100).toFixed(2)) + Ragfair.dynamic.condition["543be6674bdc2df1348b4569"].max.min = parseFloat((Config.Fleamarket.FleaConditions.FleaFood_Min / 100).toFixed(2)) + Ragfair.dynamic.condition["5422acb9af1c889c16000029"].max.max = parseFloat((Config.Fleamarket.FleaConditions.FleaWeapons_Max / 100).toFixed(2)) + Ragfair.dynamic.condition["543be5664bdc2dd4348b4569"].max.max = parseFloat((Config.Fleamarket.FleaConditions.FleaMedical_Max / 100).toFixed(2)) + Ragfair.dynamic.condition["5447e0e74bdc2d3c308b4567"].max.max = parseFloat((Config.Fleamarket.FleaConditions.FleaSpec_Max / 100).toFixed(2)) + Ragfair.dynamic.condition["543be5e94bdc2df1348b4568"].max.max = parseFloat((Config.Fleamarket.FleaConditions.FleaKeys_Max / 100).toFixed(2)) + Ragfair.dynamic.condition["5448e5284bdc2dcb718b4567"].max.max = parseFloat((Config.Fleamarket.FleaConditions.FleaVests_Max / 100).toFixed(2)) + Ragfair.dynamic.condition["57bef4c42459772e8d35a53b"].max.max = parseFloat((Config.Fleamarket.FleaConditions.FleaArmor_Max / 100).toFixed(2)) + Ragfair.dynamic.condition["543be6674bdc2df1348b4569"].max.max = parseFloat((Config.Fleamarket.FleaConditions.FleaFood_Max / 100).toFixed(2)) + } + //############## LOOT SECTION ################# + if (Config.Loot.EnableLoot) { + //loose loot mults + locs.looseLootMultiplier.bigmap = Config.Loot.Locations.Streets.Loose; + locs.looseLootMultiplier.factory4_day = Config.Loot.Locations.FactoryDay.Loose; + locs.looseLootMultiplier.factory4_night = Config.Loot.Locations.FactoryNight.Loose; + locs.looseLootMultiplier.interchange = Config.Loot.Locations.Interchange.Loose; + locs.looseLootMultiplier.laboratory = Config.Loot.Locations.Laboratory.Loose; + locs.looseLootMultiplier.rezervbase = Config.Loot.Locations.Reserve.Loose; + locs.looseLootMultiplier.shoreline = Config.Loot.Locations.Shoreline.Loose; + locs.looseLootMultiplier.woods = Config.Loot.Locations.Woods.Loose; + locs.looseLootMultiplier.lighthouse = Config.Loot.Locations.Lighthouse.Loose; + locs.looseLootMultiplier.tarkovstreets = Config.Loot.Locations.Streets.Loose; + locs.looseLootMultiplier.sandbox = Config.Loot.Locations.Sandbox.Loose; + locs.looseLootMultiplier.sandbox_high = Config.Loot.Locations.SandboxHard.Loose; + //container loot mults + locs.staticLootMultiplier.bigmap = Config.Loot.Locations.Bigmap.Container; + locs.staticLootMultiplier.factory4_day = Config.Loot.Locations.FactoryDay.Container; + locs.staticLootMultiplier.factory4_night = Config.Loot.Locations.FactoryNight.Container; + locs.staticLootMultiplier.interchange = Config.Loot.Locations.Interchange.Container; + locs.staticLootMultiplier.laboratory = Config.Loot.Locations.Laboratory.Container; + locs.staticLootMultiplier.rezervbase = Config.Loot.Locations.Reserve.Container; + locs.staticLootMultiplier.shoreline = Config.Loot.Locations.Shoreline.Container; + locs.staticLootMultiplier.woods = Config.Loot.Locations.Woods.Container; + locs.staticLootMultiplier.lighthouse = Config.Loot.Locations.Lighthouse.Container; + locs.staticLootMultiplier.tarkovstreets = Config.Loot.Locations.Streets.Container; + locs.staticLootMultiplier.sandbox = Config.Loot.Locations.Sandbox.Container; + locs.staticLootMultiplier.sandbox_high = Config.Loot.Locations.SandboxHard.Container; + locs.containerRandomisationSettings.enabled = !Config.Loot.Locations.AllContainers + //############## AIRDROPS SECTION ################## + locations["bigmap"].base.AirdropParameters[0].PlaneAirdropChance = parseFloat((Config.Loot.Airdrops.Bigmap_air / 100).toFixed(2)); + locations["shoreline"].base.AirdropParameters[0].PlaneAirdropChance = parseFloat((Config.Loot.Airdrops.Shoreline_air / 100).toFixed(2)); + locations["rezervbase"].base.AirdropParameters[0].PlaneAirdropChance = parseFloat((Config.Loot.Airdrops.Reserve_air / 100).toFixed(2)); + locations["lighthouse"].base.AirdropParameters[0].PlaneAirdropChance = parseFloat((Config.Loot.Airdrops.Lighthouse_air / 100).toFixed(2)); + locations["interchange"].base.AirdropParameters[0].PlaneAirdropChance = parseFloat((Config.Loot.Airdrops.Interchange_air / 100).toFixed(2)); + locations["tarkovstreets"].base.AirdropParameters[0].PlaneAirdropChance = parseFloat((Config.Loot.Airdrops.Streets_air / 100).toFixed(2)); + locations["sandbox"].base.AirdropParameters[0].PlaneAirdropChance = parseFloat((Config.Loot.Airdrops.Sandbox_air / 100).toFixed(2)); + locations["sandbox_high"].base.AirdropParameters[0].PlaneAirdropChance = parseFloat((Config.Loot.Airdrops.Sandbox_air / 100).toFixed(2)); + locations["woods"].base.AirdropParameters[0].PlaneAirdropChance = parseFloat((Config.Loot.Airdrops.Woods_air / 100).toFixed(2)); + for (let timers in locations) { + if (timers != "develop" && timers != "base" && timers != "privatearea" && timers != "terminal" && timers != "factory4_day" && timers != "hideout" && timers != "laboratory" && timers != "factory4_night" && timers != "town" && timers != "suburbs") {// 3.10 need to rework. + locations[timers].base.AirdropParameters[0].PlaneAirdropStartMin = Config.Loot.Airdrops.AirtimeMin * 60; + locations[timers].base.AirdropParameters[0].PlaneAirdropStartMax = Config.Loot.Airdrops.AirtimeMax * 60; + } + } + let Mixed = Config.Loot.Airdrops.Mixed + let Weapon = Config.Loot.Airdrops.Weapon + let Barter = Config.Loot.Airdrops.Barter + let Medical = Config.Loot.Airdrops.Medical + AirdropContents("mixed", Mixed) + AirdropContents("weaponArmor", Weapon) + AirdropContents("barter", Barter) + AirdropContents("foodMedical", Medical) + } + //############## BOTS SECTION ################# + if (Config.Bots.EnableBots) { + for (let i in locations) { + if (i !== "base" && locations[i].base.BossLocationSpawn) { + for (let x in locations[i].base.BossLocationSpawn) { + switch (locations[i].base.BossLocationSpawn[x].BossName) { + case "bossBoar": + locations[i].base.BossLocationSpawn[x].BossChance = Config.Bots.AIChance.Kaban + break; + case "bossKolontay": + if (i == "sandbox_high") { + locations[i].base.BossLocationSpawn[x].BossChance = Config.Bots.AIChance.KolontayGZ + } + if (i == "tarkovstreets") { + locations[i].base.BossLocationSpawn[x].BossChance = Config.Bots.AIChance.KolontayStreets + } + break; + case "bossPartisan": + // if (i == "bigmap") { Controlled by trigger, ignored for now. + // locations[i].base.BossLocationSpawn[x].BossChance = Config.Bots.AIChance.PartisanCustoms + // } + if (i == "shoreline") { + locations[i].base.BossLocationSpawn[x].BossChance = Config.Bots.AIChance.PartisanShoreline + } + if (i == "lighthouse") { + locations[i].base.BossLocationSpawn[x].BossChance = Config.Bots.AIChance.PartisanLighthouse + } + if (i == "woods") { + locations[i].base.BossLocationSpawn[x].BossChance = Config.Bots.AIChance.PartisanWoods + } + break; + case "bossBully": + locations[i].base.BossLocationSpawn[x].BossChance = Config.Bots.AIChance.Reshala + break; + case "bossSanitar": + locations[i].base.BossLocationSpawn[x].BossChance = Config.Bots.AIChance.Sanitar + break; + case "bossKilla": + if (i == "interchange") { + locations[i].base.BossLocationSpawn[x].BossChance = Config.Bots.AIChance.Killa + } + break; + case "bossTagilla": + if (i == "factory4_day") { + locations[i].base.BossLocationSpawn[x].BossChance = Config.Bots.AIChance.Tagilla + } + if (i == "factory4_night") { + locations[i].base.BossLocationSpawn[x].BossChance = Config.Bots.AIChance.TagillaNight + } + break; + case "bossGluhar": + locations[i].base.BossLocationSpawn[x].BossChance = Config.Bots.AIChance.Glukhar + break; + case "bossKojaniy": + locations[i].base.BossLocationSpawn[x].BossChance = Config.Bots.AIChance.Shturman + break; + case "bossZryachiy": + locations[i].base.BossLocationSpawn[x].BossChance = Config.Bots.AIChance.Zryachiy + break; + case "exUsec": + locations[i].base.BossLocationSpawn[x].BossChance = Config.Bots.AIChance.Rogue + break; + case "bossKnight": + if (i == "woods") { + locations[i].base.BossLocationSpawn[x].BossChance = Config.Bots.AIChance.TrioWoods + } + if (i == "shoreline") { + locations[i].base.BossLocationSpawn[x].BossChance = Config.Bots.AIChance.TrioShoreline + } + if (i == "bigmap") { + locations[i].base.BossLocationSpawn[x].BossChance = Config.Bots.AIChance.Trio + } + if (i == "lighthouse") { + locations[i].base.BossLocationSpawn[x].BossChance = Config.Bots.AIChance.TrioLighthouse + } + break; + case "pmcBot": + if (i == "laboratory") { + locations[i].base.BossLocationSpawn[x].BossChance = Config.Bots.AIChance.RaiderLab + } + if (i == "rezervbase") { + locations[i].base.BossLocationSpawn[x].BossChance = Config.Bots.AIChance.RaiderReserve + } + break; + case "sectantPriest": + if (i == "factory4_night") { + locations[i].base.BossLocationSpawn[x].BossChance = Config.Bots.AIChance.CultistFactory + } + if (i == "woods") { + + locations[i].base.BossLocationSpawn[x].BossChance = Config.Bots.AIChance.CultistWoods + } + if (i == "bigmap") { + locations[i].base.BossLocationSpawn[x].BossChance = Config.Bots.AIChance.CultistCustoms + } + if (i == "shoreline") { + locations[i].base.BossLocationSpawn[x].BossChance = Config.Bots.AIChance.CultistShoreline + } + break; + } + } + } + } + const WepDur = Config.Bots.WeaponDurab; + const ArmorDur = Config.Bots.ArmorDurab; + const BotWepMinID = [WepDur.ScavMin, WepDur.MarksmanMin, WepDur.RaiderMin, WepDur.RogueMin, WepDur.PMCMin, WepDur.BossMin, WepDur.FollowerMin]; + const BotWepMaxID = [WepDur.ScavMax, WepDur.MarksmanMax, WepDur.RaiderMax, WepDur.RogueMax, WepDur.PMCMax, WepDur.BossMax, WepDur.FollowerMax]; + const BotArmorMinID = [ArmorDur.ScavMin, ArmorDur.MarksmanMin, ArmorDur.RaiderMin, ArmorDur.RogueMin, ArmorDur.PMCMin, ArmorDur.BossMin, ArmorDur.FollowerMin]; + const BotArmorMaxID = [ArmorDur.ScavMax, ArmorDur.MarksmanMax, ArmorDur.RaiderMax, ArmorDur.RogueMax, ArmorDur.PMCMax, ArmorDur.BossMax, ArmorDur.FollowerMax]; + + const BotTypeID = ["assault", "marksman", "pmcbot", "exusec", "pmc", "boss", "follower"] + for (let durab in BotTypeID) { + Bots.durability[BotTypeID[durab]].weapon.lowestMax = BotWepMinID[durab]; + Bots.durability[BotTypeID[durab]].weapon.highestMax = BotWepMaxID[durab]; + Bots.durability[BotTypeID[durab]].armor.maxDelta = 100 - BotArmorMinID[durab]; + Bots.durability[BotTypeID[durab]].armor.minDelta = 100 - BotArmorMaxID[durab]; + switch (BotTypeID[durab]) { + case "assault": + Bots.durability["cursedassault"].weapon.lowestMax = BotWepMinID[durab] + Bots.durability["cursedassault"].weapon.highestMax = BotWepMaxID[durab] + Bots.durability["cursedassault"].armor.maxDelta = 100 - BotArmorMinID[durab]; + Bots.durability["cursedassault"].armor.minDelta = 100 - BotArmorMaxID[durab]; + + Bots.durability["crazyassaultevent"].weapon.lowestMax = BotWepMinID[durab] + Bots.durability["crazyassaultevent"].weapon.highestMax = BotWepMaxID[durab] + Bots.durability["crazyassaultevent"].armor.maxDelta = 100 - BotArmorMinID[durab]; + Bots.durability["crazyassaultevent"].armor.minDelta = 100 - BotArmorMaxID[durab]; + break; + case "pmcbot": + Bots.durability["arenafighterevent"].weapon.lowestMax = BotWepMinID[durab] + Bots.durability["arenafighterevent"].weapon.highestMax = BotWepMaxID[durab] + Bots.durability["arenafighterevent"].armor.maxDelta = 100 - BotArmorMinID[durab]; + Bots.durability["arenafighterevent"].armor.minDelta = 100 - BotArmorMaxID[durab]; + break + case "boss": + Bots.durability["sectantpriest"].weapon.lowestMax = BotWepMinID[durab]; + Bots.durability["sectantpriest"].weapon.highestMax = BotWepMaxID[durab]; + Bots.durability["sectantpriest"].armor.maxDelta = 100 - BotArmorMinID[durab]; + Bots.durability["sectantpriest"].armor.minDelta = 100 - BotArmorMaxID[durab]; + break; + case "follower": + Bots.durability["sectantwarrior"].weapon.lowestMax = BotWepMinID[durab]; + Bots.durability["sectantwarrior"].weapon.highestMax = BotWepMaxID[durab]; + Bots.durability["sectantwarrior"].armor.maxDelta = 100 - BotArmorMinID[durab]; + Bots.durability["sectantwarrior"].armor.minDelta = 100 - BotArmorMaxID[durab]; + break; + } + } + } + //############## INSURANCE/REPAIR SECTION ############ + if (Config.Services.EnableServices) { + //Repair.priceMultiplier = Config.Insurance.RepairBox.RepairMult; Disabled due to visual bug - it doesn't show converted number, the function itself is working tho + Repair.armorKitSkillPointGainPerRepairPointMultiplier = Config.Services.RepairBox.ArmorSkillMult; + Repair.weaponTreatment.pointGainMultiplier = Config.Services.RepairBox.WeaponMaintenanceSkillMult; + Repair.repairKitIntellectGainMultiplier.weapon = Config.Services.RepairBox.IntellectSkillMultWeaponKit; + Repair.repairKitIntellectGainMultiplier.armor = Config.Services.RepairBox.IntellectSkillMultArmorKit; + Repair.maxIntellectGainPerRepair.kit = Config.Services.RepairBox.IntellectSkillLimitKit; + Repair.maxIntellectGainPerRepair.trader = Config.Services.RepairBox.IntellectSkillLimitTraders; + Repair.applyRandomizeDurabilityLoss = !Config.Services.RepairBox.NoRandomRepair; + if (Config.Services.EnableInsurance) { + Insurance.returnChancePercent["54cb50c76803fa8b248b4571"] = Config.Services.ReturnChancePrapor; + Insurance.returnChancePercent["54cb57776803fa99248b456e"] = Config.Services.ReturnChanceTherapist; + traders["54cb50c76803fa8b248b4571"].base.insurance.max_storage_time = Config.Services.PraporStorageTime; + traders["54cb57776803fa99248b456e"].base.insurance.max_storage_time = Config.Services.TherapistStorageTime; + traders["54cb50c76803fa8b248b4571"].base.insurance.min_return_hour = Config.Services.Prapor_Min; + traders["54cb50c76803fa8b248b4571"].base.insurance.max_return_hour = Config.Services.Prapor_Max; + traders["54cb57776803fa99248b456e"].base.insurance.min_return_hour = Config.Services.Therapist_Min; + traders["54cb57776803fa99248b456e"].base.insurance.max_return_hour = Config.Services.Therapist_Max; + Insurance.chanceNoAttachmentsTakenPercent = Config.Services.InsuranceAttachmentChance + //3.9.0 insurance fix + new fields + Insurance.runIntervalSeconds = Config.Services.InsuranceInterval + if (Config.Services.EnableTimeOverride) { + Insurance.returnTimeOverrideSeconds = Config.Services.InsuranceTimeOverride + } + let TherapistMult = [Config.Services.InsuranceMultTherapistLvl1, Config.Services.InsuranceMultTherapistLvl2, Config.Services.InsuranceMultTherapistLvl3, Config.Services.InsuranceMultTherapistLvl4] + for (let level in traders["54cb57776803fa99248b456e"].base.loyaltyLevels) { + traders["54cb57776803fa99248b456e"].base.loyaltyLevels[level].insurance_price_coef = TherapistMult[level] + } + let PraporMult = [Config.Services.InsuranceMultPraporLvl1, Config.Services.InsuranceMultPraporLvl2, Config.Services.InsuranceMultPraporLvl3, Config.Services.InsuranceMultPraporLvl4] + for (let level in traders["54cb50c76803fa8b248b4571"].base.loyaltyLevels) { + traders["54cb50c76803fa8b248b4571"].base.loyaltyLevels[level].insurance_price_coef = PraporMult[level] + } + } + //Enable all clothes available for both side + if (Config.Services.ClothesAnySide) { + for (let suit in suits) { + let suitData = suits[suit] + if (suitData._parent === "5cd944ca1388ce03a44dc2a4" || suitData._parent === "5cd944d01388ce000a659df9") { + suitData._props.Side = ["Bear", "Usec"]; + } + } + } + if (Config.Services.ClothesFree || Config.Services.ClothesLevelUnlock) { + for (let tradercloth in traders) { + if (traders[tradercloth].suits) { + for (let file in traders[tradercloth].suits) { + let fileData = traders[tradercloth].suits[file] + if (Config.Services.ClothesLevelUnlock) { + fileData.requirements.loyaltyLevel = 1; + fileData.requirements.profileLevel = 1; + fileData.requirements.standing = 0; + fileData.requirements.questRequirements = [];//Only adik hits this + } + //fileData.requirements.skillRequirements = [];//This is useless, it always stands for empty + if (Config.Services.ClothesFree) { + fileData.requirements.itemRequirements = []; + } + } + } + } + } + if (Config.Services.EnableHealMarkup) { + let TherapistLevels = [Config.Services.TherapistLvl1, Config.Services.TherapistLvl2, Config.Services.TherapistLvl3, Config.Services.TherapistLvl4] + for (let level in traders["54cb57776803fa99248b456e"].base.loyaltyLevels) { + traders["54cb57776803fa99248b456e"].base.loyaltyLevels[level].heal_price_coef = TherapistLevels[level] * 100 + } + globals.Health.HealPrice.TrialLevels = Config.Services.FreeHealLvl + globals.Health.HealPrice.TrialRaids = Config.Services.FreeHealRaids + } + if (Config.Services.EnableRepair) { + for (let CurTrader in traders) { + if (CurTrader !== "ragfair" && (CurTrader == "5a7c2eca46aef81a7ca2145d" || CurTrader == "5ac3b934156ae10c4430e83c" || CurTrader == "5c0647fdd443bc2504c2d371" || CurTrader == "54cb50c76803fa8b248b4571" || CurTrader == "54cb57776803fa99248b456e" || CurTrader == "579dc571d53a0658a154fbec" || CurTrader == "5935c25fb3acc3127c3d8cd9" || CurTrader == "58330581ace78e27b8b10cee")) { + for (let level in traders[CurTrader].base.loyaltyLevels) { + traders[CurTrader].base.loyaltyLevels[level].repair_price_coef *= Config.Services.RepairBox.RepairMult; + } + } + } + if (Config.Services.RepairBox.OpArmorRepair) { + for (let armormats in globals.ArmorMaterials) { + globals.ArmorMaterials[armormats].MaxRepairDegradation = 0 + globals.ArmorMaterials[armormats].MinRepairDegradation = 0 + globals.ArmorMaterials[armormats].MaxRepairKitDegradation = 0 + globals.ArmorMaterials[armormats].MinRepairKitDegradation = 0 + } + } + if (Config.Services.RepairBox.OpGunRepair) { + for (let stuff in items) { + if (items[stuff]._props.MaxRepairDegradation !== undefined && items[stuff]._props.MaxRepairKitDegradation !== undefined) { + EditSimpleItemData(stuff, "MinRepairDegradation", 0); + EditSimpleItemData(stuff, "MaxRepairDegradation", 0); + EditSimpleItemData(stuff, "MinRepairKitDegradation", 0); + EditSimpleItemData(stuff, "MaxRepairKitDegradation", 0); + } + } + } + } + } + //############## CSM SECTION ################## + if (Config.CSM.EnableCSM) { + if (Config.CSM.CustomPocket) { + const JsonUtil = container.resolve("JsonUtil"); + let CustomPocketItem = JsonUtil.clone(items["627a4e6b255f7527fb05a0f6"]) + let PocketSize = Config.CSM.Pockets + CustomPocketItem._id = "a8edfb0bce53d103d3f62b9b"; + for (let cell in CustomPocketItem._props.Grids)//tried to make less code, made more, smh. + { + CustomPocketItem._props.Grids[cell]._parent = "a8edfb0bce53d103d3f62b9b" + } + for (let cell in CustomPocketItem._props.Slots) { + CustomPocketItem._props.Slots[cell]._parent = "a8edfb0bce53d103d3f62b9b" + } + CustomPocketItem._props.Grids[0]._id = "a8edfb0bce53d103d3f62b0b" + CustomPocketItem._props.Grids[0]._props.cellsH = PocketSize.FirstWidth + CustomPocketItem._props.Grids[0]._props.cellsV = PocketSize.FirstHeight + CustomPocketItem._props.Grids[1]._id = "a8edfb0bce53d103d3f62b1b" + CustomPocketItem._props.Grids[1]._props.cellsH = PocketSize.SecondWidth + CustomPocketItem._props.Grids[1]._props.cellsV = PocketSize.SecondHeight + CustomPocketItem._props.Grids[2]._id = "a8edfb0bce53d103d3f62b2b" + CustomPocketItem._props.Grids[2]._props.cellsH = PocketSize.ThirdWidth + CustomPocketItem._props.Grids[2]._props.cellsV = PocketSize.ThirdHeight + CustomPocketItem._props.Grids[3]._id = "a8edfb0bce53d103d3f62b3b" + CustomPocketItem._props.Grids[3]._props.cellsH = PocketSize.FourthWidth + CustomPocketItem._props.Grids[3]._props.cellsV = PocketSize.FourthHeight + CustomPocketItem._props.Slots[0]._id = "a8edfb0bce53d103d3f62b4b" + CustomPocketItem._props.Slots[1]._id = "a8edfb0bce53d103d3f62b5b" + CustomPocketItem._props.Slots[2]._id = "a8edfb0bce53d103d3f62b6b" + if (PocketSize.FourthWidth == 0 || PocketSize.FourthHeight == 0) { + CustomPocketItem._props.Grids.splice(3, 1); + } + if (PocketSize.ThirdWidth == 0 || PocketSize.ThirdHeight == 0) { + CustomPocketItem._props.Grids.splice(2, 1); + } + if (PocketSize.SecondWidth == 0 || PocketSize.SecondHeight == 0) { + CustomPocketItem._props.Grids.splice(1, 1); + } + if (PocketSize.FirstWidth == 0 || PocketSize.FirstHeight == 0) { + CustomPocketItem._props.Grids.splice(0, 1); + } + + switch (true) { + case Config.CSM.Pockets.SpecSlots == 0: + CustomPocketItem._props.Slots.splice(0, 3); + break; + case Config.CSM.Pockets.SpecSlots == 1: + CustomPocketItem._props.Slots.splice(1, 2); + break; + case Config.CSM.Pockets.SpecSlots == 2: + CustomPocketItem._props.Slots.splice(2, 1); + break; + case Config.CSM.Pockets.SpecSlots == 3: + break; + case Config.CSM.Pockets.SpecSlots >= 4://Graduality done, switched `switch` to true statement and expressions. + CustomPocketItem._props.Slots[3] = JsonUtil.clone(CustomPocketItem._props.Slots[2]) + CustomPocketItem._props.Slots[3]._id = "a8edfb0bce53d103d3f62b7b" + CustomPocketItem._props.Slots[3]._name = "SpecialSlot4" + CustomPocketItem._props.Slots[3]._parent = "a8edfb0bce53d103d3f62b9b" + Insurance.blacklistedEquipment.push("SpecialSlot4") + case Config.CSM.Pockets.SpecSlots == 5: + CustomPocketItem._props.Slots[4] = JsonUtil.clone(CustomPocketItem._props.Slots[2]) + CustomPocketItem._props.Slots[4]._id = "a8edfb0bce53d103d3f62b8b" + CustomPocketItem._props.Slots[4]._name = "SpecialSlot5" + CustomPocketItem._props.Slots[4]._parent = "a8edfb0bce53d103d3f62b9b" + Insurance.blacklistedEquipment.push("SpecialSlot5") + break; + } + //This is a solution to avoid removing cases from bodies if they die. + let IDsToFilter = ["5783c43d2459774bbe137486", "60b0f6c058e0b0481a09ad11", "619cbf9e0a7c3a1a2731940a", "619cbf7d23893217ec30b689", "59fafd4b86f7745ca07e1232", "62a09d3bcf4a99369e262447"]; + let Pockets = Config.CSM.Pockets + let CasesToFilter = [Pockets.SpecSimpleWallet, Pockets.SpecWZWallet, Pockets.SpecKeycardHolder, Pockets.SpecInjectorCase, Pockets.SpecKeytool, Pockets.SpecGKeychain]; + for (let ID in IDsToFilter) { + items[IDsToFilter[ID]]._props.DiscardLimit = -1; + items[IDsToFilter[ID]]._props.InsuranceDisabled = true; + } + for (let specialslots in CustomPocketItem._props.Slots) { + for (let element in IDsToFilter) { + if (CasesToFilter[element]) { + CustomPocketItem._props.Slots[specialslots]._props.filters[0].Filter.push(IDsToFilter[element]) + } + } + //items[IDsToFilter[specialslots]]._props.HideEntrails = true; + } + items["a8edfb0bce53d103d3f62b9b"] = CustomPocketItem; + //items["5795f317245977243854e041"]._props.HideEntrails = true; Still unsure what does it do + } + if (Config.CSM.EnableSecureCases) { + const SecCon = Config.CSM.SecureContainers + + const SecHeight = [ + SecCon.AlphaHeight, + SecCon.KappaHeight, + SecCon.BetaHeight, + SecCon.EpsilonHeight, + SecCon.GammaHeight, + SecCon.GammaTUEHeight, + SecCon.WaistPouchHeight, + SecCon.DevHeight + ]; + const SecWidth = [ + SecCon.AlphaWidth, + SecCon.KappaWidth, + SecCon.BetaWidth, + SecCon.EpsilonWidth, + SecCon.GammaWidth, + SecCon.GammaTUEWidth, + SecCon.WaistPouchWidth, + SecCon.DevWidth + ]; + for (let SecConts in Arrays.SecConID) { + items[Arrays.SecConID[SecConts]]._props.Grids[0]._props["cellsV"] = SecHeight[SecConts]; + items[Arrays.SecConID[SecConts]]._props.Grids[0]._props["cellsH"] = SecWidth[SecConts]; + } + } + if (Config.CSM.EnableCases) { + const Cases = Config.CSM.Cases + const Size = [ + Cases.MoneyCase, + Cases.SimpleWallet, + Cases.WZWallet, + Cases.GrenadeCase, + Cases.ItemsCase, + Cases.WeaponCase, + Cases.LuckyScav, + Cases.AmmunitionCase, + Cases.MagazineCase, + Cases.DogtagCase, + Cases.MedicineCase, + Cases.ThiccItemsCase, + Cases.ThiccWeaponCase, + Cases.SiccCase, + Cases.Keytool, + Cases.DocumentsCase, + Cases.PistolCase, + Cases.Holodilnick, + Cases.InjectorCase, + Cases.KeycardHolderCase, + Cases.GKeychain + ] + const Filts = [ + Cases.MoneyCase.Filter, + Cases.SimpleWallet.Filter, + Cases.WZWallet.Filter, + Cases.GrenadeCase.Filter, + Cases.ItemsCase.Filter, + Cases.WeaponCase.Filter, + Cases.LuckyScav.Filter, + Cases.AmmunitionCase.Filter, + Cases.MagazineCase.Filter, + Cases.DogtagCase.Filter, + Cases.MedicineCase.Filter, + Cases.ThiccItemsCase.Filter, + Cases.ThiccWeaponCase.Filter, + Cases.SiccCase.Filter, + Cases.Keytool.Filter, + Cases.DocumentsCase.Filter, + Cases.PistolCase.Filter, + Cases.Holodilnick.Filter, + Cases.InjectorCase.Filter, + Cases.KeycardHolderCase.Filter, + Cases.GKeychain.Filter + ] + for (let Case in Arrays.CasesID) { + items[Arrays.CasesID[Case]]._props.Grids[0]._props["cellsV"] = Size[Case].Height; + items[Arrays.CasesID[Case]]._props.Grids[0]._props["cellsH"] = Size[Case].Width; + } + //Filters + for (let Filters in Filts) { + if (Filts[Filters]) // To check whether checkmark is true or false + { + items[Arrays.CasesID[Filters]]._props.Grids[0]._props.filters = []; + } + } + } + } + //############## ITEMS SECTION ################ + if (Config.Items.EnableItems) { + + //Price Modifier + for (const item in DB.templates.handbook.Items) { + if (DB.templates.handbook.Items[item].ParentId !== "5b5f78b786f77447ed5636af" && DB.templates.handbook.Items[item].Price != null) { + DB.templates.handbook.Items[item].Price = (DB.templates.handbook.Items[item].Price * Config.Items.ItemPriceMult) + } + } + //Loading-Unloading rounds in a magazine + globals.BaseUnloadTime = globals.BaseUnloadTime * Config.Items.AmmoLoadSpeed; + globals.BaseLoadTime = globals.BaseLoadTime * Config.Items.AmmoLoadSpeed; + //Signal Pistol into Special slots + if (Config.Items.AddSignalPistolToSpec) { + if (items["a8edfb0bce53d103d3f62b9b"] !== undefined) { + for (let specialslots in items["a8edfb0bce53d103d3f62b9b"]._props.Slots) { + items["a8edfb0bce53d103d3f62b9b"]._props.Slots[specialslots]._props.filters[0].Filter.push("620109578d82e67e7911abf2") + } + } + if (items["627a4e6b255f7527fb05a0f6"] !== undefined) { + for (let specialslots in items["627a4e6b255f7527fb05a0f6"]._props.Slots) { + items["627a4e6b255f7527fb05a0f6"]._props.Slots[specialslots]._props.filters[0].Filter.push("620109578d82e67e7911abf2") + } + } + if (items["65e080be269cbd5c5005e529"] !== undefined) { + for (let specialslots in items["65e080be269cbd5c5005e529"]._props.Slots) { + items["65e080be269cbd5c5005e529"]._props.Slots[specialslots]._props.filters[0].Filter.push("620109578d82e67e7911abf2") + } + } + } + for (const id in items) { + let base = items[id] + //Examining time + if (base._type == "Item" && base._props.ExamineTime !== undefined) { + EditSimpleItemData(id, "ExamineTime", Config.Items.ExamineTime); + } + //Fragmentation Multiplier + if (base._props.FragmentationChance !== undefined) { + EditSimpleItemData(id, "FragmentationChance", parseFloat(base._props.FragmentationChance * Config.Items.FragmentMult).toFixed(2)); + } + //Heat Factor Multiplier + if (base._props.HeatFactor !== undefined) { + EditSimpleItemData(id, "HeatFactor", parseFloat(base._props.HeatFactor * Config.Items.HeatFactor).toFixed(4)); + } + //Dropping items in raid rather deleting them + if (base._type == "Item" && base._props.DiscardLimit !== undefined && Config.Items.RaidDrop) { + EditSimpleItemData(id, "DiscardLimit", -1); + } + //Turns off weapon overheat + if (base._props.AllowOverheat !== undefined && Config.Items.WeaponHeatOff) { + EditSimpleItemData(id, "AllowOverheat", false); + } + //Malfunction chance + if ((base._parent == "5447b5cf4bdc2d65278b4567" || base._parent == "5447b6254bdc2dc3278b4568" || items[id]._parent == "5447b5f14bdc2d61278b4567" || items[id]._parent == "5447bed64bdc2d97278b4568" || items[id]._parent == "5447b6094bdc2dc3278b4567" || items[id]._parent == "5447b5e04bdc2d62278b4567" || items[id]._parent == "5447b6194bdc2d67278b4567") && items[id]._props.BaseMalfunctionChance !== undefined) { + EditSimpleItemData(id, "BaseMalfunctionChance", parseFloat(base._props.BaseMalfunctionChance * Config.Items.MalfunctChanceMult).toFixed(6)); + } + if (base._parent == "5448bc234bdc2d3c308b4569" && base._props.MalfunctionChance !== undefined) { + EditSimpleItemData(id, "MalfunctionChance", parseFloat(base._props.MalfunctionChance * Config.Items.MalfunctChanceMult).toFixed(2)); + } + //Misfire chance + if (base._parent == "5485a8684bdc2da71d8b4567" && base._props.MalfMisfireChance !== undefined) { + EditSimpleItemData(id, "MalfMisfireChance", parseFloat(base._props.MalfMisfireChance * Config.Items.MisfireChance).toFixed(3)); + } + //Examine all items + if (Config.Items.AllExaminedItems && Config.Items.ExamineKeys) { + EditSimpleItemData(id, "ExaminedByDefault", true); + } + //Examine all items EXCEPT KEYS, checking for parent IDs of mechanical, keycards and keys in general just in case. + else if (Config.Items.AllExaminedItems && base._parent !== "5c99f98d86f7745c314214b3" && base.parent !== "5c164d2286f774194c5e69fa" && base.parent !== "543be5e94bdc2df1348b4568") { + EditSimpleItemData(id, "ExaminedByDefault", true); + } + //Change the weight + if (base._type !== "Node" && base._type !== undefined && (base.parent !== "557596e64bdc2dc2118b4571" || base._parent !== "55d720f24bdc2d88028b456d")) { + EditSimpleItemData(id, "Weight", parseFloat(Config.Items.WeightChanger * base._props.Weight).toFixed(3)); + } + if (Config.Items.NoGearPenalty) { + if (base._props.mousePenalty) { + EditSimpleItemData(id, "mousePenalty", 0) + } + if (base._props.weaponErgonomicPenalty) { + EditSimpleItemData(id, "weaponErgonomicPenalty", 0) + } + if (base._props.speedPenaltyPercent) { + EditSimpleItemData(id, "speedPenaltyPercent", 0) + } + } + //Ammo Stacks + if (base._parent.includes("5485a8684bdc2da71d8b4567") && Config.Items.AmmoSwitch) { + let str = base._name//.split("_", 2) + if (AmmoFilter(Arrays.Pistol, str)) { + EditSimpleItemData(id, "StackMaxSize", Config.Items.AmmoStacks.PistolRound) + } + else if (AmmoFilter(Arrays.Shotgun, str)) { + EditSimpleItemData(id, "StackMaxSize", Config.Items.AmmoStacks.ShotgunRound) + } + else if (AmmoFilter(Arrays.ARifle, str)) { + EditSimpleItemData(id, "StackMaxSize", Config.Items.AmmoStacks.RifleRound) + } + else if (AmmoFilter(Arrays.MRifle, str)) { + EditSimpleItemData(id, "StackMaxSize", Config.Items.AmmoStacks.MarksmanRound) + } + } + //Change money stacks + if (base._parent == "543be5dd4bdc2deb348b4569" && base._props.StackMaxSize !== undefined && Config.Items.EnableCurrency) { + switch (base._id) { + case "569668774bdc2da2298b4568": + EditSimpleItemData(id, "StackMaxSize", Config.Items.EuroStack); + break; + case "5696686a4bdc2da3298b456a": + EditSimpleItemData(id, "StackMaxSize", Config.Items.DollarStack); + break; + case "5d235b4d86f7742e017bc88a": + EditSimpleItemData(id, "StackMaxSize", Config.Items.GPStack); + break; + default: + EditSimpleItemData(id, "StackMaxSize", Config.Items.RubStack); + break; + } + } + //Allow armored rigs with armors + if (Config.Items.EquipRigsWithArmors && base._props.BlocksArmorVest !== undefined) { + EditSimpleItemData(id, "BlocksArmorVest", false); + } + //Remove filters + if (Config.Items.RemoveSecureContainerFilters && base._parent == "5448bf274bdc2dfc2f8b456a" && base._props.Grids[0]._props.filters !== undefined) { + base._props.Grids[0]._props.filters = []; + } + if (Config.Items.RemoveBackpacksRestrictions && base._parent == "5448e53e4bdc2d60728b4567" && base._props.Grids[0]._props.filters !== undefined) { + base._props.Grids[0]._props.filters = []; + } + //Change items experience gain + if (base._props.LootExperience !== undefined) { + let calculation = Math.round(base._props.LootExperience * Config.Items.LootExp); + EditSimpleItemData(id, "LootExperience", calculation); + } + if (base._props.ExamineExperience !== undefined) { + let calculation = Math.round(base._props.ExamineExperience * Config.Items.ExamineExp); + EditSimpleItemData(id, "ExamineExperience", calculation); + } + //Remove the keys usage - God i hate how i wrote it + if (Config.Items.EnableKeys) { + if ((base._parent == "5c99f98d86f7745c314214b3") && base._props.MaximumNumberOfUsage !== undefined) { + + if (base._parent == "5c99f98d86f7745c314214b3" && base._props.MaximumNumberOfUsage == 1 && !Config.Items.AvoidSingleKeys) { + base._props.MaximumNumberOfUsage = 0 + } + if ( Arrays.MarkedKeys.includes(base._id) && !Config.Items.AvoidMarkedKeys) { + base._props.MaximumNumberOfUsage = 0 + } + if (!(Arrays.MarkedKeys.includes(base._id)) && base._props.MaximumNumberOfUsage !== 1) { + base._props.MaximumNumberOfUsage = 0 + } + } + + if (base._parent == "5c164d2286f774194c5e69fa" && base._props.MaximumNumberOfUsage !== undefined && Config.Items.InfiniteKeycards) { + base._props.MaximumNumberOfUsage = 0 + } + if (base._parent == "5c99f98d86f7745c314214b3" && base._props.MaximumNumberOfUsage != 0) { + base._props.MaximumNumberOfUsage *= Config.Items.KeyUseMult + if (base._props.MaximumNumberOfUsage > Config.Items.KeyDurabilityThreshold) { + base._props.MaximumNumberOfUsage = Config.Items.KeyDurabilityThreshold + } + } + if (base._parent == "5c164d2286f774194c5e69fa" && base._props.MaximumNumberOfUsage != 0) { + base._props.MaximumNumberOfUsage *= Config.Items.KeycardUseMult + if (base._props.MaximumNumberOfUsage > Config.Items.KeyDurabilityThreshold) { + base._props.MaximumNumberOfUsage = Config.Items.KeyDurabilityThreshold + } + } + } + } + if (Config.Items.SMGToHolster) { + items["55d7217a4bdc2d86028b456d"]._props.Slots[2]._props.filters[0].Filter.push("5447b5e04bdc2d62278b4567"); + } + if (Config.Items.PistolToMain) { + items["55d7217a4bdc2d86028b456d"]._props.Slots[0]._props.filters[0].Filter.push("5447b5cf4bdc2d65278b4567", "617f1ef5e8b54b0998387733"); + items["55d7217a4bdc2d86028b456d"]._props.Slots[1]._props.filters[0].Filter.push("5447b5cf4bdc2d65278b4567", "617f1ef5e8b54b0998387733"); + } + if (Config.Items.RemoveRaidRestr) { + globals.RestrictionsInRaid = [] + } + if (Config.Items.IDChanger) { + //Edit item properties, i know it looks stupid, but hey - it works and i like it. + //5th revision, now including separate fields for filters, parents and expressions. + Logger.info("[SVM] Custom Properties is loading", "blue") + try { + if (Config.Items.IDParent.length > 0) { //ID=ParentID, same as above + let ParentList = Config.Items.IDParent.split("\r\n") + let IDArray = []; + for (let Line in ParentList) { + const Variables = ParentList[Line].split(":") + Logger.info("Parent: " + Variables) + for (let ids in items) { + if (Variables[0] == items[ids]._parent) { + IDArray.push(items[ids]._id); + } + } + Logger.info("Affected by parent: ") + Logger.info(IDArray) + for (let ID in IDArray) { + Variables[0] = IDArray[ID] + IDChanger(Variables) + } + } + } + if (Config.Items.IDDefault.length > 0) {//ID:Variable:Value + let DefaultList = Config.Items.IDDefault.split("\r\n") + for (let Line in DefaultList) { + let Variables = DefaultList[Line].split(":") + Logger.info("Default: " + Variables) + IDChanger(Variables) + } + } + if (Config.Items.IDFilter.length > 0) { //ID:Slots/Grids:Grid/Slot Number:Filter/ExcludedFilter:PushIntoArray + let FilterList = Config.Items.IDFilter.split("\r\n") + for (let Line in FilterList) { + const Variables = FilterList[Line].split(":") + Logger.info("Filter: " + Variables) + if (Variables.length === 5) { + let check = CheckType(Variables[4]) + for (let fields in check) { + items[Variables[0]]._props[Variables[1]][Variables[2]]._props.filters[0][Variables[3]].push(check[fields]) + } + } + else { + Logger.error("[SVM] INVENTORY AND ITEMS - Filters ID - failed to apply\n") + } + } + } + if (Config.Items.IDPrice.length > 0) { //ID:Expression:Number + const handbook = DB.templates.handbook.Items + let IDPriceLines = Config.Items.IDPrice.split("\r\n") + for (let Line in IDPriceLines) { + const Variables = IDPriceLines[Line].split(":") + Logger.info("Price: " + Variables) + let IDChecker = true; + for (let Target in handbook) { + if (handbook[Target].Id.includes(Variables[0])) { + handbook[Target].Price = Calculus(handbook[Target].Price, Variables[1], Variables[2]) + IDChecker = false; + break; + } + } + if (IDChecker) { + Logger.warning("[SVM] INVENTORY AND ITEMS - Price ID - " + Variables[0] + " - This ID is not found in handbook.\nChecking as ParentID") + let childs = [] + for (let ID in items) { + if (items[ID]._parent == Variables[0]) { + childs.push(items[ID]._id) + } + } + if (childs.length > 0) { + Logger.success("[SVM] Success, Changing prices of Child IDs") + Logger.info(childs) + for (let child in childs) { + for (let ID in handbook) { + if (handbook[ID].Id.includes(childs[child])) { + handbook[ID].Price = Calculus(handbook[ID].Price, Variables[1], Variables[2]) + break; + } + } + } + } + else { + Logger.error("[SVM] Price ID Failed, this ID doesn't exist in Items.json") + } + } + } + } + Logger.success("[SVM] Custom properties successfully loaded") + } + catch (e) { + Logger.error("[SVM] INVENTORY AND ITEMS - Custom properties failed to load, error of the code:\n" + e) + } + } + } + //############## PLAYER SECTION ############### + if (Config.Player.EnablePlayer) { + //Skill box + globals.SkillsSettings.SkillProgressRate = Config.Player.SkillProgMult; + globals.SkillsSettings.WeaponSkillProgressRate = Config.Player.WeaponSkillMult; + //health after raid box + Health.healthMultipliers.death = Config.Player.DiedHealth.Health_death; + Health.healthMultipliers.blacked = Config.Player.DiedHealth.Health_blacked; + Health.save.health = Config.Player.DiedHealth.Savehealth; + Health.save.effects = Config.Player.DiedHealth.Saveeffects; + // skill eff box + if (Config.Player.EnableFatigue) { + globals.SkillMinEffectiveness = Config.Player.Skills.SkillMinEffect; + globals.SkillFatiguePerPoint = Config.Player.Skills.SkillFatiguePerPoint; + globals.SkillFreshEffectiveness = Config.Player.Skills.SkillFreshEffect; + globals.SkillFreshPoints = Config.Player.Skills.SkillFPoints; + globals.SkillPointsBeforeFatigue = Config.Player.Skills.SkillPointsBeforeFatigue; + globals.SkillFatigueReset = Config.Player.Skills.SkillFatigueReset; + } + //############## Player level XP box ############## + globals.exp.kill.victimBotLevelExp = Config.Player.CharXP.ScavKill; + globals.exp.kill.victimLevelExp = Config.Player.CharXP.PMCKill; + globals.exp.kill.botHeadShotMult = Config.Player.CharXP.ScavHMult; + globals.exp.kill.pmcHeadShotMult = Config.Player.CharXP.PMCHMult + //############## END OF RAID Box ############## + globals.exp.match_end.runnerMult = Config.Player.RaidMult.Runner + globals.exp.match_end.miaMult = Config.Player.RaidMult.MIA + globals.exp.match_end.survivedMult = Config.Player.RaidMult.Survived + globals.exp.match_end.killedMult = Config.Player.RaidMult.Killed + //Remove fall damage + if (Config.Player.FallDamage) { + globals.Health.Falling.SafeHeight = 200 + globals.Health.Falling.DamagePerMeter = 0 + } + //Change stamina (unlimited or no) + if (Config.Player.MaxStamina !== 100 && !Config.Player.UnlimitedStamina) { + globals.Stamina.Capacity = Config.Player.MaxStamina; + } + else if (Config.Player.UnlimitedStamina) { + globals.Stamina.Capacity = 500; + globals.Stamina.BaseRestorationRate = 500; + globals.Stamina.StaminaExhaustionCausesJiggle = false; + globals.Stamina.StaminaExhaustionStartsBreathSound = false; + globals.Stamina.StaminaExhaustionRocksCamera = false; + globals.Stamina.SprintDrainRate = 0; + globals.Stamina.JumpConsumption = 0; + globals.Stamina.AimDrainRate = 0; + globals.Stamina.SitToStandConsumption = 0; + } + globals.Health.Effects.Existence.HydrationLoopTime = (globals.Health.Effects.Existence.HydrationLoopTime / Config.Player.HydrationLoss) + globals.Health.Effects.Existence.EnergyLoopTime = (globals.Health.Effects.Existence.EnergyLoopTime / Config.Player.EnergyLoss) + globals.Health.Effects.Existence.DestroyedStomachEnergyTimeFactor = Config.Player.BlackStomach; + globals.Health.Effects.Existence.DestroyedStomachHydrationTimeFactor = Config.Player.BlackStomach; + } + //############## HIDEOUT SECTION ############## + if (Config.Hideout.EnableHideout) { + //Change hideout fuel consumption + hideout.settings.generatorFuelFlowRate *= Config.Hideout.FuelConsumptionRate; + hideout.settings.generatorSpeedWithoutFuel *= Config.Hideout.NoFuelMult; + //hideoutC.fuelDrainRateMultipler = Config.Hideout.FuelConsumptionRate; + hideout.settings.airFilterUnitFlowRate *= Config.Hideout.AirFilterRate; + hideout.settings.gpuBoostRate *= Config.Hideout.GPUBoostRate; + + if (Config.Hideout.EnableStash) { + items["566abbc34bdc2d92178b4576"]._props.Grids[0]._props.cellsV = Config.Hideout.Stash.StashLvl1 + items["5811ce572459770cba1a34ea"]._props.Grids[0]._props.cellsV = Config.Hideout.Stash.StashLvl2 + items["5811ce662459770f6f490f32"]._props.Grids[0]._props.cellsV = Config.Hideout.Stash.StashLvl3 + items["5811ce772459770e9e5f9532"]._props.Grids[0]._props.cellsV = Config.Hideout.Stash.StashLvl4 + items["6602bcf19cc643f44a04274b"]._props.Grids[0]._props.cellsV = Config.Hideout.Stash.StashTUE + } + //Enable hideout fast constructions + for (const data in hideout.areas) { + let areaData = hideout.areas[data] + for (const i in areaData.stages) { + if (areaData.stages[i].constructionTime > 0) { + areaData.stages[i].constructionTime = parseInt(areaData.stages[i].constructionTime * Config.Hideout.HideoutConstMult) + if (areaData.stages[i].constructionTime < 1) { + areaData.stages[i].constructionTime = 2 + } + } + } + } + //Enable fast hideout production + for (const data in hideout.production.recipes) { + let productionData = hideout.production.recipes[data]; + + if (productionData._id == "5d5589c1f934db045e6c5492") { + productionData.productionTime = Config.Hideout.WaterFilterTime * 60 + productionData.requirements[1].resource = Config.Hideout.WaterFilterRate + } + if (productionData._id == "5d5c205bd582a50d042a3c0e") { + productionData.productionLimitCount = Config.Hideout.MaxBitcoins; + productionData.productionTime = Config.Hideout.BitcoinTime * 60; + } + if (!productionData.continuous && productionData.productionTime >= 10) { + productionData.productionTime = parseInt(productionData.productionTime * Config.Hideout.HideoutProdMult) + if (productionData.productionTime < 1) { + productionData.productionTime = 2 + } + } + } + //Scav cases modifications + for (const scav in hideout.production.scavRecipes) { + let caseData = hideout.production.scavRecipes[scav]; + if (caseData.productionTime >= 10) { + caseData.productionTime = parseInt(caseData.productionTime * Config.Hideout.ScavCaseTime); + if (caseData.productionTime < 1) { + caseData.productionTime = 2 + } + } + } + for (const scase in hideout.production.scavRecipes) { + let caseData = hideout.production.scavRecipes[scase]; + if (caseData.requirements[0].templateId == "5449016a4bdc2d6f028b456f" || caseData.requirements[0].templateId == "5696686a4bdc2da3298b456a" || caseData.requirements[0].templateId == "569668774bdc2da2298b4568") { + caseData.requirements[0].count = parseInt(caseData.requirements[0].count * Config.Hideout.ScavCasePrice); + } + } + //Remove construction requirements + if (Config.Hideout.RemoveConstructionsRequirements || Config.Hideout.RemoveSkillRequirements || Config.Hideout.RemoveTraderLevelRequirements) { + for (const data in hideout.areas) { + let areaData = hideout.areas[data] + //Logger.info(areaData.stages[1].requirements[1]) + for (const stage in areaData.stages) { + if (areaData.stages[stage].requirements !== undefined && areaData.stages[stage].requirements !== "[]") { + let rewriter = []; + for (let req in areaData.stages[stage].requirements)//This is horrible + { + if (areaData.stages[stage].requirements[req].hasOwnProperty("templateId") && !Config.Hideout.RemoveConstructionsRequirements) { + rewriter.push(areaData.stages[stage].requirements[req]) + } + else if (areaData.stages[stage].requirements[req].hasOwnProperty("skillName") && !Config.Hideout.RemoveSkillRequirements) { + rewriter.push(areaData.stages[stage].requirements[req]) + } + else if (areaData.stages[stage].requirements[req].hasOwnProperty("traderId") && !Config.Hideout.RemoveTraderLevelRequirements) { + rewriter.push(areaData.stages[stage].requirements[req]) + } + else if (areaData.stages[stage].requirements[req].hasOwnProperty("areaType"))//Just for sanity check to avoid certain errors like building bitcoin farm while there is no generator. + { + rewriter.push(areaData.stages[stage].requirements[req]) + } + } + areaData.stages[stage].requirements = rewriter + } + } + } + } + //Hideout regen menu + //3.10 + for (let limb in globals.Health.Effects.Regeneration.BodyHealth) { + globals.Health.Effects.Regeneration.BodyHealth[limb].Value *= Config.Hideout.Regeneration.HealthRegen + } + globals.Health.Effects.Regeneration.Energy = Config.Hideout.Regeneration.EnergyRegen + globals.Health.Effects.Regeneration.Hydration = Config.Hideout.Regeneration.HydrationRegen + + for (const data in hideout.areas) { + let areaData = hideout.areas[data] + for (const i in areaData.stages) { + for (const x in areaData.stages[i].bonuses) { + if (Config.Hideout.Regeneration.HideoutHydration && areaData.stages[i].bonuses[x].type == "HydrationRegeneration") { + areaData.stages[i].bonuses[x].value = 0; + } + if (Config.Hideout.Regeneration.HideoutEnergy && areaData.stages[i].bonuses[x].type == "EnergyRegeneration") { + areaData.stages[i].bonuses[x].value = 0; + } + if (Config.Hideout.Regeneration.HideoutHealth && areaData.stages[i].bonuses[x].type == "HealthRegeneration") { + areaData.stages[i].bonuses[x].value = 0; + } + } + } + } + } + + //############## RAIDS SECTION ################ + if (Config.Raids.EnableRaids) { + //############## INRAID SECTION ################## + if (Config.Raids.RaidStartup.EnableRaidStartup) { + Inraid.MIAOnRaidEnd = Config.Raids.RaidStartup.MIAEndofRaid; + Inraid.raidMenuSettings.aiAmount = Arrays.AIAmount[Config.Raids.RaidStartup.AIAmount]; + Inraid.raidMenuSettings.aiDifficulty = Arrays.AIDifficulty[Config.Raids.RaidStartup.AIDifficulty]; + Inraid.raidMenuSettings.bossEnabled = Config.Raids.RaidStartup.EnableBosses; + Inraid.raidMenuSettings.scavWars = Config.Raids.RaidStartup.ScavWars; + Inraid.raidMenuSettings.taggedAndCursed = Config.Raids.RaidStartup.TaggedAndCursed; + Inraid.save.loot = Config.Raids.RaidStartup.SaveLoot; + } + if (Config.Raids.ForceSeason) { + WeatherValues.overrideSeason = Config.Raids.Season; + } + trader.fence.coopExtractGift.sendGift = !Config.Raids.Exfils.FenceGift; + const Midcore = configServer.getConfig("spt-lostondeath"); + if (Config.Raids.SaveQuestItems) { + Midcore.questItems = false; + } + //Low Ground zero level access + locations["sandbox"].base.RequiredPlayerLevelMax = Config.Raids.SandboxAccessLevel; + //Time acceleration + WeatherValues.acceleration = Config.Raids.Timeacceleration + //Deploy Window time + globals.TimeBeforeDeployLocal = Config.Raids.RaidStartup.TimeBeforeDeployLocal + //Always survived + if (Config.Raids.NoRunThrough) { + globals.exp.match_end.survived_exp_requirement = 0; + globals.exp.match_end.survived_seconds_requirement = 0; + } + DB.locations["laboratory"].base.Insurance = Config.Raids.LabInsurance; + //Remove labs entry keycard + if (Config.Raids.Removelabkey) { + locations["laboratory"].base.AccessKeys = [] + } + + if (Config.Raids.Exfils.ArmorExtract) { + globals.RequirementReferences.Alpinist.splice(2, 1) + } + if (Config.Raids.Exfils.GearExtract) { + globals.RequirementReferences.Alpinist.splice(0, 2) + } + //Remove extracts restrictions + for (let i in locations) { + if (i !== "base") { + let ExitNames = locations[i].base.exits // 3.10 TODO CHECK + for (let x in ExitNames) { + if (ExitNames !== "EXFIL_Train" && (!ExitNames.includes("lab") || ExitNames == "lab_Vent") && ExitNames !== "Saferoom Exfil") {//Ok, i feel dumb again, but i was in a rush ok? + + if (Config.Raids.Exfils.GearExtract && Config.Raids.Exfils.ArmorExtract && locations[i].base.exits[x].PassageRequirement == "Reference") { + FreeExit(locations[i].base.exits[x]) + } + if (Config.Raids.Exfils.NoBackpack && locations[i].base.exits[x].PassageRequirement == "Empty") { + FreeExit(locations[i].base.exits[x]) + } + if (locations[i].base.exits[x].PassageRequirement == "TransferItem" && Config.Raids.EnableCarCoop) { + locations[i].base.exits[x].ExfiltrationTime = Config.Raids.Exfils.CarExtractTime; + switch (i) { + case "woods": + if (Config.Raids.Exfils.CarWoods !== 0) { + locations[i].base.exits[x].Count = Config.Raids.Exfils.CarWoods; + } + else { + FreeExit(locations[i].base.exits[x]) + } + break; + case "interchange": + if (Config.Raids.Exfils.CarInterchange !== 0) { + locations[i].base.exits[x].Count = Config.Raids.Exfils.CarInterchange; + } + else { + FreeExit(locations[i].base.exits[x]) + } + break; + case "bigmap": + if (Config.Raids.Exfils.CarCustoms !== 0) { + locations[i].base.exits[x].Count = Config.Raids.Exfils.CarCustoms; + } + else { + FreeExit(locations[i].base.exits[x]) + } + break; + case "tarkovstreets": + if (Config.Raids.Exfils.CarStreets !== 0) { + locations[i].base.exits[x].Count = Config.Raids.Exfils.CarStreets; + } + else { + FreeExit(locations[i].base.exits[x]) + } + break; + case "lighthouse": + if (Config.Raids.Exfils.CarLighthouse !== 0) { + locations[i].base.exits[x].Count = Config.Raids.Exfils.CarLighthouse; + } + else { + FreeExit(locations[i].base.exits[x]) + } + break; + case "shoreline": + if (Config.Raids.Exfils.CarShoreline !== 0) { + locations[i].base.exits[x].Count = Config.Raids.Exfils.CarShoreline; + } + else { + FreeExit(locations[i].base.exits[x]) + } + break; + case "sandbox": + case "sandbox_high": + if (Config.Raids.Exfils.CarSandbox !== 0) { + locations[i].base.exits[x].Count = Config.Raids.Exfils.CarSandbox; + } + else { + FreeExit(locations[i].base.exits[x]) + } + break; + default: + break; + } + } + if (Config.Raids.Exfils.CoopPaid && Config.Raids.EnableCarCoop && locations[i].base.exits[x].PassageRequirement == "ScavCooperation") { + locations[i].base.exits[x].PassageRequirement = "TransferItem"; + locations[i].base.exits[x].ExfiltrationType = "SharedTimer"; + locations[i].base.exits[x].Id = "5449016a4bdc2d6f028b456f"; + locations[i].base.exits[x].PlayersCount = 0; + locations[i].base.exits[x].RequirementTip = "EXFIL_Item"; + switch (i) { + case "woods": + if (Config.Raids.Exfils.CoopPaidWoods !== 0) { + locations[i].base.exits[x].Count = Config.Raids.Exfils.CoopPaidWoods; + } + else { + FreeExit(locations[i].base.exits[x]) + } + break; + case "tarkovstreets": + if (Config.Raids.Exfils.CoopPaidStreets !== 0) { + locations[i].base.exits[x].Count = Config.Raids.Exfils.CoopPaidStreets; + } + else { + FreeExit(locations[i].base.exits[x]) + } + break; + case "interchange": + if (Config.Raids.Exfils.CoopPaidInterchange !== 0) { + locations[i].base.exits[x].Count = Config.Raids.Exfils.CoopPaidInterchange; + } + else { + FreeExit(locations[i].base.exits[x]) + } + break; + case "lighthouse": + if (Config.Raids.Exfils.CoopPaidLighthouse !== 0) { + locations[i].base.exits[x].Count = Config.Raids.Exfils.CoopPaidLighthouse; + } + else { + FreeExit(locations[i].base.exits[x]) + } + break; + case "rezervbase": + if (Config.Raids.Exfils.CoopPaidReserve !== 0) { + locations[i].base.exits[x].Count = Config.Raids.Exfils.CoopPaidReserve; + } + else { + FreeExit(locations[i].base.exits[x]) + } + break; + case "shoreline": + if (Config.Raids.Exfils.CoopPaidShoreline !== 0) { + locations[i].base.exits[x].Count = Config.Raids.Exfils.CoopPaidShoreline; + } + else { + FreeExit(locations[i].base.exits[x]) + } + break; + case "sandbox": + case "sandbox_high": + if (Config.Raids.Exfils.CoopPaidSandbox !== 0) { + locations[i].base.exits[x].Count = Config.Raids.Exfils.CoopPaidSandbox; + } + else { + FreeExit(locations[i].base.exits[x]) + } + break; + default: + break; + } + } + if (Config.Raids.Exfils.FreeCoop && Config.Raids.EnableCarCoop && locations[i].base.exits[x].PassageRequirement == "ScavCooperation") { + FreeExit(locations[i].base.exits[x]) + } + } + } + } + } + //Make all extractions available to extract + if (Config.Raids.Exfils.ChanceExtracts) { + for (let i in locations) { + if (i !== "base") { + for (let x in locations[i].base.exits) { + if (locations[i].base.exits[x].Name !== "EXFIL_Train") { + locations[i].base.exits[x].Chance = 100; + } + } + } + } + } + //Extend raids time + if (Config.Raids.RaidTime != 0) { + for (let map in locations) { + if (map !== "base") { + if (isJSONValueDefined(locations[map].base.exit_access_time)) { + locations[map].base.exit_access_time += Config.Raids.RaidTime + } + if (isJSONValueDefined(locations[map].base.EscapeTimeLimit)) { + locations[map].base.EscapeTimeLimit += Config.Raids.RaidTime + } + } + } + } + //Make all extractions of the map available regardless of the infill + if (Config.Raids.Exfils.ExtendedExtracts) { + for (let map in locations) { + switch (map) { + case "bigmap": + for (const extract in locations[map].base.exits) { + locations[map].base.exits[extract].EntryPoints = "Customs,Boiler Tanks" + } + break; + case "interchange": + for (const extract in locations[map].base.exits) { + locations[map].base.exits[extract].EntryPoints = "MallSE,MallNW" + } + break; + case "shoreline": + for (const extract in locations[map].base.exits) { + locations[map].base.exits[extract].EntryPoints = "Village,Riverside" + } + break; + case "woods": + for (const extract in locations[map].base.exits) { + locations[map].base.exits[extract].EntryPoints = "House,Old Station" + } + break; + case "lighthouse": + for (const extract in locations[map].base.exits) { + locations[map].base.exits[extract].EntryPoints = "Tunnel,North" + } + break; + case "tarkovstreets": + for (const extract in locations[map].base.exits) { + locations[map].base.exits[extract].EntryPoints = "E1_2,E6_1,E2_3,E3_4,E4_5,E5_6,E6_1" + } + break; + case "sandbox": + case "sandbox_high": + for (const extract in locations[map].base.exits) { + locations[map].base.exits[extract].EntryPoints = "west,east" + } + break; + + default: + break; + } + } + } + Events.events[0].settings.zombieSettings.enabled = !Config.Raids.RaidEvents.DisableZombies + //Explanation of this - Turns out SPT's method doesn't seem to convert upper case to lower case with the maps, while BSG's UI requests exactly uppercased scenario + //In the end we have bigmap and lab only spawning waves because they are consistent on both sides. I hate my life. + if (Config.Raids.RaidEvents.RandomInfectionLevel) { + Events.events[0].settings.zombieSettings.mapInfectionAmount = + { + "laboratory": 100, + "bigmap": Math.floor(Math.random() * 100), + "woods": Math.floor(Math.random() * 100), + "shoreline": Math.floor(Math.random() * 100), + "sandbox": Math.floor(Math.random() * 100), + "rezervbase": Math.floor(Math.random() * 100), + "tarkovstreets": Math.floor(Math.random() * 100), + "factory4": Math.floor(Math.random() * 100), + "lighthouse": Math.floor(Math.random() * 100), + "interchange": Math.floor(Math.random() * 100) + } + //Hopefully a temporary fix + Events.events[0].settings.zombieSettings.mapInfectionAmount["Woods"] = Events.events[0].settings.zombieSettings.mapInfectionAmount["woods"] + Events.events[0].settings.zombieSettings.mapInfectionAmount["Shoreline"] = Events.events[0].settings.zombieSettings.mapInfectionAmount["shoreline"] + Events.events[0].settings.zombieSettings.mapInfectionAmount["RezervBase"] = Events.events[0].settings.zombieSettings.mapInfectionAmount["rezervbase"] + Events.events[0].settings.zombieSettings.mapInfectionAmount["TarkovStreets"] = Events.events[0].settings.zombieSettings.mapInfectionAmount["tarkovstreets"] + Events.events[0].settings.zombieSettings.mapInfectionAmount["Lighthouse"] = Events.events[0].settings.zombieSettings.mapInfectionAmount["lighthouse"] + Events.events[0].settings.zombieSettings.mapInfectionAmount["Interchange"] = Events.events[0].settings.zombieSettings.mapInfectionAmount["interchange"] + for(let map in Events.eventBossSpawns.halloweenzombies) + { + for (let wave in Events.eventBossSpawns.halloweenzombies[map]) + { + switch(map)//Feature - Infection level affects spawn chances. + { + case "factory4_day": + Events.eventBossSpawns.halloweenzombies[map][wave].BossChance = Events.events[0].settings.zombieSettings.mapInfectionAmount.factory4; + break; + case "factory4_night": + Events.eventBossSpawns.halloweenzombies[map][wave].BossChance = Events.events[0].settings.zombieSettings.mapInfectionAmount.factory4; + break; + case "sandbox": + Events.eventBossSpawns.halloweenzombies[map][wave].BossChance = Events.events[0].settings.zombieSettings.mapInfectionAmount.Sandbox; + break; + case "sandbox_high": + Events.eventBossSpawns.halloweenzombies[map][wave].BossChance = Events.events[0].settings.zombieSettings.mapInfectionAmount.Sandbox; + break; + default: + if (Events.events[0].settings.zombieSettings.mapInfectionAmount[map] !== undefined){ + Events.eventBossSpawns.halloweenzombies[map][wave].BossChance = Events.events[0].settings.zombieSettings.mapInfectionAmount[map]; + } + break; + } + } + } + } + Events.enableSeasonalEventDetection = !Config.Raids.RaidEvents.DisableEvents + if (Config.Raids.RaidEvents.RaidersEverywhere) // 3.9.0 Raider rework, need to split them up into 3 fields - Start of the raid Scavs, PMC and general waves. + { + for (let i in locations)//Locations DB + { + if (i !== "base" && locations[i].base.waves) { + for (let x in locations[i].base.waves) { + locations[i].base.waves[x].WildSpawnType = "pmcBot" + } + } + } + for (let loc in locs.customWaves.boss) { + for (let ai in locs.customWaves.boss[loc]) { + locs.customWaves.boss[loc][ai].BossName = "pmcBot"; + locs.customWaves.boss[loc][ai].BossEscortType = "pmcBot"; + } + } + for (let loc in locs.customWaves.normal) { + for (let ai in locs.customWaves.normal[loc]) { + locs.customWaves.normal[loc][ai].WildSpawnType = "pmcBot" + } + } + } + if (Config.Raids.RaidEvents.KillaFactory) { + const KillaWave = CreateBoss("bossKilla", Config.Raids.RaidEvents.KillaFactoryChance, "followerBully", 0, locations["factory4_day"].base.OpenZones) + locations["factory4_day"].base.BossLocationSpawn.push(KillaWave) + locations["factory4_night"].base.BossLocationSpawn.push(KillaWave) + } + if (Config.Raids.RaidEvents.TagillaInterchange) { + for (let bosscheck in locations["interchange"].base.BossLocationSpawn)//Looking for exactly Killa wave, even tho he is the only boss here, safety measure + { + if (locations["interchange"].base.BossLocationSpawn[bosscheck].BossName == "bossKilla") { + locations["interchange"].base.BossLocationSpawn[bosscheck].BossEscortAmount = 1 + locations["interchange"].base.BossLocationSpawn[bosscheck].BossEscortType = "bossTagilla" + } + } + } + const Waves = require('../src/Waves.json'); + if (Config.Raids.RaidEvents.BossesOnReserve) { + let BossWave = CreateBoss("bossKilla", 100, "followerBully", "0", locations["rezervbase"].base.OpenZones) + locations["rezervbase"].base.BossLocationSpawn.push(BossWave) + BossWave = CreateBoss("bossBully", 100, "followerBully", "4", locations["rezervbase"].base.OpenZones) + locations["rezervbase"].base.BossLocationSpawn.push(BossWave) + BossWave = CreateBoss("bossKojaniy", 100, "followerKojaniy", "2", locations["rezervbase"].base.OpenZones) + locations["rezervbase"].base.BossLocationSpawn.push(BossWave) + BossWave = CreateBoss("bossSanitar", 100, "followerSanitar", "2", locations["rezervbase"].base.OpenZones) + locations["rezervbase"].base.BossLocationSpawn.push(BossWave) + BossWave = CreateBoss("bossTagilla", 100, "followerBully", "0", locations["rezervbase"].base.OpenZones) + locations["rezervbase"].base.BossLocationSpawn.push(BossWave) + if (Config.Raids.RaidEvents.IncludeStreetBosses) { + const Kaban = Waves.Kaban + Kaban.BossZone = locations["rezervbase"].base.OpenZones + locations["rezervbase"].base.BossLocationSpawn.push(Kaban) + const Kolontay = Waves.Kolontay + Kaban.BossZone = locations["rezervbase"].base.OpenZones + locations["rezervbase"].base.BossLocationSpawn.push(Kolontay) + } + } + if (Config.Raids.RaidEvents.BossesOnHealthResort) { + if (Config.Raids.RaidEvents.HealthResortIncludeGuards) { + let BossWave = CreateBoss("bossKilla", 100, "followerBully", 0, "ZoneSanatorium1,ZoneSanatorium2") + locations["shoreline"].base.BossLocationSpawn.push(BossWave) + BossWave = CreateBoss("bossBully", 100, "followerBully", 4, "ZoneSanatorium1,ZoneSanatorium2") + locations["shoreline"].base.BossLocationSpawn.push(BossWave) + BossWave = CreateBoss("bossKojaniy", 100, "followerKojaniy", 2, "ZoneSanatorium1,ZoneSanatorium2") + locations["shoreline"].base.BossLocationSpawn.push(BossWave) + BossWave = CreateBoss("bossSanitar", 100, "followerSanitar", 2, "ZoneSanatorium1,ZoneSanatorium2") + locations["shoreline"].base.BossLocationSpawn.push(BossWave) + BossWave = CreateBoss("bossTagilla", 100, "followerBully", 0, "ZoneSanatorium1,ZoneSanatorium2") + locations["shoreline"].base.BossLocationSpawn.push(BossWave) + const Goons = Waves.Goons + Goons.BossZone = "ZoneSanatorium1,ZoneSanatorium2" + locations["shoreline"].base.BossLocationSpawn.push(Goons) + const Glukhar = Waves.Glukhar + Glukhar.BossZone = "ZoneSanatorium1,ZoneSanatorium2" + locations["shoreline"].base.BossLocationSpawn.push(Glukhar) + const Kaban = Waves.Kaban + Kaban.BossZone = "ZoneSanatorium1,ZoneSanatorium2" + locations["shoreline"].base.BossLocationSpawn.push(Kaban) + const Kolontay = Waves.Kolontay + Kolontay.BossZone = "ZoneSanatorium1,ZoneSanatorium2" + locations["shoreline"].base.BossLocationSpawn.push(Kolontay)//can be shorted harder, will leave it for the next time. + } + else { + let BossWave = CreateBoss("bossKilla", 100, "followerBully", 0, "ZoneSanatorium1,ZoneSanatorium2") + locations["shoreline"].base.BossLocationSpawn.push(BossWave) + BossWave = CreateBoss("bossBully", 100, "followerBully", 0, "ZoneSanatorium1,ZoneSanatorium2") + locations["shoreline"].base.BossLocationSpawn.push(BossWave) + BossWave = CreateBoss("bossKojaniy", 100, "followerKojaniy", 0, "ZoneSanatorium1,ZoneSanatorium2") + locations["shoreline"].base.BossLocationSpawn.push(BossWave) + BossWave = CreateBoss("bossSanitar", 100, "followerSanitar", 0, "ZoneSanatorium1,ZoneSanatorium2") + locations["shoreline"].base.BossLocationSpawn.push(BossWave) + BossWave = CreateBoss("bossTagilla", 100, "followerBully", 0, "ZoneSanatorium1,ZoneSanatorium2") + locations["shoreline"].base.BossLocationSpawn.push(BossWave) + BossWave = CreateBoss("bossGluhar", 100, "followerBully", 0, "ZoneSanatorium1,ZoneSanatorium2") + locations["shoreline"].base.BossLocationSpawn.push(BossWave) + BossWave = CreateBoss("bossBoar", 100, "followerKojaniy", 0, "ZoneSanatorium1,ZoneSanatorium2") + locations["shoreline"].base.BossLocationSpawn.push(BossWave) + BossWave = CreateBoss("bossKolontay", 100, "followerSanitar", 0, "ZoneSanatorium1,ZoneSanatorium2") + locations["shoreline"].base.BossLocationSpawn.push(BossWave) + const Goons = Waves.Goons + Goons.BossZone = "ZoneSanatorium1,ZoneSanatorium2" + locations["shoreline"].base.BossLocationSpawn.push(Goons) + } + } + if (Config.Raids.RaidEvents.BossesOnCustoms) { + for (let bosses in locations["bigmap"].base.BossLocationSpawn) { + if (locations["bigmap"].base.BossLocationSpawn[bosses].BossName == "bossBully") { + locations["bigmap"].base.BossLocationSpawn[bosses].BossChance = 100; + } + } + let BossWave = CreateBoss("bossKilla", 100, "followerBully", 0, "ZoneOldAZS") + locations["bigmap"].base.BossLocationSpawn.push(BossWave) + BossWave = CreateBoss("bossKojaniy", 100, "followerKojaniy", 2, "ZoneFactoryCenter") + locations["bigmap"].base.BossLocationSpawn.push(BossWave) + BossWave = CreateBoss("bossSanitar", 100, "followerSanitar", 2, "ZoneGasStation") + locations["bigmap"].base.BossLocationSpawn.push(BossWave) + BossWave = CreateBoss("bossTagilla", 100, "followerBully", 0, "ZoneOldAZS") + locations["bigmap"].base.BossLocationSpawn.push(BossWave) + const Glukhar = Waves.Glukhar + Glukhar.BossZone = "ZoneScavBase" + locations["bigmap"].base.BossLocationSpawn.push(Glukhar) + } + if (Config.Raids.RaidEvents.GoonsFactory) { + const Goons = Waves.Goons; + Goons.BossZone = "BotZone"; + Goons.BossChance = Config.Raids.RaidEvents.GoonsFactoryChance; + locations["factory4_day"].base.BossLocationSpawn.push(Goons) + locations["factory4_night"].base.BossLocationSpawn.push(Goons) + } + if (Config.Raids.RaidEvents.GlukharLabs) {//BossZone": "BotZoneFloor1,BotZoneFloor2", // "BossChance": 43, + const Glukhar = Waves.Glukhar + Glukhar.BossZone = "BotZoneFloor1,BotZoneFloor2" + locations["laboratory"].base.BossLocationSpawn.push(Glukhar) + } + for (let i in locations)//Bloodhounds events spawn chance - this is bad solution, but i made it on a quick hand, not sure this event lasts either. + { + if (i !== "base" && locations[i].base.BossLocationSpawn) { + for (let x in locations[i].base.BossLocationSpawn) { + if (locations[i].base.BossLocationSpawn[x].BossName == "arenaFighterEvent" && i == "bigmap") { + locations[i].base.BossLocationSpawn[x].BossChance = Config.Raids.RaidEvents.HoundsCustoms + } + if (locations[i].base.BossLocationSpawn[x].BossName == "arenaFighterEvent" && i == "woods") { + locations[i].base.BossLocationSpawn[x].BossChance = Config.Raids.RaidEvents.HoundsWoods + } + if (locations[i].base.BossLocationSpawn[x].BossName == "peacemaker" && i == "shoreline") { + locations[i].base.BossLocationSpawn[x].BossChance = Config.Raids.RaidEvents.PeaceFighters + } + if (locations[i].base.BossLocationSpawn[x].BossName == "skier" && i == "bigmap") { + locations[i].base.BossLocationSpawn[x].BossChance = Config.Raids.RaidEvents.SkierFighters + } + } + } + } + //#######BTR STUFF + if (Config.Raids.EnableBTR) { + if (Config.Raids.ForceBTRFriendly) { + for (let levels in globals.FenceSettings.Levels) { + globals.FenceSettings.Levels[levels].CanInteractWithBtr = true; + } + } + if (Config.Raids.ForceBTRStash) { + for (let levels in globals.FenceSettings.Levels) { + globals.FenceSettings.Levels[levels].DeliveryGridSize["x"] = Config.Raids.BTRWidth + globals.FenceSettings.Levels[levels].DeliveryGridSize["y"] = Config.Raids.BTRHeight + } + } + globals.BTRSettings.BasePriceTaxi = Config.Raids.BTRTaxiPrice + globals.BTRSettings.CleanUpPrice = Config.Raids.BTRCoverPrice + globals.BTRSettings.BearPriceMod = Config.Raids.BearMults + globals.BTRSettings.UsecPriceMod = Config.Raids.UsecMult + globals.BTRSettings.ScavPriceMod = Config.Raids.ScavMult + } + } + //############## TRADERS SECTION ############## + if (Config.Traders.EnableTraders) { + if (Config.Traders.Fence.EnableFence) { + trader.fence.assortSize = Config.Traders.Fence.AmountOnSale; + trader.fence.discountOptions.assortSize = Config.Traders.Fence.PremiumAmountOnSale; + trader.fence.weaponPresetMinMax.min = Config.Traders.Fence.PresetCount; + trader.fence.weaponPresetMinMax.max = Config.Traders.Fence.PresetCount; + trader.fence.presetPriceMult = Config.Traders.Fence.PresetMult; + trader.fence.itemPriceMult = Config.Traders.Fence.PriceMult; + for (let stock in trader.updateTime)//useless cycle for now, will remove later. + { + if (trader.updateTime[stock]._name == "fence" && trader.updateTime[stock].seconds.min != undefined) { + trader.updateTime[stock].seconds.min = Config.Traders.Fence.StockTime_Min * 60; + trader.updateTime[stock].seconds.max = Config.Traders.Fence.StockTime_Max * 60; + } + } + trader.fence.weaponDurabilityPercentMinMax.current.min = Config.Traders.Fence.GunDurability_Min + trader.fence.weaponDurabilityPercentMinMax.current.max = Config.Traders.Fence.GunDurability_Max + trader.fence.armorMaxDurabilityPercentMinMax.current.min = Config.Traders.Fence.ArmorDurability_Min + trader.fence.armorMaxDurabilityPercentMinMax.current.max = Config.Traders.Fence.ArmorDurability_Max + let BlacklistArray = Config.Traders.Fence.Blacklist.split("\r\n"); + BlackItems.blacklist.push(BlacklistArray); + } + globals.TradingSettings.BuyoutRestrictions.MinDurability = Config.Traders.MinDurabSell / 100 + Quest.redeemTime = Config.Traders.QuestRedeemTime; + trader.purchasesAreFoundInRaid = Config.Traders.FIRTrade; + traders["5c0647fdd443bc2504c2d371"].base.unlockedByDefault = Config.Traders.UnlockJaeger + traders["6617beeaa9cfa777ca915b7c"].base.unlockedByDefault = Config.Traders.UnlockRef + const Mark = Config.Traders.TraderMarkup; + const MarkArray = [Mark.Prapor, + Mark.Therapist, + Mark.Fence, + Mark.Skier, + Mark.Peacekeeper, + Mark.Mechanic, + Mark.Ragman, + Mark.Jaeger + ] + let i = 0; + for (let CurTrader in traders) {//Bad solution to avoid modded traders. + if (CurTrader !== "ragfair" && (CurTrader == "5a7c2eca46aef81a7ca2145d" || CurTrader == "5ac3b934156ae10c4430e83c" || + CurTrader == "5c0647fdd443bc2504c2d371" || CurTrader == "54cb50c76803fa8b248b4571" || CurTrader == "54cb57776803fa99248b456e" || + CurTrader == "579dc571d53a0658a154fbec" || CurTrader == "5935c25fb3acc3127c3d8cd9" || CurTrader == "58330581ace78e27b8b10cee")) { + for (let level in traders[CurTrader].base.loyaltyLevels) { + traders[CurTrader].base.loyaltyLevels[level].buy_price_coef = 100 - MarkArray[i] + } + i++ + } + } + //Enable all the quests + if (Config.Traders.AllQuestsAvailable) { + for (let id in Quests) { + let QuestData = Quests[id] + QuestData.conditions.AvailableForStart = [ + { + "_parent": "Level", + "_props": + { + "compareMethod": ">=", + "value": "1", + "index": 0, + "parentId": "", + "id": "683a4e6b255f7527fb05a0f6" + } + }] + } + } + if (Config.Traders.FIRRestrictsQuests) { + for (const id in Quests) { + let condition = Quests[id].conditions.AvailableForFinish + for (const requirements in condition) { + if (condition[requirements].onlyFoundInRaid !== undefined) { + condition[requirements].onlyFoundInRaid = false; + } + } + } + } + if (Config.Traders.RemoveTimeCondition) { + for (const id in Quests) { + let condition = Quests[id].conditions.AvailableForStart + for (const requirements in condition) { + if (condition[requirements].availableAfter !== undefined) { + condition[requirements].availableAfter = 0; + } + } + } + } + //Enable all traders 4 stars + if (Config.Traders.TradersLvl4) { + for (let traderID in traders) { + let loyaltyLevels = traders[traderID].base.loyaltyLevels; + for (let level in loyaltyLevels) { + loyaltyLevels[level].minLevel = 1 + loyaltyLevels[level].minSalesSum = 0 + loyaltyLevels[level].minStanding = 0 + } + } + } + if (Config.Traders.UnlockQuestAssort) { + for (let AssortR in traders) { + if (AssortR !== "ragfair" && AssortR !== "638f541a29ffd1183d187f57" && traders[AssortR].questassort.success !== undefined) { + traders[AssortR].questassort.success = {} + } + } + } + if (Config.Traders.RemoveTradeLimits) { + for (let AssortR in traders) { + if (AssortR !== "ragfair" && AssortR !== "638f541a29ffd1183d187f57") { + for (let level in traders[AssortR].assort.items) { + if (traders[AssortR].assort.items[level].upd !== undefined && traders[AssortR].assort.items[level].upd["BuyRestrictionMax"] !== undefined) { + traders[AssortR].assort.items[level].upd["BuyRestrictionMax"] = 999999; + } + } + } + } + } + if (Config.Traders.IncreaseAssort) { + for (let AssortR in traders) { + if (AssortR !== "ragfair" && AssortR !== "638f541a29ffd1183d187f57") { + for (let level in traders[AssortR].assort.items) { + if (traders[AssortR].assort.items[level].upd !== undefined && traders[AssortR].assort.items[level].upd["StackObjectsCount"] !== undefined) { + traders[AssortR].assort.items[level].upd["StackObjectsCount"] = 1337420; + } + } + } + } + } + //sell assort + const Sell = Config.Traders.TraderSell; + const SellArray = [Sell.Prapor, + Sell.Therapist, + Sell.Skier, + Sell.Peacekeeper, + Sell.Mechanic, + Sell.Ragman, + Sell.Jaeger + ] + let p = 0; + for (let CurTrader in Arrays.traderArray) { + for (let assortment in traders[Arrays.traderArray[CurTrader]].assort.barter_scheme) { + if (traders[Arrays.traderArray[CurTrader]].assort.barter_scheme[assortment][0][0]._tpl == "5449016a4bdc2d6f028b456f" || + traders[Arrays.traderArray[CurTrader]].assort.barter_scheme[assortment][0][0]._tpl == "569668774bdc2da2298b4568" || + traders[Arrays.traderArray[CurTrader]].assort.barter_scheme[assortment][0][0]._tpl == "5696686a4bdc2da3298b456a") { + let TempValue = (traders[Arrays.traderArray[CurTrader]].assort.barter_scheme[assortment][0][0].count * SellArray[p]).toFixed(2)//testing + traders[Arrays.traderArray[CurTrader]].assort.barter_scheme[assortment][0][0].count = parseFloat(TempValue) + } + } + p++; + } + if (Config.Traders.RemoveCurrencyOffers) { + for (let CurTrader in traders) { + if (CurTrader !== "ragfair" && CurTrader !== "638f541a29ffd1183d187f57" && CurTrader !== "579dc571d53a0658a154fbec") //avoid ragfair, lighthouse trader and fence + { + for (let assortment in traders[CurTrader].assort.barter_scheme) { + if (traders[CurTrader].assort.barter_scheme[assortment][0][0]._tpl == "5449016a4bdc2d6f028b456f" || + traders[CurTrader].assort.barter_scheme[assortment][0][0]._tpl == "569668774bdc2da2298b4568" || + traders[CurTrader].assort.barter_scheme[assortment][0][0]._tpl == "5696686a4bdc2da3298b456a") { + for (let DeletElem in traders[CurTrader].assort.items) {//3.10 rework instead of deleting assort - set everything to 0 instead. + if (traders[CurTrader].assort.items[DeletElem]._id == assortment) { + if (traders[CurTrader].assort.items[DeletElem].upd.UnlimitedCount !== undefined) { + traders[CurTrader].assort.items[DeletElem].upd.UnlimitedCount = false; + } + traders[CurTrader].assort.items[DeletElem].upd["StackObjectsCount"] = 0; + } + } + } + } + } + } + } + + if (Config.Traders.RemoveBarterOffers) { + for (let CurTrader in traders) { + if (CurTrader !== "ragfair" && CurTrader !== "638f541a29ffd1183d187f57" && CurTrader !== "579dc571d53a0658a154fbec") { + for (let assortment in traders[CurTrader].assort.barter_scheme) { + if (traders[CurTrader].assort.barter_scheme[assortment][0][0]._tpl !== "5449016a4bdc2d6f028b456f" && + traders[CurTrader].assort.barter_scheme[assortment][0][0]._tpl !== "569668774bdc2da2298b4568" && + traders[CurTrader].assort.barter_scheme[assortment][0][0]._tpl !== "5696686a4bdc2da3298b456a") { + for (let DeletElem in traders[CurTrader].assort.items) { + if (traders[CurTrader].assort.items[DeletElem]._id == assortment) { + if (traders[CurTrader].assort.items[DeletElem].upd.UnlimitedCount !== undefined) { + traders[CurTrader].assort.items[DeletElem].upd.UnlimitedCount = false; + } + traders[CurTrader].assort.items[DeletElem].upd["StackObjectsCount"] = 0; + } + } + } + } + } + } + } + } + //############## PMC SECTION ##################, + if (Config.PMC.EnablePMC) { + if (Config.PMC.EnableConvert) { + PMC.convertIntoPmcChance.default.assault.min = Config.PMC.AItoPMC.ScavToPMC; + PMC.convertIntoPmcChance.default.cursedassault.min = Config.PMC.AItoPMC.CursedToPMC; + PMC.convertIntoPmcChance.default.pmcbot.min = Config.PMC.AItoPMC.RaiderToPMC; + PMC.convertIntoPmcChance.default.exusec.min = Config.PMC.AItoPMC.RogueToPMC; + PMC.convertIntoPmcChance.default.marksman = {}; + PMC.convertIntoPmcChance.default.marksman.min = Config.PMC.AItoPMC.SnipertoPMC; + + PMC.convertIntoPmcChance.default.assault.max = Config.PMC.AItoPMC.ScavToPMC; + PMC.convertIntoPmcChance.default.cursedassault.max = Config.PMC.AItoPMC.CursedToPMC; + PMC.convertIntoPmcChance.default.pmcbot.max = Config.PMC.AItoPMC.RaiderToPMC; + PMC.convertIntoPmcChance.default.exusec.max = Config.PMC.AItoPMC.RogueToPMC; + PMC.convertIntoPmcChance.default.marksman.max = Config.PMC.AItoPMC.SniperToPMC; + PMC.isUsec = Config.PMC.PMCRatio; + } + PMC.botRelativeLevelDeltaMax = Config.PMC.LevelUpMargin; + PMC.botRelativeLevelDeltaMin = Config.PMC.LevelDownMargin; + if (Config.PMC.ChancesEnable) { + PMC.chanceSameSideIsHostilePercent = Config.PMC.PMCChance.HostilePMC; + PMC.looseWeaponInBackpackChancePercent = Config.PMC.PMCChance.PMCLooseWep; + PMC.weaponHasEnhancementChancePercent = Config.PMC.PMCChance.PMCWepEnhance; + PMC.addPrefixToSameNamePMCAsPlayerChance = Config.PMC.PMCChance.PMCNamePrefix; + PMC.allPMCsHavePlayerNameWithRandomPrefixChance = Config.PMC.PMCChance.PMCAllNamePrefix; + } + //Lootable melees + for (const id in items) { + let base = items[id] + if (base._parent === "5447e1d04bdc2dff2f8b4567" && base._id !== "6087e570b998180e9f76dc24" && Config.PMC.LootableMelee) { + EditSimpleItemData(id, "Unlootable", false); + items[id]._props.UnlootableFromSide = []; + } + } + if (Config.PMC.DisableLowLevelPMC) { + Bots.equipment.pmc.randomisation[0].levelRange.max = 1; + Bots.equipment.pmc.randomisation[1].levelRange.min = 1; + Bots.equipment.pmc.randomisation[2].levelRange.min = 1; + Bots.equipment.pmc.randomisation[3].levelRange.min = 1; + //Bots.equipment.pmc.randomisation[4].levelRange.min = 1; + } + if (Config.PMC.NamesEnable) { + if (Config.PMC.NameOverride) { + let Names = Config.PMC.PMCNameList.split("\r\n") + Bot["pmcusec"].firstName = Names; + Bot["pmcbear"].firstName = Names; + Bot["usec"].firstName = Names; + Bot["bear"].firstName = Names; + } + else { + let Names = Config.PMC.PMCNameList.split("\r\n") + for (const name in Names)//I don't really remember should i even have this cycle here, but eh, cba. + { + Bot["pmcusec"].firstName.push(Names[name]) + Bot["pmcbear"].firstName.push(Names[name]) + Bot["usec"].firstName.push(Names[name]) + Bot["bear"].firstName.push(Names[name]) + } + } + } + } + //############## REPEATABLE QUESTS SECTION ############# + if (Config.Quests.EnableQuests) { + const Daily = Config.Quests.DailyQuests; + const Weekly = Config.Quests.WeeklyQuests; + const ScavDaily = Config.Quests.ScavQuests; + //Requirements + QuestDetails(Daily, "0") + QuestDetails(Weekly, "1") + QuestDetails(ScavDaily, "2") + //Rewards + QuestReward(Daily, "0") + QuestReward(Weekly, "1") + QuestReward(ScavDaily, "2") + } + //############## SCAV SECTION ############## I wish i never made one, but here we are + if (Config.Scav.EnableScav) { + //Base Fence rep given by car extract + Inraid.carExtractBaseStandingGain = Config.Scav.CarBaseStanding + //Allow Scav into Lab + locations["laboratory"].base.DisabledForScav = !Config.Scav.ScavLab; + //Scav Cooldown Timer + globals.SavagePlayCooldown = Config.Scav.ScavTimer; + + for (let levels in globals.FenceSettings.Levels)//Damn it looks counter intuitive + { + if (Config.Scav.HostileScavs) { + globals.FenceSettings.Levels[levels].HostileScavs = Config.Scav.HostileScavs + } + if (Config.Scav.HostileBosses) { + globals.FenceSettings.Levels[levels].HostileBosses = Config.Scav.HostileScavs + } + if (Config.Scav.FriendlyScavs) { + globals.FenceSettings.Levels[levels].HostileScavs = !Config.Scav.FriendlyScavs + } + if (Config.Scav.FriendlyBosses) { + globals.FenceSettings.Levels[levels].HostileBosses = !Config.Scav.FriendlyBosses + } + } + if (Config.Scav.ScavCustomPockets) { + const JsonUtil = container.resolve("JsonUtil"); + let ScavCustomPocketItem = JsonUtil.clone(items["557ffd194bdc2d28148b457f"]) + let ScavPocketSize = Config.Scav.SCAVPockets + ScavCustomPocketItem._id = "a8edfb0bce53d103d3f6219b" + for (let cell in ScavCustomPocketItem._props.Grids)//tried to make less code, made more, smh. + { + ScavCustomPocketItem._props.Grids[cell]._parent = "a8edfb0bce53d103d3f6219b" + } + ScavCustomPocketItem._props.Grids[0]._id = "a8edfb0bce53d103d3f6229b" + ScavCustomPocketItem._props.Grids[0]._props.cellsH = ScavPocketSize.FirstWidth + ScavCustomPocketItem._props.Grids[0]._props.cellsV = ScavPocketSize.FirstHeight + ScavCustomPocketItem._props.Grids[1]._id = "a8edfb0bce53d103d3f6239b" + ScavCustomPocketItem._props.Grids[1]._props.cellsH = ScavPocketSize.SecondWidth + ScavCustomPocketItem._props.Grids[1]._props.cellsV = ScavPocketSize.SecondHeight + ScavCustomPocketItem._props.Grids[2]._id = "a8edfb0bce53d103d3f6249b" + ScavCustomPocketItem._props.Grids[2]._props.cellsH = ScavPocketSize.ThirdWidth + ScavCustomPocketItem._props.Grids[2]._props.cellsV = ScavPocketSize.ThirdHeight + ScavCustomPocketItem._props.Grids[3]._id = "a8edfb0bce53d103d3f6259b" + ScavCustomPocketItem._props.Grids[3]._props.cellsH = ScavPocketSize.FourthWidth + ScavCustomPocketItem._props.Grids[3]._props.cellsV = ScavPocketSize.FourthHeight + switch (true) { + case ScavPocketSize.FourthWidth == 0 || ScavPocketSize.FourthHeight == 0: + ScavCustomPocketItem._props.Grids.splice(3, 1) + case ScavPocketSize.ThirdWidth == 0 || ScavPocketSize.ThirdHeight == 0: + ScavCustomPocketItem._props.Grids.splice(2, 1); + case ScavPocketSize.SecondWidth == 0 || ScavPocketSize.SecondHeight == 0: + ScavCustomPocketItem._props.Grids.splice(1, 1); + case ScavPocketSize.FirstWidth == 0 || ScavPocketSize.FirstHeight == 0: + ScavCustomPocketItem._props.Grids.splice(0, 1); + break; + default: + break; + } + items["a8edfb0bce53d103d3f6219b"] = ScavCustomPocketItem; + } + } + //############## CUSTOM SECTION ############## + if (Config.Custom.EnableCustom) { + if (Config.Custom.LoggerIntoServer) { + Logger.warning("[SVM] PRESET IS BEING LOGGED INTO SERVER, DO NOT USE THIS FEATURE UNDER NORMAL CIRCUMSTANCES") + Logger.debug(Config) + } + const Core = configServer.getConfig("spt-core"); + Core.features.chatbotFeatures.sptFriendEnabled = !Config.Custom.DisableSPTFriend + Core.features.chatbotFeatures.commandoEnabled = !Config.Custom.DisableCommando + if (Config.Custom.DisablePMCMessages) { + const Chat = configServer.getConfig("spt-pmcchatresponse"); + Chat.victim.responseChancePercent = 0; + Chat.killer.responseChancePercent = 0; + } + + //If you're reading here, maybe you checked that custom fields exist now, + //feel free to use this place to run your own little scripts using SVM as a framework, Search word is `banana` + //Mind you, Custom section needs to be enabled, you can however write stuff after the bracket there to run the code if at least preset exist. + //Fields names are `CustomCheck1,2,3,4` and `CustomNumber1,2,3,4` + } + //##### + + //############## FUNCTIONS ############## + //Set a Unique AI type spawn within selected location, with a lot of variables to come in. + function CreateBoss(role, chance, followers, escortAmount, zones) { + return { + "BossName": role, + "BossChance": chance, + "BossZone": zones, + "BossPlayer": false, + "BossDifficult": "normal", + "BossEscortType": followers, + "BossEscortDifficult": "normal", + "BossEscortAmount": escortAmount, + "Time": -1 + } + } + function Filter(value) { + let test = value.substring(1, value.length - 1) + let result = test.split(",") + return result + } + function EditSimpleItemData(id, data, value) { + if (isNaN(value) && value !== 'true' && value !== 'false') { + items[id]._props[data] = value + } + else { + items[id]._props[data] = JSON.parse(value) + } + } + function QuestDetails(Type, Digit) { + Quest.repeatableQuests[Digit].resetTime = Type.Lifespan * 60; + Quest.repeatableQuests[Digit].types = [] + if (Digit < 2) { + switch (Type.Types)//Horrible + { + case 0: Quest.repeatableQuests[Digit].types.push(Arrays.Types[0]) + break; + case 1: Quest.repeatableQuests[Digit].types.push(Arrays.Types[1]) + break; + case 2: Quest.repeatableQuests[Digit].types.push(Arrays.Types[2]) + break; + case 3: Quest.repeatableQuests[Digit].types.push(Arrays.Types[0], Arrays.Types[1]) + break; + case 4: Quest.repeatableQuests[Digit].types.push(Arrays.Types[1], Arrays.Types[2]) + break; + case 5: Quest.repeatableQuests[Digit].types.push(Arrays.Types[2], Arrays.Types[2]) + break; + case 6: Quest.repeatableQuests[Digit].types.push(Arrays.Types[0], Arrays.Types[1], Arrays.Types[2]) + break; + } + } + else { + switch (Type.Types) { + case 0: Quest.repeatableQuests[2].types.push(Arrays.Types[0]) + break; + case 1: Quest.repeatableQuests[2].types.push(Arrays.Types[1]) + break; + case 2: Quest.repeatableQuests[2].types.push(Arrays.Types[0], Arrays.Types[1]) + } + } + + Quest.repeatableQuests[Digit].numQuests = Type.QuestAmount; + + Quest.repeatableQuests[Digit].minPlayerLevel = Type.Access + Quest.repeatableQuests[Digit].rewardScaling.rewardSpread = Type.Spread; + Quest.repeatableQuests[Digit].questConfig.Exploration.maxExtracts = Type.Extracts; + Quest.repeatableQuests[Digit].questConfig.Completion.minRequestedAmount = Type.MinItems; + Quest.repeatableQuests[Digit].questConfig.Completion.maxRequestedAmount = Type.MaxItems; + Quest.repeatableQuests[Digit].questConfig.Elimination[0].minKills = Type.MinKillsLR1; + Quest.repeatableQuests[Digit].questConfig.Elimination[0].maxKills = Type.MaxKillsLR1; + Quest.repeatableQuests[Digit].questConfig.Elimination[1].minKills = Type.MinKillsLR2; + Quest.repeatableQuests[Digit].questConfig.Elimination[1].maxKills = Type.MaxKillsLR2; + if (Digit < 2) { + Quest.repeatableQuests[Digit].questConfig.Elimination[2].minKills = Type.MinKillsLR3; + Quest.repeatableQuests[Digit].questConfig.Elimination[2].maxKills = Type.MaxKillsLR3; + } + } + function AirdropContents(DBType, Type) { + if (Airdrop.loot[DBType] != undefined) { + Airdrop.loot[DBType].itemCount.min = Type.BarterMin + Airdrop.loot[DBType].itemCount.max = Type.BarterMax + Airdrop.loot[DBType].weaponPresetCount.min = Type.PresetMin + Airdrop.loot[DBType].weaponPresetCount.max = Type.PresetMax + Airdrop.loot[DBType].armorPresetCount.min = Type.ArmorMin + Airdrop.loot[DBType].armorPresetCount.max = Type.ArmorMax + Airdrop.loot[DBType].weaponCrateCount.min = Type.CratesMin + Airdrop.loot[DBType].weaponCrateCount.max = Type.CratesMax + } + } + function QuestReward(Type, Digit) { + try { + let Levels = Type.Levels.split(","); + let Exp = Type.Experience.split(","); + let Reputation = Type.Reputation.split(","); + let ItemsReward = Type.ItemsReward.split(","); + let Roubles = Type.Roubles.split(","); + let GPcoins = Type.GPcoins.split(","); + let SkillChance = Type.SkillChance.split(","); + let SkillPoint = Type.SkillPoint.split(","); + + if ((Levels.length == Exp.length) && (Levels.length == Reputation.length) && + (Levels.length == ItemsReward.length) && (Levels.length == Roubles.length) && + (Levels.length == GPcoins.length) && (Levels.length == SkillChance.length) && (Levels.length == SkillPoint.length)) { + Quest.repeatableQuests[Digit].rewardScaling.levels = Levels.map(Number); + Quest.repeatableQuests[Digit].rewardScaling.experience = Exp.map(Number); + Quest.repeatableQuests[Digit].rewardScaling.reputation = Reputation.map(Number); + Quest.repeatableQuests[Digit].rewardScaling.items = ItemsReward.map(Number); + Quest.repeatableQuests[Digit].rewardScaling.roubles = Roubles.map(Number); + Quest.repeatableQuests[Digit].rewardScaling.gpCoins = GPcoins.map(Number); + Quest.repeatableQuests[Digit].rewardScaling.skillRewardChance = SkillChance.map(Number); + Quest.repeatableQuests[Digit].rewardScaling.skillPointReward = SkillPoint.map(Number); + } + else { + Logger.error("[SVM] REPEATABLE QUESTS - Daily rewards scales written wrongly, read FAQ, changes ignored.") + } + } + catch { + Logger.error("[SVM] REPEATABLE QUESTS - Daily rewards scales written wrongly, read FAQ, changes ignored.") + } + } + function isJSONValueDefined(value) { + return value !== undefined && !value.isNaN; + } + function FreeExit(Exit) { + Exit.PassageRequirement = "None"; + Exit.ExfiltrationType = "Individual"; + Exit.Id = ''; + Exit.Count = 0; + Exit.PlayersCount = 0; + Exit.RequirementTip = ''; + if (Exit.RequiredSlot) { + delete Exit.RequiredSlot; + } + } + function IDChanger(Variables) { + try { + switch (Variables.length) { + case 3: + items[Variables[0]]._props[Variables[1]] = CheckType(Variables[2]) + break; + case 4: + if (SymbolCheck(Variables[2])) { + items[Variables[0]]._props[Variables[1]] = Calculus(items[Variables[0]]._props[Variables[1]], Variables[2], Variables[3]) + } + else { + items[Variables[0]]._props[Variables[1]][Variables[2]] = CheckType(Variables[3]) + } + break; + case 5: + if (SymbolCheck(Variables[3])) { + items[Variables[0]]._props[Variables[1]][Variables[2]] = Calculus(items[Variables[0]]._props[Variables[1]][Variables[2]], Variables[3], Variables[4]) + } + else { + items[Variables[0]]._props[Variables[1]][Variables[2]][Variables[3]] = CheckType(Variables[4]) + } + break; + case 6: + if (SymbolCheck(Variables[4])) { + items[Variables[0]]._props[Variables[1]][Variables[2]][Variables[3]] = Calculus(items[Variables[0]]._props[Variables[1]][Variables[2]][Variables[3]], Variables[4], Variables[5]) + } + else { + items[Variables[0]]._props[Variables[1]][Variables[2]][Variables[3]][Variables[4]] = CheckType(Variables[5]) + } + break; + case 7: + items[Variables[0]]._props[Variables[1]][Variables[2]][Variables[3]][Variables[4]][Variables[5]] = CheckType(Variables[6]) + break; + case 8: + items[Variables[0]]._props[Variables[1]][Variables[2]][Variables[3]][Variables[4]][Variables[5]][Variables[6]] = CheckType(Variables[7]) + break; + case 9: + items[Variables[0]]._props[Variables[1]][Variables[2]][Variables[3]][Variables[4]][Variables[5]][Variables[6]][Variables[7]] = CheckType(Variables[8]) + break; + case 10: + items[Variables[0]]._props[Variables[1]][Variables[2]][Variables[3]][Variables[4]][Variables[5]][Variables[6]][Variables[7]][Variables[8]] = CheckType(Variables[9]) + break; + default: + Logger.error("[SVM] INVENTORY AND ITEMS - Custom properties line failed, More than 10 or less than 3 variables?") + break; + } + } + catch (e) { + Logger.error("[SVM] INVENTORY AND ITEMS - Custom properties line failed, something ain't right\n" + e) + } + } + function CheckType(object) { + if (object.includes(",") || object.includes("[")) { + return Filter(object) + } + else if (isNaN(object) && object !== 'true' && object !== 'false') { + return object; + } + else { + return JSON.parse(object) + } + } + function SymbolCheck(Value) { + return (Value == "*" || Value == "/" || Value == "+" || Value == "-"); + } + function Calculus(Field, Operand, Value) { + switch (Operand) { + case "/": + Field = parseInt(parseInt(Field) / parseFloat(Value)) + break; + case "*": + Field = parseInt(parseInt(Field) * parseFloat(Value)) + break; + case "+": + Field = parseInt(parseInt(Field) + parseFloat(Value)) + break; + case "-": + Field = parseInt(parseInt(Field) - parseFloat(Value)) + break; + } + return Field + } + function AmmoFilter(AID, Comp) { + for (let ID in AID) { + if (Comp.includes(AID[ID])) { + return true; + } + } + return false; + } + //initialise complete logger + const Misc = require('../src/Misc.json'); + Logger.log(`[SVM] Initialization complete. ` + Misc.funni[Math.floor(Math.random() * Misc.funni.length)], "blue"); + if (PresetLoader.CurrentlySelectedPreset != "" && PresetLoader.CurrentlySelectedPreset != undefined) { + Logger.log("[SVM] Preset - " + PresetLoader.CurrentlySelectedPreset + " - successfully loaded", "blue"); + } + } +} +module.exports = { + mod: new MainSVM +}; \ No newline at end of file diff --git a/mods/Server Value Modifier_backup/User/Mods/[SVM] Server Value Modifier/src/Waves.json b/mods/Server Value Modifier_backup/User/Mods/[SVM] Server Value Modifier/src/Waves.json new file mode 100644 index 0000000..19c5b18 --- /dev/null +++ b/mods/Server Value Modifier_backup/User/Mods/[SVM] Server Value Modifier/src/Waves.json @@ -0,0 +1,183 @@ +{ +"Glukhar": +{ + "BossChance": 100, + "BossDifficult": "normal", + "BossEscortAmount": "2", + "BossEscortDifficult": "normal", + "BossEscortType": "followerGluharSecurity", + "BossName": "bossGluhar", + "BossPlayer": false, + "BossZone": "", + "Delay": 0, + "ForceSpawn": false, + "IgnoreMaxBots": true, + "RandomTimeSpawn": false, + "SpawnMode": [ + "regular", + "pve" + ], + "Supports": [ + { + "BossEscortAmount": "2", + "BossEscortDifficult": [ + "normal" + ], + "BossEscortType": "followerGluharAssault" + }, + { + "BossEscortAmount": "2", + "BossEscortDifficult": [ + "normal" + ], + "BossEscortType": "followerGluharSecurity" + }, + { + "BossEscortAmount": "2", + "BossEscortDifficult": [ + "normal" + ], + "BossEscortType": "followerGluharScout" + } + ], + "Time": -1, + "TriggerId": "", + "TriggerName": "" +}, + "Kaban": + { + "BossChance": 100, + "BossDifficult": "normal", + "BossEscortAmount": "6", + "BossEscortDifficult": "normal", + "BossEscortType": "followerBoar", + "BossName": "bossBoar", + "BossPlayer": false, + "BossZone": "", + "Delay": 0, + "ForceSpawn": false, + "IgnoreMaxBots": true, + "RandomTimeSpawn": false, + "SpawnMode": [ + "regular", + "pve" + ], + "Supports": [ + { + "BossEscortAmount": "4", + "BossEscortDifficult": [ + "normal" + ], + "BossEscortType": "followerBoar" + }, + { + "BossEscortAmount": "1", + "BossEscortDifficult": [ + "normal" + ], + "BossEscortType": "followerBoarClose1" + }, + { + "BossEscortAmount": "1", + "BossEscortDifficult": [ + "normal" + ], + "BossEscortType": "followerBoarClose2" + } + ], + "Time": -1, + "TriggerId": "", + "TriggerName": "" + }, + "Kolontay": + { + "BossChance": 100, + "BossDifficult": "normal", + "BossEscortAmount": "2", + "BossEscortDifficult": "normal", + "BossEscortType": "followerKolontaySecurity", + "BossName": "bossKolontay", + "BossPlayer": false, + "BossZone": "", + "Delay": 0, + "ForceSpawn": false, + "IgnoreMaxBots": true, + "RandomTimeSpawn": false, + "SpawnMode": [ + "regular", + "pve" + ], + "Supports": [ + { + "BossEscortAmount": "2", + "BossEscortDifficult": [ + "normal" + ], + "BossEscortType": "followerKolontayAssault" + }, + { + "BossEscortAmount": "2", + "BossEscortDifficult": [ + "normal" + ], + "BossEscortType": "followerKolontaySecurity" + }, + { + "BossEscortAmount": "0", + "BossEscortDifficult": [ + "normal" + ], + "BossEscortType": "followerGluharScout" + } + ], + "Time": -1, + "TriggerId": "", + "TriggerName": "" + }, + "Goons":{ + "BossChance": 100, + "BossDifficult": "normal", + "BossEscortAmount": "2", + "BossEscortDifficult": "normal", + "BossEscortType": "exUsec", + "BossName": "bossKnight", + "BossPlayer": false, + "BossZone": "", + "Delay": 0, + "DependKarma": false, + "DependKarmaPVE": false, + "ForceSpawn": false, + "IgnoreMaxBots": true, + "RandomTimeSpawn": true, + "SpawnMode": [ + "regular", + "pve" + ], + "Supports": [ + { + "BossEscortAmount": "1", + "BossEscortDifficult": [ + "normal" + ], + "BossEscortType": "followerBigPipe" + }, + { + "BossEscortAmount": "1", + "BossEscortDifficult": [ + "normal" + ], + "BossEscortType": "followerBirdEye" + }, + { + "BossEscortAmount": "0", + "BossEscortDifficult": [ + "normal" + ], + "BossEscortType": "followerGluharScout" + } + ], + "Time": -1, + "TriggerId": "", + "TriggerName": "" + } +} \ No newline at end of file diff --git a/mods/Server Value Modifier_backup/meta.ini b/mods/Server Value Modifier_backup/meta.ini new file mode 100644 index 0000000..c204006 --- /dev/null +++ b/mods/Server Value Modifier_backup/meta.ini @@ -0,0 +1,28 @@ +[General] +gameName=spt +modid=0 +version=d2024.12.19.0 +newestVersion= +category="1,2" +nexusFileStatus=1 +installationFile=SVM.Server.Value.Modifier1.10H4.zip +repository= +ignoredVersion= +comments= +notes= +nexusDescription= +url= +hasCustomURL=false +lastNexusQuery= +lastNexusUpdate= +nexusLastModified=2024-12-16T06:50:21Z +nexusCategory=0 +converted=false +validated=false +color=@Variant(\0\0\0\x43\0\xff\xff\0\0\0\0\0\0\0\0) +tracked=0 + +[installedFiles] +1\modid=0 +1\fileid=0 +size=1 diff --git a/profiles/Multiplayer/modlist.txt b/profiles/Multiplayer/modlist.txt index e968cc6..9365feb 100644 --- a/profiles/Multiplayer/modlist.txt +++ b/profiles/Multiplayer/modlist.txt @@ -1,4 +1,3 @@ -# This file was automatically generated by Mod Organizer. -Unsorted_separator -Version 1.26.0_separator -Visceral Combat