11 Commits
Author SHA1 Message Date
Rage 23dc6d93c3 Update Download Modpack.bat
Cleaned up some code; Automated the MO2 install fully with a new user input method to acquire the game path.
2025-01-16 02:24:37 -05:00
Rage a84001c8bf Updated MOAR Settings 2025-01-16 02:06:59 -05:00
Rage 4ccd8753d1 Updated ModOrganizer.ini 2025-01-16 02:06:42 -05:00
Rage 1d21d74bb9 Some Optimizations to the Modpack
Disabled a lot of client-side related mods, removed Performance Improvements and disabled some potentially bad mods.

Reinstalled a default version of MOAR with just the source code preset selection set to custom.
2025-01-16 01:26:40 -05:00
Rage 3ebaed3777 Removed Potential Mod Corrupting Game 2025-01-15 21:33:26 -05:00
Rage 5d24318a39 Added A Mod; Fixed One Mod Installation
Added
- Black Clothing Pack

Fixed
- Make Val/VSS Great Again
2025-01-15 20:59:57 -05:00
Rage a161750966 Added Mods
- New Trader Mod; Painter
  - Along with a new weapon attachment mod; Black Core
- Make Val/VSS Great Again
2025-01-15 20:53:42 -05:00
Rage c3fcfb84f8 Reduced Quantity Multipliers 2025-01-15 20:16:52 -05:00
Rage 35e1404f43 Reduced MOAR Bot Spawn Counts 2025-01-15 19:38:36 -05:00
Rage f004d53072 Fixed Version Number 2025-01-15 18:47:35 -05:00
Rage 4a1cdbcd20 Tweaked MOAR Map-Specific Spawns and Config 2025-01-15 18:47:15 -05:00
532 changed files with 9243 additions and 45059 deletions
+64 -16
View File
@@ -4,6 +4,12 @@
set "mo2_install=%cd%"
set "repository=%mo2_install%\Fika-Tarkov"
:: Specifying links to download for files
set "git_repository=https://files.moddinglounge.com/Rage/Fika-Tarkov.git"
set "git_file=https://github.com/git-for-windows/git/releases/download/v2.47.1.windows.1/PortableGit-2.47.1-64-bit.7z.exe"
set "SevenZ_file=https://www.7-zip.org/a/7zr.exe"
set "mo2_file=https://github.com/ModOrganizer2/modorganizer/releases/download/v2.5.2/Mod.Organizer-2.5.2.7z"
:: Set path to the portable Git executable
set "portable_git=%mo2_install%\PortableGit\bin\git.exe"
set "portable_7z=%mo2_install%\7zr.exe"
@@ -22,7 +28,7 @@ if not exist "%mo2_install%\PortableGit\bin\git.exe" (
echo ----
echo Installing Portable Git...
:: Download Git Portable
curl -L -o PortableGit-2.47.1-64-bit.7z.exe https://github.com/git-for-windows/git/releases/download/v2.47.1.windows.1/PortableGit-2.47.1-64-bit.7z.exe
curl -L -o PortableGit-2.47.1-64-bit.7z.exe %git_file%
if %errorlevel% neq 0 (
echo ERROR: Failed to download Git Portable. Check your internet connection and try again.
@@ -41,7 +47,7 @@ if not exist "%mo2_install%\7zr.exe" (
echo ----
echo Installing 7zip Portable...
:: Download 7zip Portable
curl -L -o 7zr.exe https://www.7-zip.org/a/7zr.exe
curl -L -o 7zr.exe %SevenZ_file%
)
:: Determining if an installation exists already
@@ -64,10 +70,10 @@ IF EXIST "%mo2_install%\ModOrganizer.exe" (
timeout 10
:: Clone or update the Git repository
if not exist "Fika-Tarkov\.git" (
if not exist "%repository%\.git" (
echo ----
echo Cloning repository...
"%portable_git%" clone https://files.moddinglounge.com/Rage/Fika-Tarkov.git
"%portable_git%" clone %git_repository%
) else (
echo ----
echo Repository already exists. Pulling latest changes...
@@ -84,18 +90,11 @@ IF EXIST "%mo2_install%\ModOrganizer.exe" (
echo Synchronizing profiles folder...
robocopy "%repository%/profiles" "%mo2_install%/profiles" /MIR
echo ----
echo Synchronizing stylesheets folder...
robocopy "%repository%/stylesheets" "%mo2_install%/stylesheets" /E
echo ----
echo Synchronizing plugins folder...
robocopy "%repository%/plugins" "%mo2_install%/plugins" /E
pause
exit /B 0
:InstallModpack
echo.
echo !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
echo WARNING! The script will install the modpack in the folder this script is ran from!
echo Be sure that your folder is empty before continuing with the installation!
@@ -108,9 +107,19 @@ IF EXIST "%mo2_install%\ModOrganizer.exe" (
timeout 30
:: Requiring user input for game path
echo ----
set /p "game_path=Please enter the path to your game installation: "
if "%game_path%"=="" (
echo.
echo No path entered. Exiting.
echo.
pause
exit /b 1
)
:: Download MO2
curl -L -o MO2.7z https://github.com/ModOrganizer2/modorganizer/releases/download/v2.5.2/Mod.Organizer-2.5.2.7z
curl -L -o MO2.7z %mo2_file%
if %errorlevel% neq 0 (
echo ERROR: Failed to download the archive. Check your internet connection and try again.
pause
@@ -138,7 +147,7 @@ IF EXIST "%mo2_install%\ModOrganizer.exe" (
echo ----
echo Cloning repository...
"%portable_git%" clone https://files.moddinglounge.com/Rage/Fika-Tarkov.git
"%portable_git%" clone %git_repository%
echo ----
echo Synchronizing mods folder...
@@ -148,13 +157,52 @@ IF EXIST "%mo2_install%\ModOrganizer.exe" (
echo Synchronizing profiles folder...
robocopy "%repository%/profiles" "%mo2_install%/profiles" /MIR
echo ----
echo Synchronizing plugins folder...
robocopy "%repository%/plugins" "%mo2_install%/plugins" /E
echo ----
echo Synchronizing stylesheets folder...
robocopy "%repository%/stylesheets" "%mo2_install%/stylesheets" /E
:: Escape backslashes in the game path
setlocal enabledelayedexpansion
set "game_path=!game_path:\=/!"
set "escaped_path="
for /l %%i in (0,1,255) do (
for /f "tokens=1,* delims=" %%a in ("!game_path:~%%i,1!") do (
if "%%a"=="" goto path_done
if %%a==/ (
set "escaped_path=!escaped_path!//" :: Double the backslash
) else (
set "escaped_path=!escaped_path!%%a"
)
)
)
:path_done
echo Original Path: %game_path%
echo Escaped Path: %escaped_path%
:: Replace placeholders in ModOrganizer.ini
echo ----
echo Synchronizing plugins folder...
robocopy "%repository%/plugins" "%mo2_install%/plugins" /E
echo Updating ModOrganizer.ini...
set "ini_file=%repository%\ModOrganizer.ini"
set "temp_ini=%ini_file%.tmp"
(for /f "usebackq delims=" %%A in ("%ini_file%") do (
set "line=%%A"
set "line=!line:game_path=%escaped_path%!"
set "line=!line:replace_me=%game_path%!"
echo(!line!
)) > "%temp_ini%"
move /y "%temp_ini%" "%mo2_install%\ModOrganizer.ini"
echo ----
echo ModOrganizer.ini updated successfully!
echo ----
echo Installation complete. Launch ModOrganizer.exe and follow the remaining instructions.
+159 -2
View File
@@ -1,17 +1,75 @@
[General]
gameName=SPT
gamePath=@ByteArray(replace_me)
gamePath=@ByteArray(game_path)
selected_profile=@ByteArray(Multiplayer)
version=2.5.2
first_start=false
previousSeparatorColor=@Variant(\0\0\0\x43\x1\xff\xff\x44\x44\x36\x36))\0\0)
backup_install=true
[PluginPersistance]
Python%20Proxy\tryInit=false
[Settings]
profile_local_inis=false
profile_local_saves=false
profile_archive_invalidation=true
log_level=1
language=en
compact_downloads=true
meta_downloads=false
autohide_downloads=false
check_for_updates=true
use_prereleases=false
center_dialogs=false
show_change_game_confirmation=true
show_menubar_on_alt=true
double_click_previews=true
style=Dark Bronze.qss
overwrittenLooseFilesColor=@Variant(\0\0\0\x43\x1@@\0\0\xff\xff\0\0\0\0)
overwritingLooseFilesColor=@Variant(\0\0\0\x43\x1@@\xff\xff\0\0\0\0\0\0)
overwrittenArchiveFilesColor=@Variant(\0\0\0\x43\x1@@\0\0\xff\xff\xff\xff\0\0)
overwritingArchiveFilesColor=@Variant(\0\0\0\x43\x1@@\xff\xff\0\0\xff\xff\0\0)
containsPluginColor=@Variant(\0\0\0\x43\x1@@\0\0\0\0\xff\xff\0\0)
containedColor=@Variant(\0\0\0\x43\x1@@\0\0\0\0\xff\xff\0\0)
colorSeparatorScrollbars=true
display_foreign=true
collapsible_separators_asc=true
collapsible_separators_dsc=true
collapsible_separators_conflicts_from=true
collapsible_separators_conflicts_to=true
collapsible_separators_per_profile=false
save_filters=false
auto_collapse_on_hover=false
autocheck_update_install=true
collapsible_separators_icons_1=true
collapsible_separators_icons_2=true
collapsible_separators_icons_3=true
collapsible_separators_icons_7=true
crash_dumps_type=1
crash_dumps_max=5
loot_log_level=2
endorsement_integration=true
tracked_integration=true
category_mappings=true
hide_api_counter=false
force_enable_core_files=true
lock_gui=true
archive_parsing_experimental=false
offline_mode=false
use_proxy=false
use_custom_browser=false
custom_browser=
executable_blacklist="Chrome.exe;Firefox.exe;TSVNCache.exe;TGitCache.exe;Steam.exe;GameOverlayUI.exe;Discord.exe;GalaxyClient.exe;Spotify.exe;Brave.exe"
skip_file_suffixes=.mohidden
skip_directories=.git
filter_regex=false
regex_case_sensitive=false
regex_extended=false
filter_scroll_to_selection=false
[customExecutables]
size=1
size=6
1\arguments=
1\binary=replace_me/SPT.Launcher.exe
1\hide=false
@@ -20,3 +78,102 @@ size=1
1\title=Multiplayer
1\toolbar=false
1\workingDirectory=replace_me
2\arguments=
2\binary=replace_me/sptvfsbridge.bat
2\hide=false
2\ownicon=true
2\steamAppID=
2\title=Singleplayer
2\toolbar=false
2\workingDirectory=replace_me
3\arguments=
3\binary=D:/Modding/Modlists/Fika Tarkov/mods/Load Order Editor/LoEDD/LoEDD.exe
3\hide=false
3\ownicon=true
3\steamAppID=
3\title=Load Order Editor
3\toolbar=true
3\workingDirectory=D:\\Modding\\Modlists\\Fika Tarkov\\mods\\Load Order Editor\\LoEDD
4\arguments=
4\binary=D:/Modding/Modlists/Fika Tarkov/mods/Server Value Modifier/user/mods/[SVM] Server Value Modifier/Greed.exe
4\hide=false
4\ownicon=false
4\steamAppID=
4\title=Greed
4\toolbar=true
4\workingDirectory=D:\\Modding\\Modlists\\Fika Tarkov\\mods\\Server Value Modifier\\user\\mods\\[SVM] Server Value Modifier
5\arguments=\"D:\\Games\\Singleplayer Tarkov\"
5\binary=D:/Modding/Modlists/Fika Tarkov/explorer++/Explorer++.exe
5\hide=false
5\ownicon=true
5\steamAppID=
5\title=Explore Virtual Folder
5\toolbar=false
5\workingDirectory=D:\\Modding\\Modlists\\Fika Tarkov\\explorer++
[Widgets]
SettingsDialog_tabWidget_index=0
MainWindow_executablesListBox_index=1
MainWindow_tabWidget_index=2
MainWindow_dataTabShowOnlyConflicts_checked=false
MainWindow_dataTabShowFromArchives_checked=false
MainWindow_groupCombo_index=0
MainWindow_modList_index=SWAG + DONUTS_backup, Fika, Essentials, Bug Fixes & Optimizations, Interface & HUD, SFX & Music, New Items & Keys, Gameplay Tweaks, New Traders & Tweaks, New Weapons & Gear, AI & Combat Tweaks, VFX & Atmosphere, Modlist Addons, Backburner, Version 1.32.0, Unsorted, Overwrite
MainWindow_filters_index=0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
MainWindow_filtersAnd_checked=true
MainWindow_filtersOr_checked=false
MainWindow_filtersSeparators_index=0
ModInfoTabOrder=tabFiles tabText tabIni tabImages tabESPs tabConflicts tabCategories tabNexus tabNotes
ModInfoDialog_tabWidget_index=0
ModInfoDialog_imagesShowDDS_checked=false
ModInfoDialog_tabConflictsTabs_index=0
ModInfoDialog_conflictsAdvancedShowNoConflict_checked=true
ModInfoDialog_conflictsAdvancedShowAll_checked=true
ModInfoDialog_conflictsAdvancedShowNearest_checked=false
[Geometry]
SettingsDialog_geometry=@ByteArray(\x1\xd9\xd0\xcb\0\x3\0\0\0\0\x2\xe3\0\0\x1\x30\0\0\x6\x16\0\0\x3\x9d\0\0\x2\xe3\0\0\x1N\0\0\x6\x16\0\0\x3\x9d\0\0\0\0\0\0\0\0\t\xe\0\0\x2\xe3\0\0\x1N\0\0\x6\x16\0\0\x3\x9d)
MainWindow_state=@ByteArray(\0\0\0\xff\0\0\0\0\xfd\0\0\0\x1\0\0\0\x3\0\0\t\xe\0\0\0\xd7\xfc\x1\0\0\0\x1\xfb\0\0\0\xe\0l\0o\0g\0\x44\0o\0\x63\0k\0\0\0\0\0\0\0\t\xe\0\0\0R\0\xff\xff\xff\0\0\t\xe\0\0\x4T\0\0\0\x4\0\0\0\x4\0\0\0\b\0\0\0\b\xfc\0\0\0\x1\0\0\0\x2\0\0\0\x1\0\0\0\xe\0t\0o\0o\0l\0\x42\0\x61\0r\x1\0\0\0\0\xff\xff\xff\xff\0\0\0\0\0\0\0\0)
MainWindow_geometry=@ByteArray(\x1\xd9\xd0\xcb\0\x3\0\0\0\0\0\0\xff\xff\xff\xf9\0\0\t\r\0\0\x4\xe8\0\0\0\v\0\0\0\x1f\0\0\az\0\0\x4w\0\0\0\0\x2\0\0\0\t\xe\0\0\0\0\0\0\0\x17\0\0\t\r\0\0\x4\xe8)
MainWindow_docks_logDock_size=215
MainWindow_menuBar_visibility=true
MainWindow_statusBar_visibility=true
MainWindow_toolBar_visibility=true
toolbar_size=@Size(42 36)
toolbar_button_style=0
MainWindow_splitter_state=@ByteArray(\0\0\0\xff\0\0\0\x1\0\0\0\x2\0\0\x3\xf9\0\0\x2\xb0\x1\xff\xff\xff\xff\x1\0\0\0\x1\0)
MainWindow_categoriesSplitter_state=@ByteArray(\0\0\0\xff\0\0\0\x1\0\0\0\x2\0\0\x1\b\0\0\x3\x16\0\xff\xff\xff\xff\x1\0\0\0\x1\0)
MainWindow_monitor=0
MainWindow_categoriesGroup_visibility=false
MainWindow_espList_state=@ByteArray(\0\0\0\xff\0\0\0\0\0\0\0\x1\0\0\0\0\0\0\0\x2\x1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x2n\0\0\0\x4\x1\x1\0\x1\0\0\0\0\0\0\0\0\x1\0\0\0\x64\xff\xff\xff\xff\0\0\0\x81\0\0\0\0\0\0\0\x4\0\0\x1\xce\0\0\0\x1\0\0\0\0\0\0\0%\0\0\0\x1\0\0\0\0\0\0\0\x33\0\0\0\x1\0\0\0\0\0\0\0H\0\0\0\x1\0\0\0\0\0\0\x3\xe8\0\0\0\0\x46\0\0\0\0)
MainWindow_downloadView_state=@ByteArray(\0\0\0\xff\0\0\0\0\0\0\0\x1\0\0\0\x1\0\0\0\x3\x1\0\0\0\0\0\0\0\0\0\0\0\b\xf0\0\0\0\x4\0\0\0\x4\0\0\0\x64\0\0\0\a\0\0\0\x64\0\0\0\x6\0\0\0\x64\0\0\0\x5\0\0\0\x64\0\0\x3\x80\0\0\0\b\x1\x1\0\0\x1\0\0\0\0\0\0\0\0\0\0\0\x64\xff\xff\xff\xff\0\0\0\x81\0\0\0\0\0\0\0\b\0\0\x2\x62\0\0\0\x1\0\0\0\0\0\0\0V\0\0\0\x1\0\0\0\0\0\0\0\x64\0\0\0\x1\0\0\0\0\0\0\0\x64\0\0\0\x1\0\0\0\0\0\0\0\0\0\0\0\x1\0\0\0\0\0\0\0\0\0\0\0\x1\0\0\0\0\0\0\0\0\0\0\0\x1\0\0\0\0\0\0\0\0\0\0\0\x1\0\0\0\0\0\0\x3\xe8\x1\0\0\0\0\0\0\0\0)
MainWindow_savegameList_state=@ByteArray(\0\0\0\xff\0\0\0\0\0\0\0\x1\0\0\0\x1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x2n\0\0\0\x2\x1\0\0\x1\0\0\0\0\0\0\0\0\0\0\0\0\x64\xff\xff\xff\xff\0\0\0\x81\0\0\0\0\0\0\0\x2\0\0\x1\xa1\0\0\0\x1\0\0\0\0\0\0\0\xcd\0\0\0\x1\0\0\0\0\0\0\x3\xe8\0\0\0\0\x64\0\0\0\0)
MainWindow_dataTree_state=@ByteArray(\0\0\0\xff\0\0\0\0\0\0\0\x1\0\0\0\0\0\0\0\0\x1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x3\x80\0\0\0\x5\x1\x1\0\x1\0\0\0\0\0\0\0\0\0\0\0\0\x64\xff\xff\xff\xff\0\0\0\x81\0\0\0\0\0\0\0\x5\0\0\x1s\0\0\0\x1\0\0\0\0\0\0\0\x81\0\0\0\x1\0\0\0\0\0\0\0\xb2\0\0\0\x1\0\0\0\0\0\0\0\x64\0\0\0\x1\0\0\0\0\0\0\0v\0\0\0\x1\0\0\0\0\0\0\x3\xe8\0\0\0\0\x64\0\0\0\0)
MainWindow_modList_state=@ByteArray(\0\0\0\xff\0\0\0\0\0\0\0\x1\0\0\0\0\0\0\0\t\x1\0\0\0\v\0\0\0\0\0\0\0\x2\0\0\0\x3\0\0\0\x6\0\0\0\x5\0\0\0\a\0\0\0\b\0\0\0\t\0\0\0\x4\0\0\0\n\0\0\0\x1\0\0\0\v\0\0\0\0\0\0\0\n\0\0\0\x1\0\0\0\x2\0\0\0\b\0\0\0\x4\0\0\0\x3\0\0\0\x5\0\0\0\x6\0\0\0\a\0\0\0\t\0\0\0\v\xc2\x3\0\0\0\x5\0\0\0\a\0\0\0Y\0\0\0\x3\0\0\0 \0\0\0\x6\0\0\0 \0\0\0\n\0\0\x1\xb3\0\0\0\x5\0\0\0 \0\0\x5\x42\0\0\0\v\x1\x1\0\x1\0\0\0\0\0\0\0\0\x1\0\0\0'\xff\xff\xff\xff\0\0\0\x81\0\0\0\0\0\0\0\v\0\0\x3\n\0\0\0\x1\0\0\0\0\0\0\0\0\0\0\0\x1\0\0\0\0\0\0\0\x64\0\0\0\x1\0\0\0\0\0\0\0H\0\0\0\x1\0\0\0\0\0\0\0\xac\0\0\0\x1\0\0\0\0\0\0\0|\0\0\0\x1\0\0\0\0\0\0\0\0\0\0\0\x1\0\0\0\0\0\0\0\0\0\0\0\x1\0\0\0\0\0\0\0\0\0\0\0\x1\0\0\0\0\0\0\0\0\0\0\0\x1\0\0\0\0\0\0\0\x64\0\0\0\x1\0\0\0\0\0\0\x3\xe8\x1\0\0\0U\0\0\0\0)
EditExecutablesDialog_geometry=@ByteArray(\x1\xd9\xd0\xcb\0\x3\0\0\0\0\x2\xa7\0\0\x1\x8d\0\0\a2\0\0\x3\xbb\0\0\x2\xa7\0\0\x1\xab\0\0\a2\0\0\x3\xbb\0\0\0\0\0\0\0\0\t\xe\0\0\x2\xa7\0\0\x1\xab\0\0\a2\0\0\x3\xbb)
ModInfoDialog_tabTextSplitter_state=@ByteArray(\0\0\0\xff\0\0\0\x1\0\0\0\x2\0\0\x1\xc8\0\0\x3\x62\0\xff\xff\xff\xff\x1\0\0\0\x1\0)
ModInfoDialog_tabIniSplitter_state=@ByteArray(\0\0\0\xff\0\0\0\x1\0\0\0\x2\0\0\0\xc8\0\0\0\xed\x1\xff\xff\xff\xff\x1\0\0\0\x1\0)
ModInfoDialog_tabImagesSplitter_state=@ByteArray(\0\0\0\xff\0\0\0\x1\0\0\0\x2\0\0\0\x80\0\0\0\x83\0\xff\xff\xff\xff\x1\0\0\0\x1\0)
ModInfoDialog_ESPsSplitter_state=@ByteArray(\0\0\0\xff\0\0\0\x1\0\0\0\x2\0\0\0|\0\0\0\xab\x1\xff\xff\xff\xff\x1\0\0\0\x1\0)
ModInfoDialog_overwriteExpander_state=@ByteArray(\x1)
ModInfoDialog_overwrittenExpander_state=@ByteArray(\x1)
ModInfoDialog_noConflictExpander_state=@ByteArray(\0)
ModInfoDialog_overwriteTree_state=@ByteArray(\0\0\0\xff\0\0\0\0\0\0\0\x1\0\0\0\x1\0\0\0\0\x1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x5(\0\0\0\x2\x1\x1\0\x1\0\0\0\0\0\0\0\0\0\0\0\0\x64\xff\xff\xff\xff\0\0\0\x81\0\0\0\0\0\0\0\x2\0\0\x2\x88\0\0\0\x1\0\0\0\0\0\0\x2\xa0\0\0\0\x1\0\0\0\0\0\0\x3\xe8\0\0\0\0\x64\0\0\0\0)
ModInfoDialog_noConflictTree_state=@ByteArray(\0\0\0\xff\0\0\0\0\0\0\0\x1\0\0\0\x1\0\0\0\0\x1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x64\0\0\0\x1\x1\x1\0\x1\0\0\0\0\0\0\0\0\0\0\0\0\x64\xff\xff\xff\xff\0\0\0\x81\0\0\0\0\0\0\0\x1\0\0\0\x64\0\0\0\x1\0\0\0\0\0\0\x3\xe8\0\0\0\0\x64\0\0\0\0)
ModInfoDialog_overwrittenTree_state=@ByteArray(\0\0\0\xff\0\0\0\0\0\0\0\x1\0\0\0\x1\0\0\0\0\x1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x2\xdd\0\0\0\x2\x1\x1\0\x1\0\0\0\0\0\0\0\0\0\0\0\0\x64\xff\xff\xff\xff\0\0\0\x81\0\0\0\0\0\0\0\x2\0\0\x2y\0\0\0\x1\0\0\0\0\0\0\0\x64\0\0\0\x1\0\0\0\0\0\0\x3\xe8\0\0\0\0\x64\0\0\0\0)
ModInfoDialog_conflictsAdvancedList_state="@ByteArray(\0\0\0\xff\0\0\0\0\0\0\0\x1\0\0\0\x1\0\0\0\0\x1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x1,\0\0\0\x3\x1\x1\0\x1\0\0\0\0\0\0\0\0\0\0\0\0\x64\xff\xff\xff\xff\0\0\0\x81\0\0\0\0\0\0\0\x3\0\0\0\x64\0\0\0\x1\0\0\0\0\0\0\0\x64\0\0\0\x1\0\0\0\0\0\0\0\x64\0\0\0\x1\0\0\0\0\0\0\x3\xe8\0\0\0\0\x64\0\0\0\0)"
ModInfoDialog_filetree_state=@ByteArray(\0\0\0\xff\0\0\0\0\0\0\0\x1\0\0\0\0\0\0\0\0\x1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x5\x30\0\0\0\x4\x1\x1\0\x1\0\0\0\0\0\0\0\0\0\0\0\0\x64\xff\xff\xff\xff\0\0\0\x81\0\0\0\0\0\0\0\x4\0\0\x1\xbf\0\0\0\x1\0\0\0\0\0\0\0\x64\0\0\0\x1\0\0\0\0\0\0\0\x64\0\0\0\x1\0\0\0\0\0\0\x2\xa9\0\0\0\x1\0\0\0\0\0\0\x3\xe8\0\0\0\0\x64\0\0\0\0)
ModInfoDialog_geometry=@ByteArray(\x1\xd9\xd0\xcb\0\x3\0\0\0\0\x1\xca\0\0\x1\x1b\0\0\a\x17\0\0\x4\x1e\0\0\x1\xca\0\0\x1\x39\0\0\a\x17\0\0\x4\x1e\0\0\0\0\0\0\0\0\t\xe\0\0\x1\xca\0\0\x1\x39\0\0\a\x17\0\0\x4\x1e)
PreviewDialog_geometry=@ByteArray(\x1\xd9\xd0\xcb\0\x3\0\0\0\0\x3\r\0\0\x1\x35\0\0\x5\xec\0\0\x3\x99\0\0\x3\r\0\0\x1S\0\0\x5\xec\0\0\x3\x99\0\0\0\0\0\0\0\0\t\xe\0\0\x3\r\0\0\x1S\0\0\x5\xec\0\0\x3\x99)
ProfilesDialog_geometry=@ByteArray(\x1\xd9\xd0\xcb\0\x3\0\0\0\0\x3\x8c\0\0\x1\xb2\0\0\x5m\0\0\x3\x1b\0\0\x3\x8c\0\0\x1\xd0\0\0\x5m\0\0\x3\x1b\0\0\0\0\0\0\0\0\t\xe\0\0\x3\x8c\0\0\x1\xd0\0\0\x5m\0\0\x3\x1b)
__overwriteDialog_geometry=@ByteArray(\x1\xd9\xd0\xcb\0\x3\0\0\0\0\x2\x82\0\0\x1\x8c\0\0\a\xa9\0\0\x4\xa8\0\0\x2\x82\0\0\x1\xaa\0\0\a\xa9\0\0\x4\xa8\0\0\0\0\0\0\0\0\t\xe\0\0\x2\x82\0\0\x1\xaa\0\0\a\xa9\0\0\x4\xa8)
__overwriteDialog_filesView_state=@ByteArray(\0\0\0\xff\0\0\0\0\0\0\0\x1\0\0\0\0\0\0\0\0\x1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x4\xfe\0\0\0\x4\x1\x1\0\x1\0\0\0\0\0\0\0\0\0\0\0\0\x64\xff\xff\xff\xff\0\0\0\x81\0\0\0\0\0\0\0\x4\0\0\x1\xd7\0\0\0\x1\0\0\0\0\0\0\0\x64\0\0\0\x1\0\0\0\0\0\0\0\x64\0\0\0\x1\0\0\0\0\0\0\x2_\0\0\0\x1\0\0\0\0\0\0\x3\xe8\0\0\0\0\x64\0\0\0\0)
ProblemsDialog_geometry=@ByteArray(\x1\xd9\xd0\xcb\0\x3\0\0\0\0\x3^\0\0\x1\x9c\0\0\x5\x9b\0\0\x3\x31\0\0\x3^\0\0\x1\xba\0\0\x5\x9b\0\0\x3\x31\0\0\0\0\0\0\0\0\t\xe\0\0\x3^\0\0\x1\xba\0\0\x5\x9b\0\0\x3\x31)
CategoriesDialog_geometry=@ByteArray(\x1\xd9\xd0\xcb\0\x3\0\0\0\0\x1\xd3\0\0\x1T\0\0\x4\x99\0\0\x3#\0\0\x1\xd3\0\0\x1r\0\0\x4\x99\0\0\x3#\0\0\0\0\0\0\0\0\t\xe\0\0\x1\xd3\0\0\x1r\0\0\x4\x99\0\0\x3#)
ListDialog_geometry=@ByteArray(\x1\xd9\xd0\xcb\0\x3\0\0\0\0\x3\xfa\0\0\0\xfe\0\0\x4\xff\0\0\x3^\0\0\x3\xfa\0\0\x1\x1c\0\0\x4\xff\0\0\x3^\0\0\0\0\0\0\0\0\t\xe\0\0\x3\xfa\0\0\x1\x1c\0\0\x4\xff\0\0\x3^)
[Servers]
size=0
[pluginBlacklist]
size=0
@@ -1,11 +1,11 @@
[General]
gameName=spt
modid=0
version=d2025.1.1.0
version=d2025.1.15.0
newestVersion=
category="1,2"
category="1,"
nexusFileStatus=1
installationFile=Default Epic.zip
installationFile=MoxoPixel-BlackCore.zip
repository=Nexus
ignoredVersion=
comments=
@@ -15,7 +15,7 @@ url=
hasCustomURL=true
lastNexusQuery=
lastNexusUpdate=
nexusLastModified=2025-01-01T06:47:45Z
nexusLastModified=2025-01-16T01:49:42Z
nexusCategory=0
converted=false
validated=false
@@ -0,0 +1,556 @@
{
"manifest": [
{
"key":"tactical_all_insight_wmx200_retex.bundle",
"dependencyKeys":[]
},
{
"key":"mag_stanag_hk_polymer_mag_556x45_30_retex.bundle",
"dependencyKeys":[]
},
{
"key":"handguard_ar15_dd_ris_ii_fsp_9,5_retex.bundle",
"dependencyKeys":[]
},
{
"key":"scope_all_eotech_exps3_retex.bundle",
"dependencyKeys":[
"scope_all_eotech_exps3_gloss_nrm_retex.bundle",
"scope_all_eotech_exps3_mesh_retex.bundle",
"scope_all_eotech_exps3_tan_textures_retex.bundle",
"scope_all_eotech_xps3_textures_retex.bundle"
]
},
{
"key":"scope_all_eotech_exps3_gloss_nrm_retex.bundle",
"dependencyKeys":[]
},
{
"key":"scope_all_eotech_exps3_tan_textures_retex.bundle",
"dependencyKeys":[]
},
{
"key":"scope_all_eotech_xps3_textures_retex.bundle",
"dependencyKeys":[]
},
{
"key":"scope_all_eotech_exps3_mesh_retex.bundle",
"dependencyKeys":[
"scope_all_eotech_exps3_gloss_nrm_retex.bundle",
"scope_all_eotech_exps3_tan_textures_retex.bundle",
"scope_all_eotech_xps3_textures_retex.bundle"
]
},
{
"key":"tactical_all_holosun_ls321_retex.bundle",
"dependencyKeys":[
"assets/commonassets/physics/physicsmaterials.bundle",
"assets/content/textures/holemanager/glow_particle_bright.bundle",
"assets/standard assets/effects/lightcookies/textures/flashlightcookie.bundle",
"assets/systems/effects/collimator.bundle",
"assets/systems/effects/laserbeam/laser.bundle",
"assets/systems/effects/multiflare/multiflare.bundle",
"assets/systems/effects/nightvision.bundle",
"cubemaps",
"shaders"
]
},
{
"key":"m4a1_black_lines/textures/client_assets.bundle",
"dependencyKeys":[
]
},
{
"key":"m4a1_black_lines/client_assets.bundle",
"dependencyKeys":[
"m4a1_black_lines/textures/client_assets.bundle",
"cubemaps",
"shaders"
]
},
{
"key":"m4a1_black_lines/weapon_colt_m4a1_556x45_container.bundle",
"dependencyKeys":[
"assets/commonassets/physics/physicsmaterials.bundle",
"assets/content/audio/banks/m4a1.bundle",
"assets/content/audio/blendoptions/assets.bundle",
"assets/content/audio/weapons/ak74.bundle",
"assets/content/audio/weapons/generic",
"assets/content/audio/weapons/m4a1.bundle",
"assets/content/weapons/additional_hands/client_assets.bundle",
"assets/content/weapons/animations/simple_animations.bundle",
"assets/content/weapons/animations/spirit_animations.bundle",
"m4a1_black_lines/client_assets.bundle",
"m4a1_black_lines/textures/client_assets.bundle",
"assets/content/weapons/tx15/client_assets.bundle",
"assets/content/weapons/tx15/textures/client_assets.bundle",
"assets/content/weapons/tx15/weapon_lone_star_tx15_designated_marksman_556x45_container.bundle",
"assets/content/weapons/weapon_root_anim_fix.bundle",
"assets/content/weapons/wip/kibas tuning prefabs/muzzlejets_templates/default_assets.bundle",
"assets/systems/effects/heathaze/defaultheathaze.bundle",
"assets/systems/effects/muzzleflash/muzzleflash.bundle",
"assets/systems/effects/smoke.bundle",
"cubemaps",
"shaders"
]
},
{
"key":"ak103_black_lines/textures/client_assets.bundle",
"dependencyKeys":[
]
},
{
"key":"ak103_black_lines/client_assets.bundle",
"dependencyKeys":[
"ak103_black_lines/textures/client_assets.bundle",
"cubemaps",
"shaders"
]
},
{
"key":"ak103_black_lines/weapon_izhmash_ak103_762x39_container.bundle",
"dependencyKeys":[
"assets/commonassets/physics/physicsmaterials.bundle",
"assets/content/audio/banks/ak74.bundle",
"assets/content/audio/banks/akm.bundle",
"assets/content/audio/blendoptions/assets.bundle",
"assets/content/audio/weapons/ak74.bundle",
"assets/content/audio/weapons/akm.bundle",
"assets/content/audio/weapons/generic",
"assets/content/audio/weapons/saiga12.bundle",
"assets/content/items/mods/handguards/handguard_pp-19-01_izhmash_vityaz_std_plastic_textures.bundle",
"assets/content/weapons/additional_hands/client_assets.bundle",
"ak103_black_lines/client_assets.bundle",
"ak103_black_lines/textures/client_assets.bundle",
"assets/content/weapons/ak100/weapon_izhmash_ak104_762x39_container.bundle",
"assets/content/weapons/ak100/weapon_izhmash_ak105_545x39_container.bundle",
"assets/content/weapons/ak74m/textures/client_assets.bundle",
"assets/content/weapons/animations/simple_animations.bundle",
"assets/content/weapons/animations/spirit_animations.bundle",
"assets/content/weapons/pp-19-01/textures/client_assets.bundle",
"assets/content/weapons/weapon_root_anim_fix.bundle",
"assets/content/weapons/wip/kibas tuning prefabs/muzzlejets_templates/default_assets.bundle",
"assets/systems/effects/heathaze/defaultheathaze.bundle",
"assets/systems/effects/muzzleflash/muzzleflash.bundle",
"assets/systems/effects/smoke.bundle",
"cubemaps",
"shaders"
]
},
{
"key":"reciever_ak_akademia_bastion_retex.bundle",
"dependencyKeys":[
"assets/commonassets/physics/physicsmaterials.bundle",
"cubemaps",
"shaders"
]
},
{
"key":"rsass_black/weapon_remington_r11_rsass_762x51_container.bundle",
"dependencyKeys":[
"assets/commonassets/physics/physicsmaterials.bundle",
"assets/content/audio/banks/rsass.bundle",
"assets/content/audio/blendoptions/assets.bundle",
"assets/content/audio/weapons/ak74.bundle",
"assets/content/audio/weapons/generic",
"assets/content/audio/weapons/mpx.bundle",
"assets/content/weapons/additional_hands/client_assets.bundle",
"assets/content/weapons/animations/simple_animations.bundle",
"assets/content/weapons/animations/spirit_animations.bundle",
"rsass_black/client_assets.bundle",
"rsass_black/textures/client_assets.bundle",
"assets/content/weapons/weapon_root_anim_fix.bundle",
"assets/content/weapons/wip/kibas tuning prefabs/muzzlejets_templates/default_assets.bundle",
"assets/systems/effects/heathaze/defaultheathaze.bundle",
"assets/systems/effects/muzzleflash/muzzleflash.bundle",
"assets/systems/effects/smoke.bundle",
"cubemaps",
"shaders"
]
},
{
"key":"rsass_black/client_assets.bundle",
"dependencyKeys":[
"rsass_black/textures/client_assets.bundle",
"cubemaps",
"shaders"
]
},
{
"key":"rsass_black/textures/client_assets.bundle",
"dependencyKeys":[
]
},
{
"key":"mk47_black_lines/textures/client_assets.bundle",
"dependencyKeys":[
]
},
{
"key":"mk47_black_lines/client_assets.bundle",
"dependencyKeys":[
"mk47_black_lines/textures/client_assets.bundle",
"cubemaps",
"shaders"
]
},
{
"key":"mk47_black_lines/weapon_cmmg_mk47_762x39_container.bundle",
"dependencyKeys":[
"assets/commonassets/physics/physicsmaterials.bundle",
"assets/content/audio/banks/mp5.bundle",
"assets/content/audio/blendoptions/assets.bundle",
"assets/content/audio/weapons/ak74.bundle",
"assets/content/audio/weapons/akm/instrumental.bundle",
"assets/content/audio/weapons/generic",
"assets/content/audio/weapons/mp5.bundle",
"assets/content/audio/weapons/mpx.bundle",
"assets/content/weapons/additional_hands/client_assets.bundle",
"assets/content/weapons/animations/simple_animations.bundle",
"assets/content/weapons/animations/spirit_animations.bundle",
"assets/content/weapons/m4a1/client_assets.bundle",
"assets/content/weapons/m4a1/textures/client_assets.bundle",
"mk47_black_lines/client_assets.bundle",
"mk47_black_lines/textures/client_assets.bundle",
"assets/content/weapons/weapon_root_anim_fix.bundle",
"assets/content/weapons/wip/kibas tuning prefabs/muzzlejets_templates/default_assets.bundle",
"assets/systems/effects/heathaze/defaultheathaze.bundle",
"assets/systems/effects/muzzleflash/muzzleflash.bundle",
"assets/systems/effects/smoke.bundle",
"cubemaps",
"shaders"
]
},
{
"key":"reciever_mk47_cmmg_mk47_std_retex.bundle",
"dependencyKeys":[
]
},
{
"key":"tactical_all_wilcox_raptar_es_retex.bundle",
"dependencyKeys":[
"assets/commonassets/physics/physicsmaterials.bundle",
"assets/content/textures/holemanager/glow_particle_bright.bundle",
"assets/standard assets/effects/lightcookies/textures/flashlightcookie.bundle",
"assets/systems/effects/collimator.bundle",
"assets/systems/effects/laserbeam/laser.bundle",
"assets/systems/effects/multiflare/multiflare.bundle",
"assets/systems/effects/nightvision.bundle",
"cubemaps",
"shaders"
]
},
{
"key":"scope_30mm_razor_hd_gen_2_1_6x24_retex.bundle",
"dependencyKeys":[
"assets/commonassets/physics/physicsmaterials.bundle",
"assets/content/textures/holemanager/round_spec_mask.bundle",
"assets/systems/effects/opticsight/opticsightsmasks.bundle",
"cubemaps",
"shaders"
]
},
{
"key":"reciever_ar15_noveske_gen3_retex.bundle",
"dependencyKeys":[
]
},
{
"key":"stock_vepr_molot_vpo-101_std_wood_retex.bundle",
"dependencyKeys":[
]
},
{
"key":"stock_m14_troy_sass_chassis_retex.bundle",
"dependencyKeys":[
]
},
{
"key":"silencer_mount_silencerco_hybrid_46_multi_retex.bundle",
"dependencyKeys":[]
},
{
"key":"mag_aug_steyr_std_556x45_30_retex.bundle",
"dependencyKeys":[]
},
{
"key":"stock_ak_zenit_pt_1_retex.bundle",
"dependencyKeys":[]
},
{
"key":"pistolgrip_ak_magpul_moe_ak_retex.bundle",
"dependencyKeys":[]
},
{
"key":"gas_block_akp_slr_ak_railed_gas_tube_retex.bundle",
"dependencyKeys":[]
},
{
"key":"reciever_ak_texas_weapon_systems_dog_leg_rail_gen_3_retex.bundle",
"dependencyKeys":[]
},
{
"key":"handguard_ar15_precision_reflex_carbon_fiber_delta_gen_3_retex.bundle",
"dependencyKeys":[]
},
{
"key":"helmet_armor_slaap.bundle",
"dependencyKeys":[]
},
{
"key":"reciever_glock_glock_17_std_retex.bundle",
"dependencyKeys":[]
},
{
"key":"reciever_glock_gspc_viper_slide_cut_retex.bundle",
"dependencyKeys":[]
},
{
"key":"m4a1_flame/textures/client_assets.bundle",
"dependencyKeys":[
]
},
{
"key":"m4a1_flame/client_assets.bundle",
"dependencyKeys":[
"m4a1_flame/textures/client_assets.bundle",
"cubemaps",
"shaders"
]
},
{
"key":"m4a1_flame/weapon_colt_m4a1_556x45_container.bundle",
"dependencyKeys":[
"assets/commonassets/physics/physicsmaterials.bundle",
"assets/content/audio/banks/m4a1.bundle",
"assets/content/audio/blendoptions/assets.bundle",
"assets/content/audio/weapons/ak74.bundle",
"assets/content/audio/weapons/generic",
"assets/content/audio/weapons/m4a1.bundle",
"assets/content/weapons/additional_hands/client_assets.bundle",
"assets/content/weapons/animations/simple_animations.bundle",
"assets/content/weapons/animations/spirit_animations.bundle",
"m4a1_flame/client_assets.bundle",
"m4a1_flame/textures/client_assets.bundle",
"assets/content/weapons/tx15/client_assets.bundle",
"assets/content/weapons/tx15/textures/client_assets.bundle",
"assets/content/weapons/tx15/weapon_lone_star_tx15_designated_marksman_556x45_container.bundle",
"assets/content/weapons/weapon_root_anim_fix.bundle",
"assets/content/weapons/wip/kibas tuning prefabs/muzzlejets_templates/default_assets.bundle",
"assets/systems/effects/heathaze/defaultheathaze.bundle",
"assets/systems/effects/muzzleflash/muzzleflash.bundle",
"assets/systems/effects/smoke.bundle",
"cubemaps",
"shaders"
]
},
{
"key":"foregrip_all_bcm_mod_3_new.bundle",
"dependencyKeys":[]
},
{
"key":"mag_ak74_izhmash_6l23_545x39_30_retex.bundle",
"dependencyKeys":[]
},
{
"key":"m4a1_new/textures/client_assets.bundle",
"dependencyKeys":[
]
},
{
"key":"m4a1_new/client_assets.bundle",
"dependencyKeys":[
"m4a1_new/textures/client_assets.bundle",
"cubemaps",
"shaders"
]
},
{
"key":"m4a1_new/weapon_colt_m4a1_556x45_container.bundle",
"dependencyKeys":[
"assets/commonassets/physics/physicsmaterials.bundle",
"assets/content/audio/banks/m4a1.bundle",
"assets/content/audio/blendoptions/assets.bundle",
"assets/content/audio/weapons/ak74.bundle",
"assets/content/audio/weapons/generic",
"assets/content/audio/weapons/m4a1.bundle",
"assets/content/weapons/additional_hands/client_assets.bundle",
"assets/content/weapons/animations/simple_animations.bundle",
"assets/content/weapons/animations/spirit_animations.bundle",
"m4a1_new/client_assets.bundle",
"m4a1_new/textures/client_assets.bundle",
"assets/content/weapons/tx15/client_assets.bundle",
"assets/content/weapons/tx15/textures/client_assets.bundle",
"assets/content/weapons/tx15/weapon_lone_star_tx15_designated_marksman_556x45_container.bundle",
"assets/content/weapons/weapon_root_anim_fix.bundle",
"assets/content/weapons/wip/kibas tuning prefabs/muzzlejets_templates/default_assets.bundle",
"assets/systems/effects/heathaze/defaultheathaze.bundle",
"assets/systems/effects/muzzleflash/muzzleflash.bundle",
"assets/systems/effects/smoke.bundle",
"cubemaps",
"shaders"
]
},
{
"key":"reciever_ar15_vltor_mur-1s_retex.bundle",
"dependencyKeys":[
]
},
{
"key":"mag_ar10_lancer_l7_awm_762x51_20.bundle",
"dependencyKeys":[
]
},
{
"key":"mag_ar10_lancer_l7_awm_762x51_25.bundle",
"dependencyKeys":[
]
},
{
"key":"spear_black/textures/client_assets.bundle",
"dependencyKeys":[
]
},
{
"key":"spear_black/client_assets.bundle",
"dependencyKeys":[
"spear_black/textures/client_assets.bundle",
"cubemaps",
"shaders"
]
},
{
"key":"spear_black/weapon_sig_mcx_spear_68x51_container.bundle",
"dependencyKeys":[
"assets/commonassets/physics/physicsmaterials.bundle",
"assets/content/audio/blendoptions/assets.bundle",
"assets/content/audio/weapons/ak74.bundle",
"assets/content/audio/weapons/generic",
"assets/content/weapons/additional_hands/client_assets.bundle",
"assets/content/weapons/animations/simple_animations.bundle",
"assets/content/weapons/animations/spirit_animations.bundle",
"spear_black/client_assets.bundle",
"spear_black/textures/client_assets.bundle",
"assets/content/weapons/weapon_root_anim_fix.bundle",
"assets/content/weapons/wip/kibas tuning prefabs/muzzlejets_templates/default_assets.bundle",
"assets/systems/effects/heathaze/defaultheathaze.bundle",
"assets/systems/effects/muzzleflash/muzzleflash.bundle",
"assets/systems/effects/smoke.bundle",
"cubemaps",
"shaders"
]
},
{
"key":"spear_black/reciever_mcx_sig_spear_upper.bundle",
"dependencyKeys":[
"assets/commonassets/physics/physicsmaterials.bundle",
"spear_black/client_assets.bundle",
"spear_black/textures/client_assets.bundle",
"cubemaps",
"shaders"
]
},
{
"key":"pistolgrip_ar15_sig_reduced_angle_pistol_grip_ct_retex.bundle",
"dependencyKeys":[
]
},
{
"key":"handguard_mcx_sig_spear_m_lok_retex.bundle",
"dependencyKeys":[]
},
{
"key":"silencer_clutchlok_sig_slx68_mg_qd_suppressor_68x51_retex.bundle",
"dependencyKeys":[]
},
{
"key":"charge_spear_sig_spear_std_retex.bundle",
"dependencyKeys":[]
},
{
"key":"stock_ar15_magpul_moe_sl_k_carbine_ct_retex.bundle",
"dependencyKeys":[]
},
{
"key":"stock_base_sig_low_profile_tube_ct_retex.bundle",
"dependencyKeys":[]
},
{
"key":"balaclava/item_equipment_facecover_balaclava_black.bundle",
"dependencyKeys":[
"balaclava/wildman01head_textures_black.bundle"
]
},
{
"key":"balaclava/wildman01head_textures_black.bundle",
"dependencyKeys":[]
},
{
"key":"glasses/item_equipment_glasses_npp_retex.bundle",
"dependencyKeys":[]
},
{
"key":"rigs/cr_arscpc_retex.bundle",
"dependencyKeys":[]
},
{
"key":"rigs/item_equipment_rig_carriertactec_retex.bundle",
"dependencyKeys":[]
},
{
"key":"rigs/item_equipment_rig_tv110_retex.bundle",
"dependencyKeys":[]
},
{
"key":"rigs/item_equipment_rig_cryeavs_retex.bundle",
"dependencyKeys":[]
},
{
"key":"scope_all_vortex_razor_amg_uh-1_retex.bundle",
"dependencyKeys":[
"assets/commonassets/physics/physicsmaterials.bundle",
"assets/content/textures/holemanager/eotech_spec_mask.bundle",
"cubemaps",
"shaders"
]
},
{
"key":"tactical_all_insight_anpeq15_retex.bundle",
"dependencyKeys":[
"assets/commonassets/physics/physicsmaterials.bundle",
"assets/content/textures/holemanager/glow_particle_bright.bundle",
"assets/standard assets/effects/lightcookies/textures/flashlightcookie.bundle",
"assets/systems/effects/collimator.bundle",
"assets/systems/effects/laserbeam/laser.bundle",
"assets/systems/effects/multiflare/multiflare.bundle",
"assets/systems/effects/nightvision.bundle",
"cubemaps",
"shaders"
]
},
{
"key":"stock_ar15_fab_defense_gl_core_retex.bundle",
"dependencyKeys":[
]
},
{
"key":"scope_30mm_sig_tango6t_1_6x24_retex.bundle",
"dependencyKeys":[
"assets/commonassets/physics/physicsmaterials.bundle",
"assets/content/textures/holemanager/round_spec_mask.bundle",
"assets/systems/effects/opticsight/opticsightsmasks.bundle",
"cubemaps",
"shaders"
]
},
{
"key":"nvg_l3_gpnvg-18_anvis_retex.bundle",
"dependencyKeys":[
"assets/commonassets/physics/physicsmaterials.bundle",
"assets/content/items/equipment/glasses_6b34/glasses_6b34_glass_textures",
"cubemaps",
"shaders"
]
}
]
}
@@ -0,0 +1,603 @@
{
"ItemPresets": {
"6783f24f861dfacffe36b138": {
"_changeWeaponName": false,
"_encyclopedia": "672e37d19f1683101780773b",
"_id": "6783f24f861dfacffe36b138",
"_items": [
{
"_id": "6783f25b69d649d493cda1fd",
"_tpl": "672e37d19f1683101780773b",
"upd": {
"Repairable": {
"Durability": 100,
"MaxDurability": 100
}
}
},
{
"_id": "6783f26abcf5805ba9248ad7",
"_tpl": "55d4b9964bdc2d1d4e8b456e",
"parentId": "6783f25b69d649d493cda1fd",
"slotId": "mod_pistol_grip"
},
{
"_id": "6783f26d3b2ca6db3f36b858",
"_tpl": "55d4887d4bdc2d962f8b4570",
"parentId": "6783f25b69d649d493cda1fd",
"slotId": "mod_magazine"
},
{
"_id": "6783f2723a07e8c6a8006e9f",
"_tpl": "672e37d1249244ae3a50bb2f",
"parentId": "6783f25b69d649d493cda1fd",
"slotId": "mod_reciever"
},
{
"_id": "6783f29a304ff60a67653ddb",
"_tpl": "55d3632e4bdc2d972f8b4569",
"parentId": "6783f2723a07e8c6a8006e9f",
"slotId": "mod_barrel"
},
{
"_id": "6783f29f017667af4aeda8df",
"_tpl": "544a38634bdc2d58388b4568",
"parentId": "6783f29a304ff60a67653ddb",
"slotId": "mod_muzzle"
},
{
"_id": "6783f2a148624b6f5fe0a317",
"_tpl": "5ae30e795acfc408fb139a0b",
"parentId": "6783f29a304ff60a67653ddb",
"slotId": "mod_gas_block"
},
{
"_id": "6783f2a88b7b6cd3c9225511",
"_tpl": "5ae30db85acfc408fb139a05",
"parentId": "6783f2723a07e8c6a8006e9f",
"slotId": "mod_handguard"
},
{
"_id": "6783f2ad374903cfc652f22f",
"_tpl": "637f57a68d137b27f70c4968",
"parentId": "6783f2a88b7b6cd3c9225511",
"slotId": "mod_handguard"
},
{
"_id": "6783f2aeb598721f40ef1263",
"_tpl": "5ae30bad5acfc400185c2dc4",
"parentId": "6783f2723a07e8c6a8006e9f",
"slotId": "mod_sight_rear"
},
{
"_id": "6783f2af7cf3b743d3d8c1e2",
"_tpl": "5649be884bdc2d79388b4577",
"parentId": "6783f25b69d649d493cda1fd",
"slotId": "mod_stock"
},
{
"_id": "6783f2b54115cf68d3ffa632",
"_tpl": "55d4ae6c4bdc2d8b2f8b456e",
"parentId": "6783f2af7cf3b743d3d8c1e2",
"slotId": "mod_stock_000"
},
{
"_id": "6783f2b66dc7254a0401b1ca",
"_tpl": "55d44fd14bdc2d962f8b456e",
"parentId": "6783f25b69d649d493cda1fd",
"slotId": "mod_charge"
}
],
"_name": "M4A1 Std Painter Edition",
"_parent": "6783f25b69d649d493cda1fd",
"_type": "Preset"
},
"6783f192c8a5270c18aad6b6": {
"_changeWeaponName": false,
"_encyclopedia": "672e37d1ddaf7c656e3a634c",
"_id": "6783f192c8a5270c18aad6b6",
"_items": [
{
"_id": "6783f1a47ef435b43580168c",
"_tpl": "672e37d1ddaf7c656e3a634c",
"upd": {
"Repairable": {
"Durability": 100,
"MaxDurability": 100
}
}
},
{
"_id": "6783f1b85be1b42bf29e4a61",
"_tpl": "55d4b9964bdc2d1d4e8b456e",
"parentId": "6783f1a47ef435b43580168c",
"slotId": "mod_pistol_grip"
},
{
"_id": "6783f1bb8ce2bb9545fae1d8",
"_tpl": "55d4887d4bdc2d962f8b4570",
"parentId": "6783f1a47ef435b43580168c",
"slotId": "mod_magazine"
},
{
"_id": "6783f1c160f9c16d7f779a4d",
"_tpl": "55d355e64bdc2d962f8b4569",
"parentId": "6783f1a47ef435b43580168c",
"slotId": "mod_reciever"
},
{
"_id": "6783f1d493fa264e4493ac2e",
"_tpl": "55d3632e4bdc2d972f8b4569",
"parentId": "6783f1c160f9c16d7f779a4d",
"slotId": "mod_barrel"
},
{
"_id": "6783f1d9be58dbc9b2a069ba",
"_tpl": "544a38634bdc2d58388b4568",
"parentId": "6783f1d493fa264e4493ac2e",
"slotId": "mod_muzzle"
},
{
"_id": "6783f1daae07965124acac83",
"_tpl": "5ae30e795acfc408fb139a0b",
"parentId": "6783f1d493fa264e4493ac2e",
"slotId": "mod_gas_block"
},
{
"_id": "6783f1ddde94724c8bd6ca16",
"_tpl": "5ae30db85acfc408fb139a05",
"parentId": "6783f1c160f9c16d7f779a4d",
"slotId": "mod_handguard"
},
{
"_id": "6783f1e275d0b1ed88572ad0",
"_tpl": "637f57a68d137b27f70c4968",
"parentId": "6783f1ddde94724c8bd6ca16",
"slotId": "mod_handguard"
},
{
"_id": "6783f1e3fbc6c6dbf0aadc86",
"_tpl": "5ae30bad5acfc400185c2dc4",
"parentId": "6783f1c160f9c16d7f779a4d",
"slotId": "mod_sight_rear"
},
{
"_id": "6783f1ec39e6076911b5df9c",
"_tpl": "5649be884bdc2d79388b4577",
"parentId": "6783f1a47ef435b43580168c",
"slotId": "mod_stock"
},
{
"_id": "6783f1f09bad1af82a378d05",
"_tpl": "55d4ae6c4bdc2d8b2f8b456e",
"parentId": "6783f1ec39e6076911b5df9c",
"slotId": "mod_stock_000"
},
{
"_id": "6783f1f235ede9255929f2d4",
"_tpl": "55d44fd14bdc2d962f8b456e",
"parentId": "6783f1a47ef435b43580168c",
"slotId": "mod_charge"
}
],
"_name": "M4A1 Std Flames",
"_parent": "6783f1a47ef435b43580168c",
"_type": "Preset"
},
"6783f0fbb5c5bfbb971871e1": {
"_changeWeaponName": false,
"_encyclopedia": "672e37d1179b7b969b7577cb",
"_id": "6783f0fbb5c5bfbb971871e1",
"_items": [
{
"_id": "6783f10174bf20e471c5c055",
"_tpl": "672e37d1179b7b969b7577cb",
"upd": {
"Repairable": {
"Durability": 100,
"MaxDurability": 100
}
}
},
{
"_id": "6783f11512857c267b254af7",
"_tpl": "55d4b9964bdc2d1d4e8b456e",
"parentId": "6783f10174bf20e471c5c055",
"slotId": "mod_pistol_grip"
},
{
"_id": "6783f11aec8108543017f1e3",
"_tpl": "55d4887d4bdc2d962f8b4570",
"parentId": "6783f10174bf20e471c5c055",
"slotId": "mod_magazine"
},
{
"_id": "6783f1205747a3ea48865e73",
"_tpl": "55d355e64bdc2d962f8b4569",
"parentId": "6783f10174bf20e471c5c055",
"slotId": "mod_reciever"
},
{
"_id": "6783f1350fbe98026207e7ea",
"_tpl": "55d3632e4bdc2d972f8b4569",
"parentId": "6783f1205747a3ea48865e73",
"slotId": "mod_barrel"
},
{
"_id": "6783f13b8484c0c25a66be35",
"_tpl": "544a38634bdc2d58388b4568",
"parentId": "6783f1350fbe98026207e7ea",
"slotId": "mod_muzzle"
},
{
"_id": "6783f13dc1acd3ecae24270f",
"_tpl": "5ae30e795acfc408fb139a0b",
"parentId": "6783f1350fbe98026207e7ea",
"slotId": "mod_gas_block"
},
{
"_id": "6783f1488a3d2dc4157c8758",
"_tpl": "5ae30db85acfc408fb139a05",
"parentId": "6783f1205747a3ea48865e73",
"slotId": "mod_handguard"
},
{
"_id": "6783f151960a80ad5f9745ae",
"_tpl": "637f57a68d137b27f70c4968",
"parentId": "6783f1488a3d2dc4157c8758",
"slotId": "mod_handguard"
},
{
"_id": "6783f154906b450be0b3182f",
"_tpl": "5ae30bad5acfc400185c2dc4",
"parentId": "6783f1205747a3ea48865e73",
"slotId": "mod_sight_rear"
},
{
"_id": "6783f15600d12159f91920f6",
"_tpl": "5649be884bdc2d79388b4577",
"parentId": "6783f10174bf20e471c5c055",
"slotId": "mod_stock"
},
{
"_id": "6783f15bc0fe63d6d241fb9b",
"_tpl": "55d4ae6c4bdc2d8b2f8b456e",
"parentId": "6783f15600d12159f91920f6",
"slotId": "mod_stock_000"
},
{
"_id": "6783f1f861bc1198d4d14f7c",
"_tpl": "55d44fd14bdc2d962f8b456e",
"parentId": "6783f10174bf20e471c5c055",
"slotId": "mod_charge"
}
],
"_name": "M4A1 Std Topo",
"_parent": "6783f10174bf20e471c5c055",
"_type": "Preset"
},
"6783f026a570e11e98538c25": {
"_changeWeaponName": false,
"_encyclopedia": "672e37d1e35a6ec6e6997492",
"_id": "6783f026a570e11e98538c25",
"_items": [
{
"_id": "6783f04c9ff3e61038c7a73b",
"_tpl": "672e37d1e35a6ec6e6997492"
},
{
"_id": "6783f05f37f27dd00e59aa24",
"_tpl": "59c6633186f7740cf0493bb9",
"parentId": "6783f04c9ff3e61038c7a73b",
"slotId": "mod_gas_block"
},
{
"_id": "6783f07124277c3fd1890147",
"_tpl": "5648b1504bdc2d9d488b4584",
"parentId": "6783f05f37f27dd00e59aa24",
"slotId": "mod_handguard"
},
{
"_id": "6783f0741ec1081b46650491",
"_tpl": "5ac72e7d5acfc40016339a02",
"parentId": "6783f04c9ff3e61038c7a73b",
"slotId": "mod_muzzle"
},
{
"_id": "6783f0764bac8452114f4a95",
"_tpl": "5649ade84bdc2d1b2b8b4587",
"parentId": "6783f04c9ff3e61038c7a73b",
"slotId": "mod_pistol_grip"
},
{
"_id": "6783f0770459d79d0f33b9da",
"_tpl": "672e37d10c5f88d8ed0d056a",
"parentId": "6783f04c9ff3e61038c7a73b",
"slotId": "mod_reciever"
},
{
"_id": "6783f07a137b256bffe1cfb1",
"_tpl": "5ac50c185acfc400163398d4",
"parentId": "6783f04c9ff3e61038c7a73b",
"slotId": "mod_stock"
},
{
"_id": "6783f07c8853c5e4efc96806",
"_tpl": "5ac66bea5acfc43b321d4aec",
"parentId": "6783f04c9ff3e61038c7a73b",
"slotId": "mod_magazine"
}
],
"_name": "AK-103 Default Topo",
"_parent": "6783f04c9ff3e61038c7a73b",
"_type": "Preset"
},
"6783ec2851c792b686291cb9": {
"_changeWeaponName": false,
"_encyclopedia": "672e37d17f433cdb29072bc8",
"_id": "6783ec2851c792b686291cb9",
"_items": [
{
"_id": "6783ec33c8d50fdb6b63d3e9",
"_tpl": "672e37d17f433cdb29072bc8",
"upd": {
"FireMode": {
"FireMode": "single"
},
"Repairable": {
"Durability": 100,
"MaxDurability": 100
}
}
},
{
"_id": "657eb3773271d8578610fe2a",
"_tpl": "672e37d1861c12c7e1d94089",
"parentId": "6783ec33c8d50fdb6b63d3e9",
"slotId": "mod_pistol_grip"
},
{
"_id": "657eb3773271d8578610fe2b",
"_tpl": "672e37d19811257c1de39e6d",
"parentId": "6783ec33c8d50fdb6b63d3e9",
"slotId": "mod_magazine"
},
{
"_id": "6783ec4cf0b00cd50d9c2a87",
"_tpl": "672e37d133cc1fb4424ddb4c",
"parentId": "6783ec33c8d50fdb6b63d3e9",
"slotId": "mod_reciever"
},
{
"_id": "6783ec6e1a49dfd7571ae44e",
"_tpl": "5b2389515acfc4771e1be0c0",
"parentId": "6783ec4cf0b00cd50d9c2a87",
"slotId": "mod_scope"
},
{
"_id": "6783ec7588341583da153886",
"_tpl": "67617ec9ea1e82ea5e103054",
"parentId": "6783ec6e1a49dfd7571ae44e",
"slotId": "mod_scope_000"
},
{
"_id": "6783ec85d0fd3275f2ab164a",
"_tpl": "652910565ae2ae97b80fdf35",
"parentId": "6783ec4cf0b00cd50d9c2a87",
"slotId": "mod_barrel"
},
{
"_id": "6783ec955c4560dd83a3c26f",
"_tpl": "6529113b5ae2ae97b80fdf39",
"parentId": "6783ec85d0fd3275f2ab164a",
"slotId": "mod_muzzle"
},
{
"_id": "6783ec9892098902e42933bd",
"_tpl": "672e37d143ba463a1cdcbd7b",
"parentId": "6783ec955c4560dd83a3c26f",
"slotId": "mod_muzzle"
},
{
"_id": "6783ec9ddf30430fd30d48ef",
"_tpl": "652910bc24cbe3c74a05e5b9",
"parentId": "6783ec85d0fd3275f2ab164a",
"slotId": "mod_gas_block"
},
{
"_id": "6783ec9fb358c9d737de5800",
"_tpl": "672e37d1984bc9a10241a9c7",
"parentId": "6783ec4cf0b00cd50d9c2a87",
"slotId": "mod_handguard"
},
{
"_id": "6783eea29163d870c845e6b9",
"_tpl": "6529348224cbe3c74a05e5c4",
"parentId": "6783ec33c8d50fdb6b63d3e9",
"slotId": "mod_stock_000"
},
{
"_id": "6783eea6b0158f1b5bf6ba4e",
"_tpl": "672e37d151b832f3fb8ccbb0",
"parentId": "6783eea29163d870c845e6b9",
"slotId": "mod_stock"
},
{
"_id": "6783eeaa698962dfeeda79a3",
"_tpl": "672e37d1d9a55146e49287d6",
"parentId": "6783eea6b0158f1b5bf6ba4e",
"slotId": "mod_stock_000"
},
{
"_id": "6783eca92713d47b3f369d0b",
"_tpl": "672e37d1906226680c4e28d5",
"parentId": "6783ec33c8d50fdb6b63d3e9",
"slotId": "mod_charge"
}
],
"_name": "SIG SPEAR default black",
"_parent": "6783ec33c8d50fdb6b63d3e9",
"_type": "Preset"
},
"6783e5da52977a05d959ac2f": {
"_changeWeaponName": false,
"_encyclopedia": "672e37d1dd890afba20c10e7",
"_id": "6783e5da52977a05d959ac2f",
"_items": [
{
"_id": "6783e5f4c23d0a4830e3d069",
"_tpl": "672e37d1dd890afba20c10e7",
"upd": {
"Repairable": {
"Durability": 100,
"MaxDurability": 100
}
}
},
{
"_id": "6783e603e6cebbfe9babfb73",
"_tpl": "5cc9bcaed7f00c011c04e179",
"parentId": "6783e5f4c23d0a4830e3d069",
"slotId": "mod_pistol_grip"
},
{
"_id": "6783e60517f08a8301bbd2c5",
"_tpl": "5a3501acc4a282000d72293a",
"parentId": "6783e5f4c23d0a4830e3d069",
"slotId": "mod_magazine"
},
{
"_id": "6783e607810d48f18bc7e606",
"_tpl": "5a33ca0fc4a282000d72292f",
"parentId": "6783e5f4c23d0a4830e3d069",
"slotId": "mod_stock"
},
{
"_id": "6783e60ba048490f25da323e",
"_tpl": "5d44069ca4b9361ebd26fc37",
"parentId": "6783e607810d48f18bc7e606",
"slotId": "mod_stock"
},
{
"_id": "6783e60d0f11531e764dd864",
"_tpl": "5d00ef6dd7ad1a0940739b16",
"parentId": "6783e5f4c23d0a4830e3d069",
"slotId": "mod_handguard"
},
{
"_id": "6783e61457c31046a3d9466b",
"_tpl": "5a34fae7c4a2826c6e06d760",
"parentId": "6783e5f4c23d0a4830e3d069",
"slotId": "mod_barrel"
},
{
"_id": "6783e618cc78902eec1f2c0b",
"_tpl": "5a34fd2bc4a282329a73b4c5",
"parentId": "6783e61457c31046a3d9466b",
"slotId": "mod_muzzle"
},
{
"_id": "6783e61a7bfb5f73bdcef867",
"_tpl": "5a34fbadc4a28200741e230a",
"parentId": "6783e61457c31046a3d9466b",
"slotId": "mod_gas_block"
}
],
"_name": "RSASS Black",
"_parent": "6783e5f4c23d0a4830e3d069",
"_type": "Preset"
},
"6783eb2892780aded22f44d6": {
"_changeWeaponName": false,
"_encyclopedia": "672e37d10b7a12e6a7a50b77",
"_id": "6783eb2892780aded22f44d6",
"_items": [
{
"_id": "6783eb3a05c979d9171196e2",
"_tpl": "672e37d10b7a12e6a7a50b77",
"upd": {
"FireMode": {
"FireMode": "single"
}
}
},
{
"_id": "6783eb482a3ac74d07710776",
"_tpl": "55802f5d4bdc2dac148b458f",
"parentId": "6783eb3a05c979d9171196e2",
"slotId": "mod_pistol_grip"
},
{
"_id": "6783eb4de2e02a031c2d2eb9",
"_tpl": "59d6272486f77466146386ff",
"parentId": "6783eb3a05c979d9171196e2",
"slotId": "mod_magazine"
},
{
"_id": "6783eb54e77a16ac4853c726",
"_tpl": "672e37d1a98e0628807ba29a",
"parentId": "6783eb3a05c979d9171196e2",
"slotId": "mod_reciever"
},
{
"_id": "6783eb6f7e0a5b57278b5d8f",
"_tpl": "60658776f2cb2e02a42ace2b",
"parentId": "6783eb54e77a16ac4853c726",
"slotId": "mod_barrel"
},
{
"_id": "6783eb76f0ceaeb9063cdbf2",
"_tpl": "6065c6e7132d4d12c81fd8e1",
"parentId": "6783eb6f7e0a5b57278b5d8f",
"slotId": "mod_muzzle"
},
{
"_id": "6783eb7901da578da4b2230c",
"_tpl": "6065dc8a132d4d12c81fd8e3",
"parentId": "6783eb6f7e0a5b57278b5d8f",
"slotId": "mod_gas_block"
},
{
"_id": "6783eb7b04cdf6ff2fb14809",
"_tpl": "6065880c132d4d12c81fd8da",
"parentId": "6783eb54e77a16ac4853c726",
"slotId": "mod_handguard"
},
{
"_id": "6783eb7e73028d0ad6ba25a7",
"_tpl": "5bc09a30d4351e00367fb7c8",
"parentId": "6783eb7b04cdf6ff2fb14809",
"slotId": "mod_sight_front"
},
{
"_id": "6783eb801f0133eec60418fd",
"_tpl": "5bc09a18d4351e003562b68e",
"parentId": "6783eb54e77a16ac4853c726",
"slotId": "mod_sight_rear"
},
{
"_id": "6783eb82d4bfe4734f1968e8",
"_tpl": "606587e18900dc2d9a55b65f",
"parentId": "6783eb3a05c979d9171196e2",
"slotId": "mod_stock_001"
},
{
"_id": "6783eb85ede00f4e10fe95fa",
"_tpl": "606587d11246154cad35d635",
"parentId": "6783eb82d4bfe4734f1968e8",
"slotId": "mod_stock_000"
},
{
"_id": "6783eb8781c4dad6d094d7d5",
"_tpl": "606587bd6d0bd7580617bacc",
"parentId": "6783eb3a05c979d9171196e2",
"slotId": "mod_charge"
}
],
"_name": "CMMG MK47 short default black",
"_parent": "6783eb3a05c979d9171196e2",
"_type": "Preset"
}
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,26 @@
{
"name": "Black Core",
"version": "1.1.6",
"main": "src/mod.js",
"license": "University of Illinois/NCSA Open Source License",
"author": "MoxoPixel",
"sptVersion": "3.10.X",
"isBundleMod": true,
"scripts": {
"setup": "npm i",
"build": "node ./build.mjs",
"buildinfo": "node ./build.mjs --verbose"
},
"devDependencies": {
"@types/node": "20.11",
"@typescript-eslint/eslint-plugin": "7.2",
"@typescript-eslint/parser": "7.2",
"archiver": "^6.0",
"eslint": "8.57",
"fs-extra": "11.2",
"ignore": "^5.2",
"tsyringe": "4.8.0",
"typescript": "5.4",
"winston": "3.12"
}
}
@@ -0,0 +1,236 @@
import { DependencyContainer } from "tsyringe";
import { IPostDBLoadMod } from "@spt/models/external/IPostDBLoadMod";
import { DatabaseServer } from "@spt/servers/DatabaseServer";
import { ImporterUtil } from "@spt/utils/ImporterUtil";
import { ILogger } from "@spt/models/spt/utils/ILogger";
import { PreSptModLoader } from "@spt/loaders/PreSptModLoader";
import { IDatabaseTables } from "@spt/models/spt/server/IDatabaseTables";
import { JsonUtil } from "@spt/utils/JsonUtil"
interface IHandbookEntry {
Id: string;
ParentId: string;
Price: number;
}
class BlackCore implements IPostDBLoadMod {
private db: IDatabaseTables;
private mydb: any;
private logger: ILogger;
private jsonUtil: JsonUtil;
public postDBLoad(container: DependencyContainer): void {
try {
this.logger = container.resolve<ILogger>("WinstonLogger");
this.jsonUtil = container.resolve<JsonUtil>("JsonUtil");
const databaseServer = container.resolve<DatabaseServer>("DatabaseServer");
const databaseImporter = container.resolve<ImporterUtil>("ImporterUtil");
const modLoader = container.resolve<PreSptModLoader>("PreSptModLoader");
this.db = databaseServer.getTables();
this.mydb = databaseImporter.loadRecursive(`${modLoader.getModPath("MoxoPixel-BlackCore")}database/`);
if (!this.db || !this.mydb) {
throw new Error("Failed to load required databases");
}
const modFolderName = "MoxoPixel-BlackCore";
const traders = {
"painter": "668aaff35fd574b6dcc4a686"
};
for (const newItem in this.mydb.items) {
this.cloneItem(this.mydb.items[newItem].clone, newItem);
this.addCompatibilitiesAndConflicts(this.mydb.items[newItem].clone, newItem);
const newItemLocales = this.mydb.items[newItem].locales;
for (const lang in this.db.locales.global) {
this.db.locales.global[lang][`${newItem} Name`] = newItemLocales.Name;
this.db.locales.global[lang][`${newItem} ShortName`] = newItemLocales.Shortname;
this.db.locales.global[lang][`${newItem} Description`] = newItemLocales.Description;
}
}
for (const trader in traders) this.addTraderAssort(traders[trader]);
for (const preset in this.mydb.globals.ItemPresets) {
this.db.globals.ItemPresets[preset] = this.mydb.globals.ItemPresets[preset];
}
const dbMastering = this.db.globals.config.Mastering;
for (const weapon in dbMastering) {
if (dbMastering[weapon].Name == "M4") dbMastering[weapon].Templates.push("672e37d1179b7b969b7577cb", "672e37d1ddaf7c656e3a634c", "672e37d19f1683101780773b");
if (dbMastering[weapon].Name == "AK74") dbMastering[weapon].Templates.push("672e37d1e35a6ec6e6997492");
if (dbMastering[weapon].Name == "R11SRASS") dbMastering[weapon].Templates.push("672e37d1dd890afba20c10e7");
if (dbMastering[weapon].Name == "MK47") dbMastering[weapon].Templates.push("672e37d10b7a12e6a7a50b77");
if (dbMastering[weapon].Name == "SPEAR") dbMastering[weapon].Templates.push("672e37d17f433cdb29072bc8");
}
const dbQuests = this.db.templates.quests;
for (const M4Quest in dbQuests) {
if (
dbQuests[M4Quest]._id === "5a27bb8386f7741c770d2d0a" ||
dbQuests[M4Quest]._id === "5c0d4c12d09282029f539173" ||
dbQuests[M4Quest]._id === "63a9b229813bba58a50c9ee5" ||
dbQuests[M4Quest]._id === "64e7b9bffd30422ed03dad38" ||
dbQuests[M4Quest]._id === "666314b4d7f171c4c20226c3"
) {
const availableForFinish = dbQuests[M4Quest].conditions.AvailableForFinish;
for (const condition of availableForFinish) {
if (condition.counter && condition.counter.conditions) {
for (const counterCondition of condition.counter.conditions) {
if (counterCondition.weapon) {
counterCondition.weapon.push(
"672e37d1179b7b969b7577cb",
"672e37d1ddaf7c656e3a634c",
"672e37d19f1683101780773b"
);
}
}
}
}
}
}
for (const AKQuest in dbQuests) {
if (
dbQuests[AKQuest]._id === "59c50a9e86f7745fef66f4ff" ||
dbQuests[AKQuest]._id === "61e6e60223374d168a4576a6" ||
dbQuests[AKQuest]._id === "64e7b9bffd30422ed03dad38"
) {
const availableForFinish = dbQuests[AKQuest].conditions.AvailableForFinish;
for (const condition of availableForFinish) {
if (condition.counter && condition.counter.conditions) {
for (const counterCondition of condition.counter.conditions) {
if (counterCondition.weapon) {
counterCondition.weapon.push(
"672e37d1e35a6ec6e6997492"
);
}
}
}
}
}
}
for (const MK47Quest in dbQuests) {
if (
dbQuests[MK47Quest]._id === "64e7b9bffd30422ed03dad38"
) {
const availableForFinish = dbQuests[MK47Quest].conditions.AvailableForFinish;
for (const condition of availableForFinish) {
if (condition.counter && condition.counter.conditions) {
for (const counterCondition of condition.counter.conditions) {
if (counterCondition.weapon) {
counterCondition.weapon.push(
"672e37d10b7a12e6a7a50b77",
"672e37d17f433cdb29072bc8"
);
}
}
}
}
}
}
this.logger.info("------------------------");
this.logger.info("Black Core Loaded");
} catch (error) {
this.logger.error(`Error loading BlackCore mod: ${error.message}`);
}
}
private cloneItem(itemToClone: string, blackCoreID: string): void {
if (!itemToClone || !blackCoreID) {
this.logger.error("Invalid parameters passed to cloneItem");
return;
}
if (!this.mydb.items[blackCoreID]?.enable) {
return;
}
if (!this.db.templates.items[itemToClone]) {
this.logger.error(`Template item ${itemToClone} not found`);
return;
}
if (this.mydb.items[blackCoreID].enable == true) {
let blackCoreItemOut = this.jsonUtil.clone(this.db.templates.items[itemToClone]);
blackCoreItemOut._id = blackCoreID;
blackCoreItemOut = this.compareAndReplace(blackCoreItemOut, this.mydb.items[blackCoreID]["items"]);
const bcCompatibilities: object = (typeof this.mydb.items[blackCoreID].bcCompatibilities == "undefined") ? {} : this.mydb.items[blackCoreID].bcCompatibilities;
const bcConflicts: Array<string> = (typeof this.mydb.items[blackCoreID].bcConflicts == "undefined") ? [] : this.mydb.items[blackCoreID].bcConflicts;
for (const modSlotName in bcCompatibilities) {
for (const slot of blackCoreItemOut._props.Slots) {
if (slot._name === modSlotName) for (const id of bcCompatibilities[modSlotName]) slot._props.filters[0].Filter.push(id);
}
}
blackCoreItemOut._props.ConflictingItems = blackCoreItemOut._props.ConflictingItems.concat(bcConflicts);
this.db.templates.items[blackCoreID] = blackCoreItemOut;
const handbookEntry: IHandbookEntry = {
"Id": blackCoreID,
"ParentId": this.mydb.items[blackCoreID]["handbook"]["ParentId"],
"Price": this.mydb.items[blackCoreID]["handbook"]["Price"]
};
this.db.templates.handbook.Items.push(handbookEntry);
}
}
private compareAndReplace(originalItem: any, attributesToChange: any): any {
for (const key in attributesToChange) {
if ((["boolean", "string", "number"].includes(typeof attributesToChange[key])) || Array.isArray(attributesToChange[key])) {
if (key in originalItem) originalItem[key] = attributesToChange[key];
else this.logger.error("Error finding the attribute: \"" + key + "\", default value is used instead.");
}
else originalItem[key] = this.compareAndReplace(originalItem[key], attributesToChange[key]);
}
return originalItem;
}
private addCompatibilitiesAndConflicts(itemClone: string, blackCoreID: string): void {
for (const item in this.db.templates.items) {
if (item in this.mydb.items) continue;
const slots = (typeof this.db.templates.items[item]._props.Slots === "undefined") ? [] : this.db.templates.items[item]._props.Slots;
const chambers = (typeof this.db.templates.items[item]._props.Chambers === "undefined") ? [] : this.db.templates.items[item]._props.Chambers;
const cartridges = (typeof this.db.templates.items[item]._props.Cartridges === "undefined") ? [] : this.db.templates.items[item]._props.Cartridges;
const combined = slots.concat(chambers, cartridges)
for (const entry of combined) {
for (const id of entry._props.filters[0].Filter) {
if (id === itemClone) entry._props.filters[0].Filter.push(blackCoreID);
}
}
const conflictingItems = (typeof this.db.templates.items[item]._props.ConflictingItems === "undefined") ? [] : this.db.templates.items[item]._props.ConflictingItems;
for (const conflictID of conflictingItems) if (conflictID === itemClone) conflictingItems.push(blackCoreID);
}
}
private addTraderAssort(trader: string): void {
if (!this.db.traders[trader]?.assort || !this.mydb.traders[trader]?.assort) {
this.logger.error(`Invalid trader assort data for trader: ${trader}`);
return;
}
for (const item in this.mydb.traders[trader].assort.items) {
this.db.traders[trader].assort.items.push(this.mydb.traders[trader].assort.items[item]);
}
for (const item in this.mydb.traders[trader].assort.barter_scheme) {
this.db.traders[trader].assort.barter_scheme[item] = this.mydb.traders[trader].assort.barter_scheme[item];
}
for (const item in this.mydb.traders[trader].assort.loyal_level_items) {
this.db.traders[trader].assort.loyal_level_items[item] = this.mydb.traders[trader].assort.loyal_level_items[item];
}
}
}
module.exports = { mod: new BlackCore() }
@@ -130,9 +130,9 @@ scavMaxGroupSize = 4
## Max pmc group size
# Setting type: Int32
# Default value: 5
# Default value: 4
# Acceptable value range: From 0 to 10
pmcMaxGroupSize = 5
pmcMaxGroupSize = 4
## Increases chances of pmc groups spawning, doesn't dramatically increase quantity.
# Setting type: Boolean
@@ -158,9 +158,9 @@ MaxBotCap = 25
## This controls the health of zombies
# Setting type: Double
# Default value: 0.5
# Default value: 1
# Acceptable value range: From 0 to 3
ZombieHealth = 0.5
ZombieHealth = 1
## Multiplies wave counts seen in the server's mapConfig.json by this number
# Setting type: Double
@@ -170,14 +170,14 @@ ZombieWaveQuantity = 1
## Determines the weighting of spawns at the beginning (1) spread evenly throughout (0.5) or at the end(0) of the raid
# Setting type: Double
# Default value: 0.2
# Default value: 0.5
# Acceptable value range: From 0 to 1
ZombieWaveDistribution = 0.2
ZombieWaveDistribution = 0.5
## Enables zombies to spawn
# Setting type: Boolean
# Default value: true
zombiesEnabled On/Off = true
# Default value: false
zombiesEnabled On/Off = false
## Determines the weighting of spawns at the beginning (1) spread evenly throughout (0.5) or at the end(0) of the raid
# Setting type: Double
@@ -187,21 +187,21 @@ ScavWaveDistribution = 0.5
## Determines the weighting of spawns at the beginning (1) spread evenly throughout (0.5) or at the end(0) of the raid
# Setting type: Double
# Default value: 0.8
# Default value: 0.7
# Acceptable value range: From 0 to 1
PmcWaveDistribution = 0.8
PmcWaveDistribution = 0.7
## Multiplies wave counts seen in the server's mapConfig.json by this number
# Setting type: Double
# Default value: 1.5
# Default value: 1
# Acceptable value range: From 0 to 10
ScavWaveQuantity = 1.5
ScavWaveQuantity = 1
## Multiplies wave counts seen in the server's mapConfig.json by this number
# Setting type: Double
# Default value: 1.5
# Default value: 1
# Acceptable value range: From 0 to 10
PmcWaveQuantity = 1.5
PmcWaveQuantity = 1
[3.Debug]
@@ -51,7 +51,7 @@ Gating level = 0
## Will reset when the game opens. You are supposed to use the gating increase/decrease keys to change the gating level, but you are free to change it manually if you want to make sure you are at a specific gating level.
# Setting type: Int32
# Default value: 0
Gating level = 0
Gating level = -2
1.Manual gating increase = KeypadPlus
+11 -8
View File
@@ -7,6 +7,7 @@
"tyfon-uifixes",
"MoreCheckmarksBackend",
"ExpandedTaskText",
"aMoxoPixel-Painter",
"acidphantasm-bosseshavelegamedals",
"acidphantasm-defaultfiremode",
"acidphantasm-refsptfriendlyquests",
@@ -17,6 +18,9 @@
"choccy-striker-1.0.5",
"flir-betterkeysng",
"redlaser42-Increase Climb Height",
"MoxoPixel-BlackCore",
"Additional Clothing USEC",
"Additional Clothing BEAR",
"WTT-LittleDrummerBoy",
"WTTArmoryAk5C",
"WTTArmoryHK417",
@@ -24,21 +28,20 @@
"WTTArmorySVD",
"choccy-rpg7-1.1.4",
"choccy-saa-1.0.7",
"raid_review__0.3.0",
"BRNVG_N-15Adapter",
"z_hacker228-makevalvssgreatagain",
"OpticRework-310",
"tyfon-weaponcustomizer",
"ArenaLockboxes-Delod-1.0.0",
"lacyway-mergeconsumables",
"acidphantasm-brightlasers",
"AUG_AttachmentPack",
"shibdib-shibsexpandedcrafts",
"zSolarint-SAIN-ServerMod",
"Skwizzy-LootingBots-ServerMod",
"acidphantasm-progressivebotsystem",
"DewardianDev-MOAR",
"inory-dynamicgoons",
"acidphantasm-progressivebotsystem",
"ArenaLockboxes-Delod-1.0.0",
"tyfon-weaponcustomizer",
"Additional Clothing BEAR",
"Additional Clothing USEC",
"BRNVG_N-15Adapter",
"OpticRework-310"
"raid_review__0.3.0"
]
}
+1 -1
View File
@@ -6,7 +6,7 @@ newestVersion=
category="1,"
nexusFileStatus=1
installationFile=DewardianDev-MOAR-2.6.7.zip
repository=Nexus
repository=
ignoredVersion=
comments=
notes=
@@ -5,7 +5,7 @@
"scavDifficulty": 0.4,
"scavWaveDistribution": 0.5,
"scavWaveQuantity": 1.5,
"scavWaveQuantity": 1,
"startingPmcs": false,
@@ -13,20 +13,20 @@
"pmcOpenZones": true,
"allOpenZones": false,
"pmcWaveDistribution": 0.8,
"pmcWaveQuantity": 1.5,
"pmcWaveDistribution": 0.7,
"pmcWaveQuantity": 1,
"zombiesEnabled": true,
"zombieWaveDistribution": 0.2,
"zombiesEnabled": false,
"zombieWaveDistribution": 0.5,
"zombieWaveQuantity": 1,
"zombieHealth": 0.5,
"zombieHealth": 1,
"maxBotCap": 25,
"maxBotPerZone": 5,
"moreScavGroups": false,
"morePmcGroups": false,
"pmcMaxGroupSize": 5,
"pmcMaxGroupSize": 4,
"scavMaxGroupSize": 4,
"snipersHaveFriends": false,
@@ -1,11 +1,11 @@
[General]
gameName=spt
modid=0
version=d2025.1.14.0
version=d2025.1.13.0
newestVersion=
category="1,"
nexusFileStatus=1
installationFile=SWAG-Donuts-v4.0.0RC4-SPT310x.7z
installationFile=DewardianDev-MOAR-2.6.7.zip
repository=Nexus
ignoredVersion=
comments=
@@ -15,7 +15,7 @@ url=
hasCustomURL=false
lastNexusQuery=
lastNexusUpdate=
nexusLastModified=2024-12-18T07:07:11Z
nexusLastModified=2024-12-16T06:46:30Z
nexusCategory=0
converted=false
validated=false
@@ -1,6 +1,6 @@
MIT License
Copyright (c) 2023 Kevin
Copyright (c) 2023 Dushaoan
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@@ -0,0 +1,12 @@
{
"live-like": 25,
"more-scavs": 8,
"more-pmcs": 8,
"more-scavs-and-pmcs": 5,
"main-boss-roaming": 5,
"sniper-buddies": 4,
"boss-invasion": 2,
"rogue-invasion": 0,
"raider-invasion": 0,
"insanity": 0
}
@@ -0,0 +1,64 @@
{
"live-like": {},
"more-scavs": {
"moreScavGroups": true,
"scavMaxGroupSize": 5,
"scavWaveQuantity": 1.2
},
"more-pmcs": {
"scavWaveDistribution": 0.4,
"morePmcGroups": true,
"pmcMaxGroupSize": 5,
"pmcWaveQuantity": 1.2
},
"more-scavs-and-pmcs": {
"scavWaveDistribution": 0.4,
"moreScavGroups": true,
"scavMaxGroupSize": 5,
"morePmcGroups": true,
"pmcMaxGroupSize": 5,
"scavWaveQuantity": 1.2,
"pmcWaveQuantity": 1.2,
"mainBossChanceBuff": 25
},
"boss-invasion": {
"bossOpenZones": true,
"bossInvasion": true,
"bossInvasionSpawnChance": 10,
"mainBossChanceBuff": 25,
"gradualBossInvasion": true
},
"rogue-invasion": {
"randomRaiderGroup": true,
"randomRaiderGroupChance": 50
},
"raider-invasion": {
"randomRaiderGroup": true,
"randomRaiderGroupChance": 50
},
"insanity": {
"scavWaveDistribution": 0.4,
"scavWaveQuantity": 1.3,
"pmcWaveQuantity": 1.3,
"moreScavGroups": true,
"morePmcGroups": true,
"pmcMaxGroupSize": 6,
"scavMaxGroupSize": 6,
"snipersHaveFriends": true,
"bossOpenZones": true,
"randomRaiderGroup": true,
"randomRaiderGroupChance": 50,
"randomRogueGroup": true,
"randomRogueGroupChance": 50,
"mainBossChanceBuff": 50,
"bossInvasion": true,
"bossInvasionSpawnChance": 10
},
"main-boss-roaming": {
"bossOpenZones": true,
"mainBossChanceBuff": 35
},
"sniper-buddies": {
"snipersHaveFriends": true
}
}
@@ -0,0 +1,63 @@
{
"ADD_THESE_TO_A_MAP_TO_OVERRIDE_OR_ADD_A_BOSS_TO_A_MAP": {
"BOSS_NAME_EXAMPLE": "CHANCE_OF_SPAWNING_PERCENT",
"sectantPriest": 0,
"arenaFighterEvent": 0,
"bossBoarSniper": 0,
"pmcBot": 0,
"bossZryachiy": 0,
"exUsec": 0,
"crazyAssaultEvent": 0,
"peacemaker": 0,
"bossKojaniy": 0,
"bossGluhar": 0,
"bossSanitar": 0,
"bossKilla": 0,
"bossTagilla": 0,
"bossKnight": 0,
"bossBoar": 0,
"bossKolontay": 0,
"bossPartisan": 0,
"bossBully": 0
},
"customs": {
"bossKnight": 30,
"bossPartisan": 30,
"bossBully": 30
},
"factoryDay": {
"bossTagilla": 30
},
"factoryNight": {
"bossTagilla": 30
},
"interchange": {
"bossKilla": 30
},
"laboratory": {},
"lighthouse": {
"bossKnight": 30,
"bossPartisan": 30
},
"rezervbase": {
"bossGluhar": 30
},
"shoreline": {
"bossKnight": 30,
"bossPartisan": 30,
"bossSanitar": 30
},
"tarkovstreets": {
"bossBoar": 30,
"bossKolontay": 30
},
"woods": {
"bossKojaniy": 30,
"bossKnight": 30,
"bossPartisan": 30
},
"gzLow": {},
"gzHigh": {
"bossKolontay": 30
}
}
@@ -0,0 +1,50 @@
{
"enableBotSpawning": true,
"pmcDifficulty": 0.6,
"scavDifficulty": 0.4,
"scavWaveDistribution": 0.5,
"scavWaveQuantity": 1.0,
"startingPmcs": false,
"playerOpenZones": false,
"pmcOpenZones": true,
"allOpenZones": false,
"pmcWaveDistribution": 0.8,
"pmcWaveQuantity": 1.0,
"zombiesEnabled": true,
"zombieWaveDistribution": 0.2,
"zombieWaveQuantity": 1,
"zombieHealth": 0.5,
"maxBotCap": 25,
"maxBotPerZone": 5,
"moreScavGroups": false,
"morePmcGroups": false,
"pmcMaxGroupSize": 5,
"scavMaxGroupSize": 4,
"snipersHaveFriends": false,
"bossOpenZones": false,
"randomRaiderGroup": false,
"randomRaiderGroupChance": 10,
"randomRogueGroup": false,
"randomRogueGroupChance": 10,
"disableBosses": false,
"mainBossChanceBuff": 0,
"bossInvasion": false,
"bossInvasionSpawnChance": 5,
"gradualBossInvasion": true,
"debug": false
}
@@ -0,0 +1,110 @@
{
"customs": {
"spawnMinDistance": 30,
"pmcWaveCount": 14,
"scavWaveCount": 21,
"zombieWaveCount": 9,
"scavHotZones": [
"ZoneDormitory"
],
"pmcHotZones": [
"ZoneDormitory"
]
},
"factoryDay": {
"spawnMinDistance": 20,
"maxBotCapOverride": 12,
"maxBotPerZoneOverride": 10,
"pmcWaveCount": 10,
"scavWaveCount": 10,
"zombieWaveCount": 6
},
"factoryNight": {
"spawnMinDistance": 20,
"maxBotCapOverride": 12,
"maxBotPerZoneOverride": 10,
"pmcWaveCount": 10,
"scavWaveCount": 10,
"zombieWaveCount": 6
},
"interchange": {
"spawnMinDistance": 40,
"pmcWaveCount": 16,
"scavWaveCount": 32,
"zombieWaveCount": 12,
"scavHotZones": [
"ZoneCenterBot",
"ZoneCenter"
]
},
"laboratory": {
"spawnMinDistance": 20,
"pmcWaveCount": 12,
"scavWaveCount": 0,
"zombieWaveCount": 12
},
"lighthouse": {
"spawnMinDistance": 40,
"pmcWaveCount": 14,
"scavWaveCount": 22,
"zombieWaveCount": 10,
"scavHotZones": [
"Zone_LongRoad",
"Zone_LongRoad"
]
},
"rezervbase": {
"spawnMinDistance": 40,
"pmcWaveCount": 14,
"scavWaveCount": 26,
"zombieWaveCount": 9,
"scavHotZones": [
"ZoneRailStrorage"
],
"pmcHotZones": [
"ZoneBarrack"
]
},
"shoreline": {
"spawnMinDistance": 40,
"pmcWaveCount": 16,
"scavWaveCount": 32,
"zombieWaveCount": 12,
"scavHotZones": [
"ZoneSanatorium1"
],
"pmcHotZones": [
"ZoneSanatorium2"
]
},
"tarkovstreets": {
"spawnMinDistance": 40,
"pmcWaveCount": 16,
"scavWaveCount": 28,
"zombieWaveCount": 13
},
"woods": {
"spawnMinDistance": 40,
"pmcWaveCount": 16,
"scavWaveCount": 28,
"zombieWaveCount": 10,
"scavHotZones": [
"ZoneWoodCutter"
],
"pmcHotZones": [
"ZoneWoodCutter"
]
},
"gzLow": {
"spawnMinDistance": 30,
"pmcWaveCount": 12,
"scavWaveCount": 18,
"zombieWaveCount": 9
},
"gzHigh": {
"spawnMinDistance": 30,
"pmcWaveCount": 12,
"scavWaveCount": 18,
"zombieWaveCount": 9
}
}
@@ -0,0 +1,25 @@
{
"name": "MOAR",
"version": "2.6.7",
"main": "src/mod.js",
"license": "MIT",
"author": "DewardianDev",
"sptVersion": "^3.10.x",
"scripts": {
"setup": "npm i",
"build": "node ./packageBuild.ts"
},
"devDependencies": {
"@semantic-release/git": "^10.0.1",
"@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",
"semantic-release": "^24.2.0",
"tsyringe": "4.7.0",
"typescript": "4.9.4"
}
}
@@ -0,0 +1,11 @@
import config from "../config/config.json";
import { ILocationBase } from "@spt/models/eft/common/ILocationBase";
export class globalValues {
public static baseConfig: typeof config = undefined;
public static overrideConfig: Partial<typeof config> = undefined;
public static locationsBase: ILocationBase[] = undefined;
public static currentPreset: string = "";
public static forcedPreset: string = "custom";
public static addedMapZones: Record<string, string[]> = {};
}
@@ -0,0 +1,168 @@
import { DependencyContainer } from "tsyringe";
import { buildWaves } from "../Spawning/Spawning";
import { StaticRouterModService } from "@spt/services/mod/staticRouter/StaticRouterModService";
// import { DynamicRouterModService } from "@spt/services/mod/dynamicRouter/DynamicRouterModService";
import { globalValues } from "../GlobalValues";
import { kebabToTitle } from "../utils";
import PresetWeightingsConfig from "../../config/PresetWeightings.json";
export const setupRoutes = (container: DependencyContainer) => {
const staticRouterModService = container.resolve<StaticRouterModService>(
"StaticRouterModService"
);
// const dynamicRouterModService = container.resolve<DynamicRouterModService>(
// "DynamicRouterModService"
// );
// Make buildwaves run on game end
staticRouterModService.registerStaticRouter(
`moarUpdater`,
[
{
url: "/client/match/local/end",
action: async (_url, info, sessionId, output) => {
buildWaves(container);
return output;
},
},
],
"moarUpdater"
);
staticRouterModService.registerStaticRouter(
`moarGetCurrentPreset`,
[
{
url: "/moar/currentPreset",
action: async () => {
return globalValues.forcedPreset || "random";
},
},
],
"moarGetCurrentPreset"
);
staticRouterModService.registerStaticRouter(
`moarGetAnnouncePreset`,
[
{
url: "/moar/announcePreset",
action: async () => {
if (globalValues.forcedPreset?.toLowerCase() === "random") {
return globalValues.currentPreset;
}
return globalValues.forcedPreset || globalValues.currentPreset;
},
},
],
"moarGetAnnouncePreset"
);
staticRouterModService.registerStaticRouter(
`getDefaultConfig`,
[
{
url: "/moar/getDefaultConfig",
action: async () => {
return JSON.stringify(globalValues.baseConfig);
},
},
],
"getDefaultConfig"
);
staticRouterModService.registerStaticRouter(
`getServerConfigWithOverrides`,
[
{
url: "/moar/getServerConfigWithOverrides",
action: async () => {
return JSON.stringify({
...(globalValues.baseConfig || {}),
...(globalValues.overrideConfig || {}),
});
},
},
],
"getServerConfigWithOverrides"
);
staticRouterModService.registerStaticRouter(
`getServerConfigWithOverrides`,
[
{
url: "/moar/getServerConfigWithOverrides",
action: async () => {
return JSON.stringify({
...globalValues.baseConfig,
...globalValues.overrideConfig,
});
},
},
],
"getServerConfigWithOverrides"
);
staticRouterModService.registerStaticRouter(
`moarGetPresetsList`,
[
{
url: "/moar/getPresets",
action: async () => {
let result = [
...Object.keys(PresetWeightingsConfig).map((preset) => ({
Name: kebabToTitle(preset),
Label: preset,
})),
{ Name: "Random", Label: "random" },
{ Name: "Custom", Label: "custom" },
];
return JSON.stringify({ data: result });
},
},
],
"moarGetPresetsList"
);
staticRouterModService.registerStaticRouter(
"setOverrideConfig",
[
{
url: "/moar/setOverrideConfig",
action: async (
url: string,
overrideConfig: typeof globalValues.overrideConfig = {},
sessionID,
output
) => {
globalValues.overrideConfig = overrideConfig;
buildWaves(container);
return "Success";
},
},
],
"setOverrideConfig"
);
staticRouterModService.registerStaticRouter(
"moarSetPreset",
[
{
url: "/moar/setPreset",
action: async (url: string, { Preset }, sessionID, output) => {
globalValues.forcedPreset = Preset;
buildWaves(container);
return `Current Preset: ${kebabToTitle(
globalValues.forcedPreset || "Random"
)}`;
},
},
],
"moarSetPreset"
);
};
@@ -0,0 +1,158 @@
import { IBotConfig } from "@spt/models/spt/config/IBotConfig.d";
import { IPmcConfig } from "@spt/models/spt/config/IPmcConfig.d";
import { DatabaseServer } from "@spt/servers/DatabaseServer";
import _config from "../../config/config.json";
import _mapConfig from "../../config/mapConfig.json";
import { ConfigServer } from "@spt/servers/ConfigServer";
import { ConfigTypes } from "@spt/models/enums/ConfigTypes";
import { DependencyContainer } from "tsyringe";
import { globalValues } from "../GlobalValues";
import {
cloneDeep,
getRandomPresetOrCurrentlySelectedPreset,
saveToFile,
} from "../utils";
import { ILocationConfig } from "@spt/models/spt/config/ILocationConfig.d";
import { originalMapList } from "./constants";
import { buildBossWaves } from "./buildBossWaves";
import buildZombieWaves from "./buildZombieWaves";
import buildScavMarksmanWaves from "./buildScavMarksmanWaves";
import buildPmcs from "./buildPmcs";
import { setEscapeTimeOverrides } from "./utils";
import { ILogger } from "@spt/models/spt/utils/ILogger";
import updateSpawnLocations from "./updateSpawnLocations";
export const buildWaves = (container: DependencyContainer) => {
const configServer = container.resolve<ConfigServer>("ConfigServer");
const Logger = container.resolve<ILogger>("WinstonLogger");
const pmcConfig = configServer.getConfig<IPmcConfig>(ConfigTypes.PMC);
const botConfig = configServer.getConfig<IBotConfig>(ConfigTypes.BOT);
const locationConfig = configServer.getConfig<ILocationConfig>(
ConfigTypes.LOCATION
);
locationConfig.rogueLighthouseSpawnTimeSettings.waitTimeSeconds = 60;
locationConfig.enableBotTypeLimits = false;
locationConfig.fitLootIntoContainerAttempts = 1; // Move to ALP
locationConfig.addCustomBotWavesToMaps = false;
locationConfig.customWaves = { boss: {}, normal: {} };
const databaseServer = container.resolve<DatabaseServer>("DatabaseServer");
const { locations, bots, globals } = databaseServer.getTables();
let config = cloneDeep(globalValues.baseConfig) as typeof _config;
const preset = getRandomPresetOrCurrentlySelectedPreset();
Object.keys(globalValues.overrideConfig).forEach((key) => {
if (config[key] !== globalValues.overrideConfig[key]) {
config.debug &&
console.log(
`[MOAR] overrideConfig ${key} changed from ${config[key]} to ${globalValues.overrideConfig[key]}`
);
config[key] = globalValues.overrideConfig[key];
}
});
// Set from preset if preset above is not empty
Object.keys(preset).forEach((key) => {
if (config[key] !== preset[key]) {
config.debug &&
console.log(
`[MOAR] preset ${globalValues.currentPreset}: ${key} changed from ${config[key]} to ${preset[key]}`
);
config[key] = preset[key];
}
});
// config.debug &&
console.log(
globalValues.forcedPreset === "custom"
? "custom"
: globalValues.currentPreset
);
const {
bigmap: customs,
factory4_day: factoryDay,
factory4_night: factoryNight,
interchange,
laboratory,
lighthouse,
rezervbase,
shoreline,
tarkovstreets,
woods,
sandbox: gzLow,
sandbox_high: gzHigh,
} = locations;
let locationList = [
customs,
factoryDay,
factoryNight,
interchange,
laboratory,
lighthouse,
rezervbase,
shoreline,
tarkovstreets,
woods,
gzLow,
gzHigh,
];
// This resets all locations to original state
if (!globalValues.locationsBase) {
globalValues.locationsBase = locationList.map(({ base }) =>
cloneDeep(base)
);
} else {
locationList = locationList.map((item, key) => ({
...item,
base: cloneDeep(globalValues.locationsBase[key]),
}));
}
pmcConfig.convertIntoPmcChance = {
default: {
assault: { min: 0, max: 0 },
cursedassault: { min: 0, max: 0 },
pmcbot: { min: 0, max: 0 },
exusec: { min: 0, max: 0 },
arenafighter: { min: 0, max: 0 },
arenafighterevent: { min: 0, max: 0 },
crazyassaultevent: { min: 0, max: 0 },
},
factory4_day: { assault: { min: 0, max: 0 } },
laboratory: { pmcbot: { min: 0, max: 0 } },
rezervbase: { pmcbot: { min: 0, max: 0 } },
};
updateSpawnLocations(locationList, config);
setEscapeTimeOverrides(locationList, _mapConfig, Logger, config);
// Make main waves
buildScavMarksmanWaves(config, locationList, botConfig);
// BOSS RELATED STUFF!
buildBossWaves(config, locationList);
//Zombies
if (config.zombiesEnabled) {
buildZombieWaves(config, locationList, bots);
}
buildPmcs(config, locationList);
originalMapList.forEach((name, index) => {
if (!locations[name]) {
console.log("[MOAR] OH CRAP we have a problem!", name);
} else {
locations[name] = locationList[index];
}
});
};
@@ -0,0 +1,277 @@
import { ILocation } from "@spt/models/eft/common/ILocation";
import _config from "../../config/config.json";
import bossConfig from "../../config/bossConfig.json";
import mapConfig from "../../config/mapConfig.json";
import {
bossesToRemoveFromPool,
configLocations,
mainBossNameList,
originalMapList,
} from "./constants";
import { buildBossBasedWave, shuffle } from "./utils";
import { IBossLocationSpawn } from "@spt/models/eft/common/ILocationBase";
import { cloneDeep } from "../utils";
export function buildBossWaves(
config: typeof _config,
locationList: ILocation[]
) {
let {
randomRaiderGroup,
randomRaiderGroupChance,
randomRogueGroup,
randomRogueGroupChance,
mainBossChanceBuff,
bossInvasion,
bossInvasionSpawnChance,
disableBosses,
bossOpenZones,
gradualBossInvasion,
} = config;
const bossList = mainBossNameList.filter(
(bossName) => !["bossKnight"].includes(bossName)
);
const allBosses: Record<string, IBossLocationSpawn> = {};
for (const key in locationList) {
locationList[key].base.BossLocationSpawn.forEach((boss) => {
if (!allBosses[boss.BossName]) {
allBosses[boss.BossName] = boss;
}
});
}
// CreateBossList
const bosses: Record<string, IBossLocationSpawn> = {};
for (let indx = 0; indx < locationList.length; indx++) {
// Disable Bosses
if (disableBosses && !!locationList[indx].base?.BossLocationSpawn) {
locationList[indx].base.BossLocationSpawn = [];
} else {
//Remove all other spawns from pool now that we have the spawns zone list
locationList[indx].base.BossLocationSpawn = locationList[
indx
].base.BossLocationSpawn.filter(
(boss) => !bossesToRemoveFromPool.has(boss.BossName)
);
const location = locationList[indx];
const defaultBossSettings =
mapConfig?.[configLocations[indx]]?.defaultBossSettings;
// Sets bosses spawn chance from settings
if (
location?.base?.BossLocationSpawn &&
defaultBossSettings &&
Object.keys(defaultBossSettings)?.length
) {
const filteredBossList = Object.keys(defaultBossSettings).filter(
(name) => defaultBossSettings[name]?.BossChance !== undefined
);
if (filteredBossList?.length) {
filteredBossList.forEach((bossName) => {
location.base.BossLocationSpawn =
location.base.BossLocationSpawn.map((boss) => ({
...boss,
...(boss.BossName === bossName
? { BossChance: defaultBossSettings[bossName].BossChance }
: {}),
}));
});
}
}
if (randomRaiderGroup) {
const raiderWave = buildBossBasedWave(
randomRaiderGroupChance,
"1,2,2,2,3",
"pmcBot",
"pmcBot",
"",
locationList[indx].base.EscapeTimeLimit
);
location.base.BossLocationSpawn.push(raiderWave);
}
if (randomRogueGroup) {
const rogueWave = buildBossBasedWave(
randomRogueGroupChance,
"1,2,2,2,3",
"exUsec",
"exUsec",
"",
locationList[indx].base.EscapeTimeLimit
);
location.base.BossLocationSpawn.push(rogueWave);
}
//Add each boss from each map to bosses object
const filteredBosses = location.base.BossLocationSpawn?.filter(
({ BossName }) => mainBossNameList.includes(BossName)
);
if (filteredBosses.length) {
for (let index = 0; index < filteredBosses.length; index++) {
const boss = filteredBosses[index];
if (
!bosses[boss.BossName] ||
(bosses[boss.BossName] &&
bosses[boss.BossName].BossChance < boss.BossChance)
) {
bosses[boss.BossName] = { ...boss };
}
}
}
}
}
if (!disableBosses) {
// Make boss Invasion
if (bossInvasion) {
if (bossInvasionSpawnChance) {
bossList.forEach((bossName) => {
if (bosses[bossName])
bosses[bossName].BossChance = bossInvasionSpawnChance;
});
}
for (let key = 0; key < locationList.length; key++) {
//Gather bosses to avoid duplicating.
const duplicateBosses = [
...locationList[key].base.BossLocationSpawn.filter(
({ BossName, BossZone }) => bossList.includes(BossName)
).map(({ BossName }) => BossName),
"bossKnight", // So knight doesn't invade
];
//Build bosses to add
const bossesToAdd = shuffle<IBossLocationSpawn[]>(Object.values(bosses))
.filter(({ BossName }) => !duplicateBosses.includes(BossName))
.map((boss, j) => ({
...boss,
BossZone: "",
BossEscortAmount:
boss.BossEscortAmount === "0" ? boss.BossEscortAmount : "1",
...(gradualBossInvasion ? { Time: j * 20 + 1 } : {}),
}));
// UpdateBosses
locationList[key].base.BossLocationSpawn = [
...locationList[key].base.BossLocationSpawn,
...bossesToAdd,
];
}
}
let hasChangedBossSpawns = false;
// console.log(Object.keys(allBosses));
configLocations.forEach((mapName, index) => {
const bossLocationSpawn = locationList[index].base.BossLocationSpawn;
const mapBossConfig: Record<string, number> = cloneDeep(
bossConfig[mapName] || {}
);
// if (Object.keys(mapBossConfig).length === 0) console.log(name, "empty");
const adjusted = new Set<string>([]);
bossLocationSpawn.forEach(({ BossName, BossChance }, bossIndex) => {
if (typeof mapBossConfig[BossName] === "number") {
if (BossChance !== mapBossConfig[BossName]) {
if (!hasChangedBossSpawns) {
console.log(
`\n[MOAR]: --- Adjusting default boss spawn rates --- `
);
hasChangedBossSpawns = true;
}
console.log(
`[MOAR]: ${mapName} ${BossName}: ${locationList[index].base.BossLocationSpawn[bossIndex].BossChance} => ${mapBossConfig[BossName]}`
);
locationList[index].base.BossLocationSpawn[bossIndex].BossChance =
mapBossConfig[BossName];
}
adjusted.add(BossName);
}
});
const bossesToAdd = Object.keys(mapBossConfig)
.filter(
(adjustName) => !adjusted.has(adjustName) && !!allBosses[adjustName]
)
.map((bossName) => {
`[MOAR]: Adding non-default boss ${bossName} to ${originalMapList[index]}`;
const newBoss: IBossLocationSpawn = cloneDeep(
allBosses[bossName] || {}
);
newBoss.BossChance = mapBossConfig[bossName];
// console.log(
// "Adding boss",
// bossName,
// "to ",
// originalMapList[index],
// "spawn chance =>",
// mapBossConfig[bossName]
// );
return newBoss;
});
// console.log(bossesToAdd);
if (bossOpenZones || mainBossChanceBuff) {
locationList[index].base?.BossLocationSpawn?.forEach((boss, key) => {
if (bossList.includes(boss.BossName)) {
if (bossOpenZones) {
locationList[index].base.BossLocationSpawn[key] = {
...locationList[index].base.BossLocationSpawn[key],
BossZone: "",
};
}
if (!!boss.BossChance && mainBossChanceBuff > 0) {
locationList[index].base.BossLocationSpawn[key] = {
...locationList[index].base.BossLocationSpawn[key],
BossChance:
boss.BossChance + mainBossChanceBuff > 100
? 100
: Math.round(boss.BossChance + mainBossChanceBuff),
};
}
}
});
}
locationList[index].base.BossLocationSpawn = [
...locationList[index].base.BossLocationSpawn,
...bossesToAdd,
];
bossesToAdd.length &&
console.log(
`[MOAR] Adding the following bosses to map ${
configLocations[index]
}: ${bossesToAdd.map(({ BossName }) => BossName)}`
);
// console.log(locationList[index].base.BossLocationSpawn.length);
// Apply the percentages on all bosses, cull those that won't spawn, make all bosses 100 chance that remain.
locationList[index].base.BossLocationSpawn = locationList[
index
].base.BossLocationSpawn.filter(({ BossChance, BossName }, bossIndex) => {
if (BossChance < 100 && BossChance / 100 < Math.random()) {
return false;
}
return true;
}).map((boss) => ({ ...boss, ...{ BossChance: 100 } }));
// if (mapName === "customs")
// console.log(mapName, locationList[index].base.BossLocationSpawn);
});
if (hasChangedBossSpawns) {
console.log(
`[MOAR]: --- Adjusting default boss spawn rates complete --- \n`
);
}
}
}
@@ -0,0 +1,88 @@
import { ILocation } from "@spt/models/eft/common/ILocation";
import _config from "../../config/config.json";
import mapConfig from "../../config/mapConfig.json";
import {
bossesToRemoveFromPool,
defaultEscapeTimes,
defaultHostility,
} from "./constants";
import { buildPmcWaves, MapSettings, shuffle } from "./utils";
import { saveToFile } from "../utils";
export default function buildPmcs(
config: typeof _config,
locationList: ILocation[]
) {
for (let index = 0; index < locationList.length; index++) {
const mapSettingsList = Object.keys(mapConfig) as Array<
keyof typeof mapConfig
>;
const map = mapSettingsList[index];
locationList[index].base.BotLocationModifier.AdditionalHostilitySettings =
defaultHostility;
const { pmcHotZones = [] } = (mapConfig?.[map] as MapSettings) || {};
let pmcZones = shuffle<string[]>([
...new Set(
[...locationList[index].base.SpawnPointParams]
.filter(
({ Categories, BotZoneName }) =>
!!BotZoneName &&
!BotZoneName.includes("snipe") &&
(Categories.includes("Player") || Categories.includes("All")) &&
!BotZoneName.includes("BotZoneGate")
)
.map(({ BotZoneName, ...rest }) => {
return BotZoneName;
})
),
]);
// Make labs have only named zones
if (map === "laboratory") {
pmcZones = new Array(10).fill(pmcZones).flat(1);
}
const { pmcWaveCount } = mapConfig[map];
const escapeTimeLimitRatio = Math.round(
locationList[index].base.EscapeTimeLimit / defaultEscapeTimes[map]
);
const totalWaves = Math.round(
pmcWaveCount * config.pmcWaveQuantity * escapeTimeLimitRatio
);
const numberOfZoneless = totalWaves - pmcZones.length;
if (numberOfZoneless > 0) {
const addEmpty = new Array(numberOfZoneless).fill("");
pmcZones = shuffle<string[]>([...pmcZones, ...addEmpty]);
}
if (config.debug) {
console.log(`${map} PMC count ${totalWaves} \n`);
escapeTimeLimitRatio !== 1 &&
console.log(
`${map} PMC wave count changed from ${pmcWaveCount} to ${totalWaves} due to escapeTimeLimit adjustment`
);
}
const timeLimit = locationList[index].base.EscapeTimeLimit * 60;
const waves = buildPmcWaves(
totalWaves,
timeLimit,
config,
pmcZones,
pmcHotZones
);
locationList[index].base.BossLocationSpawn = [
...waves,
...locationList[index].base.BossLocationSpawn,
];
}
}
@@ -0,0 +1,218 @@
import { ILocation } from "@spt/models/eft/common/ILocation";
import _config from "../../config/config.json";
import mapConfig from "../../config/mapConfig.json";
import {
configLocations,
defaultEscapeTimes,
defaultHostility,
originalMapList,
} from "./constants";
import { MapSettings, shuffle, waveBuilder } from "./utils";
import { IWave, WildSpawnType } from "@spt/models/eft/common/ILocationBase";
import { IBotConfig } from "@spt/models/spt/config/IBotConfig";
import { saveToFile } from "../utils";
export default function buildScavMarksmanWaves(
config: typeof _config,
locationList: ILocation[],
botConfig: IBotConfig
) {
let {
debug,
maxBotCap,
scavWaveQuantity,
scavWaveDistribution,
snipersHaveFriends,
maxBotPerZone,
scavMaxGroupSize,
scavDifficulty,
moreScavGroups,
} = config;
for (let index = 0; index < locationList.length; index++) {
const mapSettingsList = Object.keys(mapConfig) as Array<
keyof typeof mapConfig
>;
const map = mapSettingsList[index];
locationList[index].base = {
...locationList[index].base,
...{
NewSpawn: false,
OcculsionCullingEnabled: true,
OfflineNewSpawn: false,
OfflineOldSpawn: true,
OldSpawn: true,
BotSpawnCountStep: 0,
},
};
locationList[index].base.NonWaveGroupScenario.Enabled = false;
locationList[index].base["BotStartPlayer"] = 0;
if (
locationList[index].base.BotStop <
locationList[index].base.EscapeTimeLimit * 60
) {
locationList[index].base.BotStop =
locationList[index].base.EscapeTimeLimit * 60;
}
const {
maxBotPerZoneOverride,
maxBotCapOverride,
EscapeTimeLimit,
scavHotZones,
} = (mapConfig?.[map] as MapSettings) || {};
// Set per map EscapeTimeLimit
if (EscapeTimeLimit) {
locationList[index].base.EscapeTimeLimit = EscapeTimeLimit;
locationList[index].base.exit_access_time = EscapeTimeLimit + 1;
}
// Set default or per map maxBotCap
if (maxBotCapOverride || maxBotCap) {
const capToSet = maxBotCapOverride || maxBotCap;
// console.log(map, capToSet, maxBotCapOverride, maxBotCap);
locationList[index].base.BotMax = capToSet;
locationList[index].base.BotMaxPvE = capToSet;
botConfig.maxBotCap[originalMapList[index]] = capToSet;
}
// Adjust botZone quantity
if (maxBotPerZoneOverride || maxBotPerZone) {
const BotPerZone = maxBotPerZoneOverride || maxBotPerZone;
// console.log(map, BotPerZone, maxBotPerZoneOverride, maxBotPerZone);
locationList[index].base.MaxBotPerZone = BotPerZone;
}
const sniperLocations = new Set(
[...locationList[index].base.SpawnPointParams]
.filter(
({ Categories, DelayToCanSpawnSec, BotZoneName, Sides }) =>
!Categories.includes("Boss") &&
Sides[0] === "Savage" &&
(BotZoneName?.toLowerCase().includes("snipe") ||
DelayToCanSpawnSec > 40)
)
.map(({ BotZoneName }) => BotZoneName || "")
);
if (sniperLocations.size) {
locationList[index].base.MinMaxBots = [
{
WildSpawnType: "marksman",
max: sniperLocations.size * 5,
min: sniperLocations.size,
},
];
}
let scavZones = shuffle<string[]>([
...new Set(
[...locationList[index].base.SpawnPointParams]
.filter(
({ Categories, Sides, BotZoneName }) =>
!!BotZoneName &&
Categories.includes("Bot") &&
(Sides.includes("Savage") || Sides.includes("All"))
)
.map(({ BotZoneName }) => BotZoneName)
.filter((name) => !sniperLocations.has(name))
),
]);
const { scavWaveCount } = mapConfig[map];
const escapeTimeLimitRatio = Math.round(
locationList[index].base.EscapeTimeLimit / defaultEscapeTimes[map]
);
// Scavs
const scavTotalWaveCount = Math.round(
scavWaveCount * scavWaveQuantity * escapeTimeLimitRatio
);
const numberOfZoneless = scavTotalWaveCount - scavZones.length;
// console.log(numberOfZoneless);
if (numberOfZoneless > 0) {
const addEmpty = new Array(numberOfZoneless).fill("");
scavZones = shuffle<string[]>([...scavZones, ...addEmpty]);
}
// console.log(scavZones);
config.debug &&
escapeTimeLimitRatio !== 1 &&
console.log(
`${map} Scav wave count changed from ${scavWaveCount} to ${scavTotalWaveCount} due to escapeTimeLimit adjustment`
);
const timeLimit = locationList[index].base.EscapeTimeLimit * 60;
let snipers = waveBuilder(
sniperLocations.size,
Math.round(timeLimit / 4),
0.5,
WildSpawnType.MARKSMAN,
0.7,
false,
2,
[],
shuffle([...sniperLocations]),
80,
true,
true
);
if (snipersHaveFriends)
snipers = snipers.map((wave) => ({
...wave,
...(snipersHaveFriends && wave.slots_max < 2
? { slots_min: 1, slots_max: 2 }
: {}),
}));
const scavWaves = waveBuilder(
scavTotalWaveCount,
timeLimit,
scavWaveDistribution,
WildSpawnType.ASSAULT,
scavDifficulty,
false,
scavMaxGroupSize,
map === "gzHigh" ? [] : scavZones,
scavHotZones,
0,
false,
!!moreScavGroups
);
if (debug) {
let totalscav = 0;
scavWaves.forEach(({ slots_max }) => (totalscav += slots_max));
console.log(configLocations[index]);
console.log(
"Scavs:",
totalscav,
"configVal",
Math.round((totalscav / scavWaveCount) * 100) / 100,
"configWaveCount",
scavWaveCount,
"waveCount",
scavWaves.length,
"\n"
);
}
// const finalSniperWaves = snipers?.map(({ ...rest }, snipKey) => ({
// ...rest,
// number: snipKey,
// time_min: snipKey * 120,
// time_max: snipKey * 120 + 120,
// }));
// if (map === "customs") saveToFile({ scavWaves }, "scavWaves.json");
locationList[index].base.waves = [...snipers, ...scavWaves]
.sort(({ time_min: a }, { time_min: b }) => a - b)
.map((wave, i) => ({ ...wave, number: i + 1 }));
}
}

Some files were not shown because too many files have changed in this diff Show More