From a37880fc0d62671527017b1d160ff442f26ce918 Mon Sep 17 00:00:00 2001 From: Faber <103538724+FaberTheCatboy@users.noreply.github.com> Date: Tue, 5 Jul 2022 15:08:18 -0700 Subject: [PATCH 1/5] Bo1 main_point_hook Changed Hook address from Cod4 to Bo1 Radiant --- src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index def2e73..2c208fe 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -39,7 +39,7 @@ BOOL APIENTRY DllMain(HMODULE /*hModule*/, DWORD ul_reason_for_call, LPVOID /*l Beep(523, 100); // Adress is the entry adress found in IDA under Exports - main::entry_point_hook.initialize(0x5C4299, entry_point)->install(); + main::entry_point_hook.initialize(0x5D92E3, entry_point)->install(); //This is the entry point for the Linkermod Bo1 Radiant } else if (ul_reason_for_call == DLL_PROCESS_DETACH) From b0247ad2c456656dcf7ea4285a79636ba386c95e Mon Sep 17 00:00:00 2001 From: Faber <103538724+FaberTheCatboy@users.noreply.github.com> Date: Tue, 5 Jul 2022 16:03:57 -0700 Subject: [PATCH 2/5] Update main.cpp --- src/main.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 2c208fe..b025e6c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -24,7 +24,7 @@ __declspec(naked) void entry_point() call main::initialize // same address as entry_point_hook.initialize - mov eax, 5C4299h + mov eax, 5D92E3h jmp eax } } @@ -34,7 +34,7 @@ BOOL APIENTRY DllMain(HMODULE /*hModule*/, DWORD ul_reason_for_call, LPVOID /*l if (ul_reason_for_call == DLL_PROCESS_ATTACH) { DWORD oldProtect; - VirtualProtect(GetModuleHandle(nullptr), 0x234D000, PAGE_EXECUTE_READWRITE, &oldProtect); // find this with CFF Explorer - Optinal Headers - SizeOfImage + VirtualProtect(GetModuleHandle(nullptr), 0x257A000, PAGE_EXECUTE_READWRITE, &oldProtect); // find this with CFF Explorer - Optinal Headers - SizeOfImage Beep(523, 100); From 66ab9f8886096e4f7d827c876f999148dec2623c Mon Sep 17 00:00:00 2001 From: FaberTheCatgirl <103538724+FaberTheCatgirl@users.noreply.github.com> Date: Fri, 17 Mar 2023 10:21:28 -0700 Subject: [PATCH 3/5] Wip Update README.md --- README.md | 37 +++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 35c73bc..d8e09f6 100644 --- a/README.md +++ b/README.md @@ -112,14 +112,14 @@ ___
-1. Install the CoD4 Modtools -2. Download the latest [release](https://github.com/xoxor4d/iw3xo-radiant/releases) +1. Install the Bo1 Modtools +2. Download the latest [release](https://github.com/VenomModding/T5xRadiant/releases) 3. Copy the contents into your cod4 root directory -4. Start `bin/IW3xRadiant.exe` +4. Start `bin/T5xRadiant.exe` -- [NIGHTLY]    install latest release, download nightly, unpack and replace `iw3r.dll` within the `bin` folder -                 -> check for additional assets in the __#nightly-builds__ channel (📍) on the [iw3xo discord](https://discord.gg/t5jRGbj) -- [OPTIONAL]  __bo3-tool-textures.zip__ (unpack and place `.iwi's` into `bin\IW3xRadiant\images`) +- [NIGHTLY]    install latest release, download nightly, unpack and replace `t5xr.dll` within the `bin` folder +                 -> check for additional assets in the __#nightly-builds__ channel (📍) on the [Venom Modding discord](https://discord.gg/QuNcjXbsqY) +- [OPTIONAL]  __bo3-tool-textures.zip__ (unpack and place `.iwi's` into `bin\T5xRadiant\images`)
@@ -130,14 +130,14 @@ ___ ### How to build / compile the project using Visual Studio 1. Clone the repo! __(zip does not include deps!)__ -2. Copy everything within the assets folder into your cod4-root folder +2. Copy everything within the assets folder into your bo1-root folder 3. Use __update_submodules.bat__ to update submodules 4. Use __generate-buildfiles.bat__ to build project files with premake -5. Load the solution `(build/iw3xo-radiant.sln)` and open the iw3r project-settings to setup paths: -> - General       output directory path -> `path-to-cod4-root\bin\` -> - Debugging   command -> `path-to-cod4-root\bin\IW3xRadiant.exe` -> - Debugging   working directory -> `path-to-cod4-root\bin\` -> + Preferred: Create a new environment variable called `COD4_ROOT` that points to your cod4 directory and re-generate the project files. +5. Load the solution `(build/t5x-radiant.sln)` and open the iw3r project-settings to setup paths: +> - General       output directory path -> `path-to-bo1-root\bin\` +> - Debugging   command -> `path-to-bo1-root\bin\T5xRadiant.exe` +> - Debugging   working directory -> `path-to-bo1-root\bin\` +> + Preferred: Create a new environment variable called `BO1_ROOT` that points to your bo1 directory and re-generate the project files. 6. Build -> Build Solution or run with debugger
@@ -146,17 +146,17 @@ ___ 1. Install C++ Build tools (msbuild) 2. Add msbuild folder to the "PATH" environment variable: > `%ProgramFiles(x86)%\Microsoft Visual Studio\2019\Community\MSBuild\Current\Bin` -3. Add `COD4_ROOT` environment variable with path to your cod4 directory -> `"COD4_ROOT" "D:\COD4-Modtools"` +3. Add `BO1_ROOT` environment variable with path to your bo1 directory +> `"BO1_ROOT" "D:\BO1-Modtools"` 4. Clone the repo (zip does not include deps!) -5. Copy everything within the assets folder into your cod4-root folder +5. Copy everything within the assets folder into your bo1-root folder 6. Drag and drop all files from `.vscode/tracked\` into `.vscode\` -7. Open __iw3xo-radiant.code-workspace__ +7. Open __t5x-radiant.code-workspace__ 8. Run task: `update_submodules` or open __update_submodules.bat__ 9. Run task: `generate-buildfiles` or open __generate-buildfiles.bat__ -Use provided build-tasks with the option to copy `iw3r.dll` and `iw3r.pdb` to `%COD4_ROOT%/bin` -__Run->Start Debugging__ will build and copy a debug build to to `%COD4_ROOT%/bin` and launch IW3xRadiant. +Use provided build-tasks with the option to copy `T5xr.dll` and `T5xr.pdb` to `%BO1_ROOT%/bin` +__Run->Start Debugging__ will build and copy a debug build to to `%BO1_ROOT%/bin` and launch IW3xRadiant.
@@ -165,6 +165,7 @@ ___
### Optional: +https://github.com/VenomModding/t5xo-dev https://github.com/xoxor4d/iw3xo-dev ### Project Page: From acc6a11b431b8a5cc324cdd449cc1e5ccfdc18bc Mon Sep 17 00:00:00 2001 From: Faber <103538724+FaberTheCatboy@users.noreply.github.com> Date: Fri, 17 Mar 2023 11:13:55 -0700 Subject: [PATCH 4/5] T5 Radiant --- .github/workflows/build-debug.yml | 4 +- .github/workflows/build-release.yml | 4 +- .vscode/readme.txt | 10 +- .vscode/tracked/copy-to-cod4-dir.bat | 4 +- .vscode/tracked/launch.json | 4 +- .vscode/tracked/tasks.json | 12 +- assets/bin/IW3xRadiant/batch/compile_bsp.bat | 4 +- assets/bin/iw3xradiant.def | 2 +- assets/bin/iw3xradiant.prj | 4 +- premake5.lua | 16 +- src/Resource.rc | 14 +- src/common/mainframe.cpp | 6 +- src/common/radiantapp.cpp | 16 +- src/common/texwnd.cpp | 12 +- src/components/modules/config.cpp | 8 +- src/components/modules/d3dbsp.cpp | 1994 +++++++++--------- src/components/modules/effects.cpp | 2 +- src/components/modules/generate_previews.cpp | 2 +- src/components/modules/gui.cpp | 4 +- src/components/modules/main_module.cpp | 12 +- src/components/modules/mesh_painter.cpp | 12 +- src/components/modules/patches.cpp | 2 +- src/components/modules/reflectionprobes.cpp | 4 +- src/components/modules/renderer.cpp | 8 +- src/components/modules/time_wasted.cpp | 4 +- src/ggui/effects_editor_gui.cpp | 2 +- src/ggui/hotkeys.cpp | 8 +- src/ggui/menubar.cpp | 2 +- src/ggui/textures.cpp | 4 +- src/ggui/toolbar.cpp | 4 +- src/utils/filesystem.cpp | 2 +- 31 files changed, 1093 insertions(+), 1093 deletions(-) diff --git a/.github/workflows/build-debug.yml b/.github/workflows/build-debug.yml index 00823f2..35e748b 100644 --- a/.github/workflows/build-debug.yml +++ b/.github/workflows/build-debug.yml @@ -47,8 +47,8 @@ jobs: with: name: ${{matrix.configuration}} binaries path: | - build/bin/${{matrix.configuration}}/iw3r.dll - build/bin/${{matrix.configuration}}/iw3r.pdb + build/bin/${{matrix.configuration}}/t5xr.dll + build/bin/${{matrix.configuration}}/t5xr.pdb build/bin/${{matrix.configuration}}/PhysX_32.dll build/bin/${{matrix.configuration}}/PhysXCommon_32.dll build/bin/${{matrix.configuration}}/PhysXCooking_32.dll diff --git a/.github/workflows/build-release.yml b/.github/workflows/build-release.yml index 7ded048..c619a24 100644 --- a/.github/workflows/build-release.yml +++ b/.github/workflows/build-release.yml @@ -47,8 +47,8 @@ jobs: with: name: ${{matrix.configuration}} binaries path: | - build/bin/${{matrix.configuration}}/iw3r.dll - build/bin/${{matrix.configuration}}/iw3r.pdb + build/bin/${{matrix.configuration}}/t5xr.dll + build/bin/${{matrix.configuration}}/t5xr.pdb build/bin/${{matrix.configuration}}/PhysX_32.dll build/bin/${{matrix.configuration}}/PhysXCommon_32.dll build/bin/${{matrix.configuration}}/PhysXCooking_32.dll diff --git a/.vscode/readme.txt b/.vscode/readme.txt index ac09f28..74ba0f7 100644 --- a/.vscode/readme.txt +++ b/.vscode/readme.txt @@ -1,10 +1,10 @@ 1.) Install C++ Build tools (msbuild) -2.) Add msbuild to the "PATH" environment variable (eg. "%ProgramFiles(x86)%\Microsoft Visual Studio\2019\Community\MSBuild\Current\Bin") -3.) Add "COD4_ROOT" environment variable with path to your cod4 directory (eg. "COD4_ROOT" "D:\COD4-Modtools") +2.) Add msbuild to the "PATH" environment variable (eg. "%ProgramFiles(x86)%\Microsoft Visual Studio\2022\Community\Msbuild\Current\Bin") +3.) Add "BO1_ROOT" environment variable with path to your bo1 directory (eg. "BO1_ROOT" "D:\BO1-Modtools") 4.) Drag and drop all files from ".vscode/tracked\" into ".vscode\ (we ignore all files in .vscode/ besides the readme) -5.) Open "iw3xo-radiant.code-workspace" +5.) Open "t5xo-radiant.code-workspace" 6.) Run task "update_submodules" or open "update_submodules.bat" 7.) Run task "generate-buildfiles" or open "generate-buildfiles.bat" -Use provided build-tasks to build debug/release builds with the option to copy iw3r.dll and iw3r.pdb to %COD4_ROOT%/bin. -Run->Start Debugging will build and copy a debug build to to %COD4_ROOT%/bin and launch IW3xRadiant. \ No newline at end of file +Use provided build-tasks to build debug/release builds with the option to copy t5xr.dll and t5xr.pdb to %BO1_ROOT%/bin. +Run->Start Debugging will build and copy a debug build to to %BO1_ROOT%/bin and launch T5xRadiant. \ No newline at end of file diff --git a/.vscode/tracked/copy-to-cod4-dir.bat b/.vscode/tracked/copy-to-cod4-dir.bat index 95f2187..7680884 100644 --- a/.vscode/tracked/copy-to-cod4-dir.bat +++ b/.vscode/tracked/copy-to-cod4-dir.bat @@ -3,5 +3,5 @@ set path=%~1 cd ../build/bin/%path% @echo on -copy iw3r.dll "%COD4_ROOT%\bin\" -copy iw3r.pdb "%COD4_ROOT%\bin\" \ No newline at end of file +copy t5xr.dll "%BO1_ROOT%\bin\" +copy t5xr.pdb "%BO1_ROOT%\bin\" \ No newline at end of file diff --git a/.vscode/tracked/launch.json b/.vscode/tracked/launch.json index 4ca7209..e1d292f 100644 --- a/.vscode/tracked/launch.json +++ b/.vscode/tracked/launch.json @@ -8,10 +8,10 @@ "name": "(Windows) Start", "type": "cppvsdbg", "request": "launch", - "program": "IW3xRadiant.exe", + "program": "T5xRadiant.exe", "args": [], "stopAtEntry": false, - "cwd": "${env:COD4_ROOT}\\bin", + "cwd": "${env:BO1_ROOT}\\bin", "environment": [], "preLaunchTask": "debug-build-copy" } diff --git a/.vscode/tracked/tasks.json b/.vscode/tracked/tasks.json index 927c4a8..4298af7 100644 --- a/.vscode/tracked/tasks.json +++ b/.vscode/tracked/tasks.json @@ -45,7 +45,7 @@ "label": "debug-build", "command": "msbuild.exe", "args": [ - "build/iw3xo-radiant.sln", + "build/t5xo-radiant.sln", "/p:Configuration=Debug;Platform=Win32", ], "problemMatcher": "$msCompile", @@ -61,7 +61,7 @@ "label": "release-build", "command": "msbuild.exe", "args": [ - "build/iw3xo-radiant.sln", + "build/t5xo-radiant.sln", "/p:Configuration=Release;Platform=Win32", ], "problemMatcher": ["$msCompile"], @@ -72,22 +72,22 @@ // * // copy to dir - // debug: copy build to cod4/bin + // debug: copy build to bo1/bin { "type": "shell", "label": "z-copy-debug", - "command": "copy-to-cod4-dir.bat", + "command": "copy-to-bo1-dir.bat", "options": { "cwd": "${workspaceFolder}\\.vscode" }, "args": ["debug"], }, - // release: copy build to cod4/bin + // release: copy build to bo1/bin { "type": "shell", "label": "z-copy-release", - "command": "copy-to-cod4-dir.bat", + "command": "copy-to-bo1-dir.bat", "options": { "cwd": "${workspaceFolder}\\.vscode" diff --git a/assets/bin/IW3xRadiant/batch/compile_bsp.bat b/assets/bin/IW3xRadiant/batch/compile_bsp.bat index 45676ea..fd89577 100644 --- a/assets/bin/IW3xRadiant/batch/compile_bsp.bat +++ b/assets/bin/IW3xRadiant/batch/compile_bsp.bat @@ -38,7 +38,7 @@ if "%compileBSP%" == "1" ( echo. copy "%mapsourcepath%%mapname%.map" "%bsppath%%mapname%.map" - "%treepath%bin\cod4map" -platform pc -loadFrom "%mapsourcepath%%mapname%.map" %parmBSPOptions% "%bsppath%%mapname%" + "%treepath%bin\bo1map" -platform pc -loadFrom "%mapsourcepath%%mapname%.map" %parmBSPOptions% "%bsppath%%mapname%" ) if "%compileLight%" == "1" ( @@ -47,7 +47,7 @@ if "%compileLight%" == "1" ( echo. IF EXIST "%mapsourcepath%%mapname%.grid" copy "%mapsourcepath%%mapname%.grid" "%bsppath%%mapname%.grid" - "%treepath%bin\cod4rad" -platform pc %parmLightOptions% "%bsppath%%mapname%" + "%treepath%bin\bo1rad" -platform pc %parmLightOptions% "%bsppath%%mapname%" ) IF EXIST "%bsppath%%mapname%.map" del "%bsppath%%mapname%.map" diff --git a/assets/bin/iw3xradiant.def b/assets/bin/iw3xradiant.def index b75b047..fff7e63 100644 --- a/assets/bin/iw3xradiant.def +++ b/assets/bin/iw3xradiant.def @@ -145,7 +145,7 @@ NO_STATIC_SHADOWS - the opaque surfaces will not cast static light map shadows /*QUAKED fx_origin (0.45 0.3 0.2) (-2 -2 -2) (2 2 2) used for createFX generation and general effect handling. -default: "fx" "iw3xradiant_def" +default: "fx" "t5xradiant_def" fx - effect definition fxloop - make createFX gen. use loopfx instead of createOneshotEffect diff --git a/assets/bin/iw3xradiant.prj b/assets/bin/iw3xradiant.prj index 5c807dd..ac1bbd9 100644 --- a/assets/bin/iw3xradiant.prj +++ b/assets/bin/iw3xradiant.prj @@ -1,9 +1,9 @@ { "basepath" ".." "mapspath" "..\\map_source" -"entitypath" ".\\iw3xradiant.def" +"entitypath" ".\\t5xradiant.def" "autosave" "autosave.map" "game" "" "basegame" "" -"layeredmaterials" "cod4_layered_material_library.txt" +"layeredmaterials" "bo1_layered_material_library.txt" } diff --git a/premake5.lua b/premake5.lua index 5d15b78..3f0e303 100644 --- a/premake5.lua +++ b/premake5.lua @@ -212,9 +212,9 @@ end dependencies.load() -workspace "iw3xo-radiant" +workspace "T5xRadiant" - startproject "iw3r" + startproject "t5xr" location "./build" objdir "%{wks.location}/obj" targetdir "%{wks.location}/bin/%{cfg.buildcfg}" @@ -283,7 +283,7 @@ workspace "iw3xo-radiant" -- Project - project "iw3r" + project "t5xr" kind "SharedLib" language "C++" @@ -313,11 +313,11 @@ workspace "iw3xo-radiant" "/Zm100 -Zm100" } - if(os.getenv("COD4_ROOT")) then - print ("Setup paths using environment variable 'COD4_ROOT' :: '" .. os.getenv("COD4_ROOT") .. "'") - targetdir(os.getenv("COD4_ROOT") .. "/bin/") - debugdir (os.getenv("COD4_ROOT") .. "/bin/") - debugcommand (os.getenv("COD4_ROOT") .. "/bin/" .. "IW3xRadiant.exe") + if(os.getenv("BO1_ROOT")) then + print ("Setup paths using environment variable 'BO1_ROOT' :: '" .. os.getenv("BO1_ROOT") .. "'") + targetdir(os.getenv("BO1_ROOT") .. "/bin/") + debugdir (os.getenv("BO1_ROOT") .. "/bin/") + debugcommand (os.getenv("BO1_ROOT") .. "/bin/" .. "T5xRadiant.exe") end -- Specific configurations diff --git a/src/Resource.rc b/src/Resource.rc index d6f6dcb..e304fb8 100644 --- a/src/Resource.rc +++ b/src/Resource.rc @@ -67,17 +67,17 @@ BEGIN BEGIN BLOCK "040904b0" BEGIN - VALUE "CompanyName", "" + VALUE "CompanyName", "Gungnir Studios LLC" #ifdef _DEBUG - VALUE "FileDescription", "Radiant modification built for IW3xo" + VALUE "FileDescription", "Radiant modification built for T5xo-dev" #else - VALUE "FileDescription", "Radiant modification built for IW3xo" + VALUE "FileDescription", "Radiant modification built for T5xo-dev" #endif VALUE "FileVersion", VERSION_FILE - VALUE "InternalName", "iw3r" - VALUE "LegalCopyright", "xoxor4d.github.io" - VALUE "OriginalFilename", "iw3r.dll" - VALUE "ProductName", "IW3xRadiant" + VALUE "InternalName", "t5xr" + VALUE "LegalCopyright", "Copyright (C) 2023 Gungnir Studios LLC" + VALUE "OriginalFilename", "t5xr.dll" + VALUE "ProductName", "T5xRadiant" VALUE "ProductVersion", VERSION_PRODUCT END END diff --git a/src/common/mainframe.cpp b/src/common/mainframe.cpp index 6fc63db..19cb3a2 100644 --- a/src/common/mainframe.cpp +++ b/src/common/mainframe.cpp @@ -203,7 +203,7 @@ void __declspec(naked) hk_on_createclient() } } -// auto load iw3xradiant.prj +// auto load t5xradiant.prj void create_qe_children(cmainframe* mainframe) { char app_path[_MAX_PATH + 1]; @@ -216,7 +216,7 @@ void create_qe_children(cmainframe* mainframe) if(!bProjectLoaded) { - game::Com_Error("Unable to load project file "); + game::Com_Error("Unable to load project file "); } auto* m_camera_origin = reinterpret_cast(0x241A5A4); @@ -882,7 +882,7 @@ void cmainframe::hooks() // handle wm_char events for non-focused subwindows utils::hook(0x421A7B, cmainframe::windowproc, HOOK_CALL).install()->quick(); - // automatically load iw3xradiant.prj + // automatically load t5xradiant.prj utils::hook(0x422984, hk_create_qe_children_stub, HOOK_JUMP).install()->quick(); // hook end of createclient diff --git a/src/common/radiantapp.cpp b/src/common/radiantapp.cpp index 69a1db9..56cab2a 100644 --- a/src/common/radiantapp.cpp +++ b/src/common/radiantapp.cpp @@ -102,7 +102,7 @@ bool on_exit_instance() void registery_save([[maybe_unused]] CPrefsDlg* prefs) { const auto state = afx::get_module_state(); - CWinApp_WriteProfileInt(state->m_pCurrentWinApp, "Prefs", "iw3x_mainframe_menubar_enabled", ggui::mainframe_menubar_enabled); + CWinApp_WriteProfileInt(state->m_pCurrentWinApp, "Prefs", "t5x_mainframe_menubar_enabled", ggui::mainframe_menubar_enabled); CWinApp_WriteProfileInt(state->m_pCurrentWinApp, "Prefs", "lights_max_intensity", game::g_qeglobals->preview_at_max_intensity); CWinApp_WriteProfileInt(state->m_pCurrentWinApp, "Prefs", "force_zero_dropheight", prefs->m_bForceZeroDropHeight); CWinApp_WriteProfileInt(state->m_pCurrentWinApp, "Prefs", "discord_rpc", components::discord::g_enable_discord_rpc); @@ -111,7 +111,7 @@ void registery_save([[maybe_unused]] CPrefsDlg* prefs) void registery_load() { const auto state = afx::get_module_state(); - ggui::mainframe_menubar_enabled = CWinApp_GetProfileIntA(state->m_pCurrentWinApp, "Prefs", "iw3x_mainframe_menubar_enabled", 0); + ggui::mainframe_menubar_enabled = CWinApp_GetProfileIntA(state->m_pCurrentWinApp, "Prefs", "t5x_mainframe_menubar_enabled", 0); // always bothered me .. game::g_qeglobals->preview_at_max_intensity = CWinApp_GetProfileIntA(state->m_pCurrentWinApp, "Prefs", "lights_max_intensity", 0); @@ -147,7 +147,7 @@ BOOL LoadRegistryInfo(const char* pszName, void* pvBuf, long* plSize) } else { - RegOpenKeyExA(HKEY_CURRENT_USER, "Software\\iw\\IW3xRadiant\\IW3xRadiant", 0, KEY_READ, &hKey); + RegOpenKeyExA(HKEY_CURRENT_USER, "Software\\iw\\T5xRadiant\\T5xRadiant", 0, KEY_READ, &hKey); } RegQueryValueExA(hKey, pszName, NULL, (unsigned long*)&lType, (unsigned char*)pvBuf, (unsigned long*)plSize); @@ -424,11 +424,11 @@ void radiantapp::hooks() // show/hide mainframe menubar on startup 03 :: CMainFrame::OnCreate utils::hook(0x421057, menubar_stub_03, HOOK_JUMP).install()->quick(); - // do not use or overwrite stock radiant registry keys - create seperate ones for IW3xRadiant - utils::hook::write_string(0x6EBA58, R"(Software\iw\IW3xRadiant\IW3xRadiant)"s); - utils::hook::write_string(0x6E2320, R"(iw\IW3xRadiant)"s); - utils::hook::write_string(0x6E22F0, R"(Software\iw\IW3xRadiant\IniPrefs)"s); - utils::hook::write_string(0x6DC1EC, R"(Software\iw\IW3xRadiant\MRU)"s); + // do not use or overwrite stock radiant registry keys - create seperate ones for T5xRadiant + utils::hook::write_string(0x6EBA58, R"(Software\iw\T5xRadiant\T5xRadiant)"s); + utils::hook::write_string(0x6E2320, R"(iw\T5xRadiant)"s); + utils::hook::write_string(0x6E22F0, R"(Software\iw\T5xRadiant\IniPrefs)"s); + utils::hook::write_string(0x6DC1EC, R"(Software\iw\T5xRadiant\MRU)"s); #ifdef HIDE_MAINFRAME_MENUBAR // ----------------------------------------------------------------------- diff --git a/src/common/texwnd.cpp b/src/common/texwnd.cpp index 68c78c4..eac8c39 100644 --- a/src/common/texwnd.cpp +++ b/src/common/texwnd.cpp @@ -53,7 +53,7 @@ void ctexwnd::write_favourite_list(int list_id) dvars::fs_homepath) { std::string dir_path = dvars::fs_homepath->current.string; - dir_path += R"(\IW3xRadiant\texture_favourites\)"; + dir_path += R"(\T5xRadiant\texture_favourites\)"; std::filesystem::create_directories(dir_path); if (std::filesystem::exists(dir_path)) @@ -77,7 +77,7 @@ void ctexwnd::write_favourite_list(int list_id) // read line by line while (std::getline(file, input)) { - if (!line_num && input.find("// texture favourites generated by iw3xo-radiant") == std::string::npos) + if (!line_num && input.find("// texture favourites generated by t5xo-radiant") == std::string::npos) { // invalid file break; @@ -115,7 +115,7 @@ void ctexwnd::write_favourite_list(int list_id) if (ofile.is_open()) { - ofile << "// texture favourites generated by iw3xo-radiant" << std::endl; + ofile << "// texture favourites generated by t5xo-radiant" << std::endl; ofile << texwnd_vector_of_favourites[list_id][0] << std::endl; int line_num = 0; @@ -136,7 +136,7 @@ void ctexwnd::write_favourite_list(int list_id) } else { - game::printf_to_console("[ERR][TEX] Failed to find favourite list '%s' in 'bin/IW3xRadiant/texture_favourites'", texwnd_vector_of_favourites[list_id][0].c_str()); + game::printf_to_console("[ERR][TEX] Failed to find favourite list '%s' in 'bin/T5xRadiant/texture_favourites'", texwnd_vector_of_favourites[list_id][0].c_str()); } } } @@ -199,7 +199,7 @@ void ctexwnd::load_favourites() std::ifstream file; std::string filepath = dvars::fs_homepath->current.string; - filepath += R"(\IW3xRadiant\texture_favourites\)"; + filepath += R"(\T5xRadiant\texture_favourites\)"; if (std::filesystem::exists(filepath)) { @@ -221,7 +221,7 @@ void ctexwnd::load_favourites() // read line by line while (std::getline(file, input)) { - if (!line_num && input.find("// texture favourites generated by iw3xo-radiant") == std::string::npos) + if (!line_num && input.find("// texture favourites generated by t5xo-radiant") == std::string::npos) { // invalid file break; diff --git a/src/components/modules/config.cpp b/src/components/modules/config.cpp index d15d678..eb60cd8 100644 --- a/src/components/modules/config.cpp +++ b/src/components/modules/config.cpp @@ -15,9 +15,9 @@ namespace components int loaded_dvar_count = 0; std::ifstream cfg; - if (utils::fs::open_file_homepath("IW3xRadiant", "dvars.cfg", false, cfg)) + if (utils::fs::open_file_homepath("T5xRadiant", "dvars.cfg", false, cfg)) { - game::printf_to_console("[CFG] Loading dvars from config 'bin/IW3xRadiant/dvars.cfg'"); + game::printf_to_console("[CFG] Loading dvars from config 'bin/T5xRadiant/dvars.cfg'"); std::string input; std::vector args; @@ -94,9 +94,9 @@ namespace components { std::ofstream cfg; - if (utils::fs::write_file_homepath("IW3xRadiant", "dvars.cfg", false, cfg)) + if (utils::fs::write_file_homepath("T5xRadiant", "dvars.cfg", false, cfg)) { - cfg << "// generated by iw3xo-radiant" << std::endl; + cfg << "// generated by t5xo-radiant" << std::endl; for (auto iter = 0; iter < *game::dvarCount; ++iter) { diff --git a/src/components/modules/d3dbsp.cpp b/src/components/modules/d3dbsp.cpp index bd3b443..8ecf87b 100644 --- a/src/components/modules/d3dbsp.cpp +++ b/src/components/modules/d3dbsp.cpp @@ -1,181 +1,181 @@ -#include "std_include.hpp" - -namespace components -{ - // * - // * Entity Handling - // * - - int d3dbsp::radiant_dobj_count = 0; - d3dbsp::radiant_dobj_s d3dbsp::radiant_dobj[512] = {}; - - +#include "std_include.hpp" + +namespace components +{ + // * + // * Entity Handling + // * + + int d3dbsp::radiant_dobj_count = 0; + d3dbsp::radiant_dobj_s d3dbsp::radiant_dobj[512] = {}; + + void d3dbsp::dobj_clear_list() { - memset(d3dbsp::radiant_dobj, 0, sizeof(d3dbsp::radiant_dobj)); + memset(d3dbsp::radiant_dobj, 0, sizeof(d3dbsp::radiant_dobj)); d3dbsp::radiant_dobj_count = 0; - } - - // hack but works - unsigned short lightinghandle = 0; - - // R_AddDObjToScene - void dobj_add_to_scene(game::DObj_s* obj, game::cpose_t* pose, unsigned int ent_num, float* lighting_origin) - { - if (!obj) - { - Assert(); - } - - if (!pose) - { - Assert(); - } - - unsigned int& gfxCfg_entCount = *reinterpret_cast(0x13683DC); - //DWORD& scene_dpvs_sceneDObjIndex = *reinterpret_cast(0x14C564C); - DWORD& scene_dpvs_sceneXModelIndex = *reinterpret_cast(0x14C5648); - - if (ent_num >= gfxCfg_entCount) - { - Assert(); - } - - if (game::Dvar_FindVar("r_drawEntities")->current.enabled) - { - const unsigned int scene_ent_index = utils::hook::call(0x501D80)(); // R_AllocSceneModel() - if (scene_ent_index < 1024) - { - game::GfxSceneModel* sceneModel = &game::scene->sceneModel[scene_ent_index]; - sceneModel->model = obj->models[0]; - sceneModel->DObj_s_obj = obj; - sceneModel->entnum = static_cast(ent_num); - sceneModel->cachedLightingHandle = &lightinghandle; - sceneModel->placement.base.origin[0] = pose->origin[0]; - sceneModel->placement.base.origin[1] = pose->origin[1]; - sceneModel->placement.base.origin[2] = pose->origin[2]; - - game::AnglesToQuat(pose->angles, sceneModel->placement.base.quat); - - sceneModel->placement.scale = 1.0f; - sceneModel->radius = sceneModel->model->radius; - sceneModel->lightingOrigin[0] = *lighting_origin; - sceneModel->lightingOrigin[1] = lighting_origin[1]; - sceneModel->lightingOrigin[2] = lighting_origin[2]; - sceneModel->gfxEntIndex = 0; - - *((WORD*)scene_dpvs_sceneXModelIndex + ent_num) = static_cast(scene_ent_index); - } - } - } - - void dobj_get_lighting_origin(game::cpose_t* pose, float* lighting_origin) - { + } + + // hack but works + unsigned short lightinghandle = 0; + + // R_AddDObjToScene + void dobj_add_to_scene(game::DObj_s* obj, game::cpose_t* pose, unsigned int ent_num, float* lighting_origin) + { + if (!obj) + { + Assert(); + } + + if (!pose) + { + Assert(); + } + + unsigned int& gfxCfg_entCount = *reinterpret_cast(0x13683DC); + //DWORD& scene_dpvs_sceneDObjIndex = *reinterpret_cast(0x14C564C); + DWORD& scene_dpvs_sceneXModelIndex = *reinterpret_cast(0x14C5648); + + if (ent_num >= gfxCfg_entCount) + { + Assert(); + } + + if (game::Dvar_FindVar("r_drawEntities")->current.enabled) + { + const unsigned int scene_ent_index = utils::hook::call(0x501D80)(); // R_AllocSceneModel() + if (scene_ent_index < 1024) + { + game::GfxSceneModel* sceneModel = &game::scene->sceneModel[scene_ent_index]; + sceneModel->model = obj->models[0]; + sceneModel->DObj_s_obj = obj; + sceneModel->entnum = static_cast(ent_num); + sceneModel->cachedLightingHandle = &lightinghandle; + sceneModel->placement.base.origin[0] = pose->origin[0]; + sceneModel->placement.base.origin[1] = pose->origin[1]; + sceneModel->placement.base.origin[2] = pose->origin[2]; + + game::AnglesToQuat(pose->angles, sceneModel->placement.base.quat); + + sceneModel->placement.scale = 1.0f; + sceneModel->radius = sceneModel->model->radius; + sceneModel->lightingOrigin[0] = *lighting_origin; + sceneModel->lightingOrigin[1] = lighting_origin[1]; + sceneModel->lightingOrigin[2] = lighting_origin[2]; + sceneModel->gfxEntIndex = 0; + + *((WORD*)scene_dpvs_sceneXModelIndex + ent_num) = static_cast(scene_ent_index); + } + } + } + + void dobj_get_lighting_origin(game::cpose_t* pose, float* lighting_origin) + { lighting_origin[0] = pose->origin[0]; lighting_origin[1] = pose->origin[1]; - lighting_origin[2] = pose->origin[2] + 4.0f; - } - - void d3dbsp::add_entities_to_scene() - { - for (auto i = 0; i < radiant_dobj_count; i++) - { - game::vec3_t lighting_origin = {}; - dobj_get_lighting_origin(&radiant_dobj[i].pose, lighting_origin); - dobj_add_to_scene(&radiant_dobj[i].obj, &radiant_dobj[i].pose, 0, lighting_origin); - } - } - - - // * - // * BSP Loading - // * - - std::string d3dbsp::loaded_bsp_path; - d3dbsp::bspGlob_s d3dbsp::comBspGlob = {}; - game::clipMap_t d3dbsp::cm = {}; - game::GfxLight d3dbsp::scene_lights[255] = {}; - - - game::cplane_s* d3dbsp::CM_GetPlanes() - { - return d3dbsp::cm.planes; - } - - int d3dbsp::CM_GetPlaneCount() - { - return d3dbsp::cm.planeCount; - } - - bool d3dbsp::Com_IsBspLoaded() - { - return comBspGlob.header != nullptr; - } - - std::uint32_t d3dbsp::Com_GetBspVersion() - { - if (!d3dbsp::Com_IsBspLoaded()) - { - return 0; - } - - return comBspGlob.header->version; - } - - char* d3dbsp::Com_ValidateBspLumpData(LumpType type, unsigned int offset, unsigned int length, unsigned int elemSize, unsigned int* count) - { - char* result = nullptr; - - ASSERT_MSG(count, "count"); - - if (length) - { - if (length + offset > comBspGlob.fileSize) - { - game::Com_Error("LoadMap: lump %i extends past end of file", type); - } - - *count = length / elemSize; - - if (elemSize * *count != length) - { - game::Com_Error("LoadMap: lump %i has funny size", type); - } - - result = (char*)comBspGlob.header + offset; - } - else - { - *count = 0; - } - - return result; - } - - bool d3dbsp::Com_GetBspLumpBool(LumpType type) - { - auto t_count = 0u; - if (d3dbsp::Com_GetBspLump(type, 1, &t_count)) - { - return true; - } - - return false; - } - + lighting_origin[2] = pose->origin[2] + 4.0f; + } + + void d3dbsp::add_entities_to_scene() + { + for (auto i = 0; i < radiant_dobj_count; i++) + { + game::vec3_t lighting_origin = {}; + dobj_get_lighting_origin(&radiant_dobj[i].pose, lighting_origin); + dobj_add_to_scene(&radiant_dobj[i].obj, &radiant_dobj[i].pose, 0, lighting_origin); + } + } + + + // * + // * BSP Loading + // * + + std::string d3dbsp::loaded_bsp_path; + d3dbsp::bspGlob_s d3dbsp::comBspGlob = {}; + game::clipMap_t d3dbsp::cm = {}; + game::GfxLight d3dbsp::scene_lights[255] = {}; + + + game::cplane_s* d3dbsp::CM_GetPlanes() + { + return d3dbsp::cm.planes; + } + + int d3dbsp::CM_GetPlaneCount() + { + return d3dbsp::cm.planeCount; + } + + bool d3dbsp::Com_IsBspLoaded() + { + return comBspGlob.header != nullptr; + } + + std::uint32_t d3dbsp::Com_GetBspVersion() + { + if (!d3dbsp::Com_IsBspLoaded()) + { + return 0; + } + + return comBspGlob.header->version; + } + + char* d3dbsp::Com_ValidateBspLumpData(LumpType type, unsigned int offset, unsigned int length, unsigned int elemSize, unsigned int* count) + { + char* result = nullptr; + + ASSERT_MSG(count, "count"); + + if (length) + { + if (length + offset > comBspGlob.fileSize) + { + game::Com_Error("LoadMap: lump %i extends past end of file", type); + } + + *count = length / elemSize; + + if (elemSize * *count != length) + { + game::Com_Error("LoadMap: lump %i has funny size", type); + } + + result = (char*)comBspGlob.header + offset; + } + else + { + *count = 0; + } + + return result; + } + + bool d3dbsp::Com_GetBspLumpBool(LumpType type) + { + auto t_count = 0u; + if (d3dbsp::Com_GetBspLump(type, 1, &t_count)) + { + return true; + } + + return false; + } + #pragma warning(push) #pragma warning(disable: 4146) void d3dbsp::Com_SaveLump(LumpType type, const void* newLump, unsigned int size) { const void* chunkData[100]; - + BspHeader new_header = {}; new_header.ident = 1347633737; new_header.version = 22; - new_header.chunkCount = 0; + new_header.chunkCount = 0; bool isNewChunk = true; - unsigned int offset = 8 * comBspGlob.header->chunkCount + 12; + unsigned int offset = 8 * comBspGlob.header->chunkCount + 12; for (auto chunkIter = 0u; chunkIter < comBspGlob.header->chunkCount; ++chunkIter) { @@ -195,7 +195,7 @@ namespace components new_header.chunks[new_header.chunkCount].type = chunk->type; new_header.chunks[new_header.chunkCount].length = chunk->length; chunkData[new_header.chunkCount++] = (char*)comBspGlob.header + offset; - } + } offset += (chunk->length + 3) & 0xFFFFFFFC; } @@ -204,287 +204,287 @@ namespace components new_header.chunks[new_header.chunkCount].type = type; new_header.chunks[new_header.chunkCount].length = size; chunkData[new_header.chunkCount++] = newLump; - } + } if (const auto h = game::FS_OpenFileOverwrite(comBspGlob.name); h) - { + { game::FS_Write(&new_header, 8 * new_header.chunkCount + 12, h); for (auto chunkIter = 0u; chunkIter < new_header.chunkCount; ++chunkIter) - { - game::FS_Write(chunkData[chunkIter], new_header.chunks[chunkIter].length, h); - const unsigned int zeroCount = -new_header.chunks[chunkIter].length & 3; - - if (zeroCount) - { - unsigned int zero; - game::FS_Write(&zero, zeroCount, h); - } + { + game::FS_Write(chunkData[chunkIter], new_header.chunks[chunkIter].length, h); + const unsigned int zeroCount = -new_header.chunks[chunkIter].length & 3; + + if (zeroCount) + { + unsigned int zero; + game::FS_Write(&zero, zeroCount, h); + } } - - game::FS_FCloseFile(h); + + game::FS_FCloseFile(h); d3dbsp::radiant_load_bsp(d3dbsp::loaded_bsp_path.c_str(), true); } else - { + { game::Com_Error("Failed to open file %s for writing", comBspGlob.name); } - } -#pragma warning(pop) - - const void* d3dbsp::Com_GetBspLump(LumpType type, unsigned int elemSize, unsigned int* count) - { - const void* result = nullptr; - unsigned int offset; - - ASSERT_MSG(Com_IsBspLoaded(), "Com_IsBspLoaded()"); - - if (comBspGlob.header->version > 18) - { - offset = 8 * comBspGlob.header->chunkCount + 12; - for (auto chunkIter = 0u; chunkIter < comBspGlob.header->chunkCount; ++chunkIter) - { - if (comBspGlob.header->chunks[chunkIter].type == type) - { - return Com_ValidateBspLumpData(type, offset, comBspGlob.header->chunks[chunkIter].length, elemSize, count); - } - - offset += (comBspGlob.header->chunks[chunkIter].length + 3) & 0xFFFFFFFC; - } - - *count = 0; - } - else - { - *count = 0; - } - - return result; - } - - const char* Com_GetHunkStringCopy(const char* string) - { - const auto len = strlen(string); - const auto hunk_copy = reinterpret_cast(game::Hunk_Alloc(len + 1)); - - memcpy(hunk_copy, string, len + 1); - return hunk_copy; - } - - const char* Com_GetLightDefName(const char* defName, game::ComPrimaryLight* primaryLights, unsigned int primaryLightCount) - { - for (auto primaryLightIndex = 0u; primaryLightIndex < primaryLightCount; ++primaryLightIndex) - { - if (primaryLights[primaryLightIndex].defName && !strcmp(defName, primaryLights[primaryLightIndex].defName)) - { - return primaryLights[primaryLightIndex].defName; - } - } - - return Com_GetHunkStringCopy(defName); - } - - void Com_LoadPrimaryLights() - { - unsigned int primary_light_count; - auto bsp_lights = (game::DiskPrimaryLight*)(d3dbsp::Com_GetBspLump(d3dbsp::LUMP_PRIMARY_LIGHTS, 128, &primary_light_count)); - - if (primary_light_count <= 1) - { - game::Com_Error("Com_LoadPrimaryLights: no primary lights in bsp\n"); - } - - game::comworld->primaryLightCount = primary_light_count; - game::comworld->primaryLights = reinterpret_cast(game::Hunk_Alloc(sizeof(game::ComPrimaryLight) * primary_light_count)); - - game::ComPrimaryLight* out = game::comworld->primaryLights; - auto lightIndex = 0u; - - while (lightIndex < primary_light_count) - { - out->type = bsp_lights->type; - out->canUseShadowMap = bsp_lights->canUseShadowMap; - out->exponent = static_cast(bsp_lights->exponent); - out->color[0] = bsp_lights->color[0]; - out->color[1] = bsp_lights->color[1]; - out->color[2] = bsp_lights->color[2]; - out->dir[0] = bsp_lights->dir[0]; - out->dir[1] = bsp_lights->dir[1]; - out->dir[2] = bsp_lights->dir[2]; - out->origin[0] = bsp_lights->origin[0]; - out->origin[1] = bsp_lights->origin[1]; - out->origin[2] = bsp_lights->origin[2]; - out->radius = bsp_lights->radius; - out->cosHalfFovOuter = bsp_lights->cosHalfFovOuter; - out->cosHalfFovInner = bsp_lights->cosHalfFovInner; - out->rotationLimit = bsp_lights->rotationLimit; - out->translationLimit = bsp_lights->translationLimit; - - if (bsp_lights->type && bsp_lights->type != 1) - { - out->defName = Com_GetLightDefName(bsp_lights->defName, game::comworld->primaryLights, lightIndex); - if (out->cosHalfFovOuter >= out->cosHalfFovInner) - { - out->cosHalfFovInner = out->cosHalfFovOuter * 0.75f + 0.25f; - } - if (out->rotationLimit == 1.0f) - { - out->cosHalfFovExpanded = out->cosHalfFovOuter; - } - else if (-out->cosHalfFovOuter < out->rotationLimit) - { - out->cosHalfFovExpanded = utils::vector::cos_of_sum_of_arc_cos(out->cosHalfFovOuter, out->rotationLimit); - } - else - { - out->cosHalfFovExpanded = -1.0f; - } - } - else - { - out->defName = nullptr; - out->cosHalfFovExpanded = bsp_lights->cosHalfFovOuter; - } - - ++lightIndex; - ++bsp_lights; - ++out; - } - } - - void R_LoadPrimaryLights(unsigned int bsp_version) - { - if (bsp_version > 14) - { - game::s_world->primaryLightCount = game::comworld->primaryLightCount; // Com_GetPrimaryLightCount(); - - if (game::s_world->primaryLightCount <= 1) - { - game::s_world->sunPrimaryLightIndex = 0; - } - else - { - game::s_world->sunPrimaryLightIndex = game::comworld->primaryLights[1].type == 1; // Com_GetPrimaryLight(1u)->type == 1; - } - - for (auto light_index = 0u; light_index < game::s_world->primaryLightCount; ++light_index) - { - const auto primary_light = &game::comworld->primaryLights[light_index]; // Com_GetPrimaryLight(lightIndex); - if (primary_light->defName) - { - game::R_RegisterLightDef(primary_light->defName); - } - } - } - else - { - game::s_world->sunPrimaryLightIndex = 1; - game::s_world->primaryLightCount = 2; - } - } - - void R_InitPrimaryLights(game::GfxLight* primaryLights) - { - for (auto lightIndex = 0u; lightIndex < game::s_world->primaryLightCount; ++lightIndex) - { - const auto in = &game::comworld->primaryLights[lightIndex]; //Com_GetPrimaryLight(lightIndex); - const auto out = &primaryLights[lightIndex]; - - out->type = in->type; - out->canUseShadowMap = in->canUseShadowMap; - out->color[0] = in->color[0]; - out->color[1] = in->color[1]; - out->color[2] = in->color[2]; - out->dir[0] = in->dir[0]; - out->dir[1] = in->dir[1]; - out->dir[2] = in->dir[2]; - out->origin[0] = in->origin[0]; - out->origin[1] = in->origin[1]; - out->origin[2] = in->origin[2]; - out->radius = in->radius; - out->cosHalfFovOuter = in->cosHalfFovOuter; - out->cosHalfFovInner = in->cosHalfFovInner; - out->exponent = static_cast(in->exponent); - out->def = nullptr; - - if (in->defName) - { - out->def = game::R_RegisterLightDef(in->defName); - } - } - } - - void CMod_LoadPlanes() - { - unsigned int count; - auto in = static_cast(d3dbsp::Com_GetBspLump(d3dbsp::LUMP_PLANES, sizeof(game::dplane_t), &count)); - if (!count) - { - game::Com_Error("CMod_LoadPlanes: Map with no planes"); - } - - if (count > 0x10000) - { - game::Com_Error("CMod_LoadPlanes: Number of planes exceeds 65536"); - } - - d3dbsp::cm.planes = reinterpret_cast(game::Hunk_Alloc(sizeof(game::cplane_s) * count)); - d3dbsp::cm.planeCount = static_cast(count); - - game::cplane_s* out = d3dbsp::cm.planes; - - for (auto plane = 0u; plane < count; ++plane) - { - char bits = 0; - - for (auto axis = 0u; axis < 3; ++axis) - { - out->normal[axis] = in->normal[axis]; - if (out->normal[axis] < 0.0f) - { - bits |= 1 << axis; - } - } - - out->dist = in->dist; - char n0; - - if (out->normal[0] == 1.0f) - { - n0 = 0; - } - else - { - char n1; - if (out->normal[1] == 1.0f) - { - n1 = 1; - } - else - { - char n2; - if (out->normal[2] == 1.0f) - { - n2 = 2; - } - else - { - n2 = 3; - } - - n1 = n2; - } - - n0 = n1; - } - - out->type = n0; - out->signbits = bits; - ++in; - ++out; - } - } - + } +#pragma warning(pop) + + const void* d3dbsp::Com_GetBspLump(LumpType type, unsigned int elemSize, unsigned int* count) + { + const void* result = nullptr; + unsigned int offset; + + ASSERT_MSG(Com_IsBspLoaded(), "Com_IsBspLoaded()"); + + if (comBspGlob.header->version > 18) + { + offset = 8 * comBspGlob.header->chunkCount + 12; + for (auto chunkIter = 0u; chunkIter < comBspGlob.header->chunkCount; ++chunkIter) + { + if (comBspGlob.header->chunks[chunkIter].type == type) + { + return Com_ValidateBspLumpData(type, offset, comBspGlob.header->chunks[chunkIter].length, elemSize, count); + } + + offset += (comBspGlob.header->chunks[chunkIter].length + 3) & 0xFFFFFFFC; + } + + *count = 0; + } + else + { + *count = 0; + } + + return result; + } + + const char* Com_GetHunkStringCopy(const char* string) + { + const auto len = strlen(string); + const auto hunk_copy = reinterpret_cast(game::Hunk_Alloc(len + 1)); + + memcpy(hunk_copy, string, len + 1); + return hunk_copy; + } + + const char* Com_GetLightDefName(const char* defName, game::ComPrimaryLight* primaryLights, unsigned int primaryLightCount) + { + for (auto primaryLightIndex = 0u; primaryLightIndex < primaryLightCount; ++primaryLightIndex) + { + if (primaryLights[primaryLightIndex].defName && !strcmp(defName, primaryLights[primaryLightIndex].defName)) + { + return primaryLights[primaryLightIndex].defName; + } + } + + return Com_GetHunkStringCopy(defName); + } + + void Com_LoadPrimaryLights() + { + unsigned int primary_light_count; + auto bsp_lights = (game::DiskPrimaryLight*)(d3dbsp::Com_GetBspLump(d3dbsp::LUMP_PRIMARY_LIGHTS, 128, &primary_light_count)); + + if (primary_light_count <= 1) + { + game::Com_Error("Com_LoadPrimaryLights: no primary lights in bsp\n"); + } + + game::comworld->primaryLightCount = primary_light_count; + game::comworld->primaryLights = reinterpret_cast(game::Hunk_Alloc(sizeof(game::ComPrimaryLight) * primary_light_count)); + + game::ComPrimaryLight* out = game::comworld->primaryLights; + auto lightIndex = 0u; + + while (lightIndex < primary_light_count) + { + out->type = bsp_lights->type; + out->canUseShadowMap = bsp_lights->canUseShadowMap; + out->exponent = static_cast(bsp_lights->exponent); + out->color[0] = bsp_lights->color[0]; + out->color[1] = bsp_lights->color[1]; + out->color[2] = bsp_lights->color[2]; + out->dir[0] = bsp_lights->dir[0]; + out->dir[1] = bsp_lights->dir[1]; + out->dir[2] = bsp_lights->dir[2]; + out->origin[0] = bsp_lights->origin[0]; + out->origin[1] = bsp_lights->origin[1]; + out->origin[2] = bsp_lights->origin[2]; + out->radius = bsp_lights->radius; + out->cosHalfFovOuter = bsp_lights->cosHalfFovOuter; + out->cosHalfFovInner = bsp_lights->cosHalfFovInner; + out->rotationLimit = bsp_lights->rotationLimit; + out->translationLimit = bsp_lights->translationLimit; + + if (bsp_lights->type && bsp_lights->type != 1) + { + out->defName = Com_GetLightDefName(bsp_lights->defName, game::comworld->primaryLights, lightIndex); + if (out->cosHalfFovOuter >= out->cosHalfFovInner) + { + out->cosHalfFovInner = out->cosHalfFovOuter * 0.75f + 0.25f; + } + if (out->rotationLimit == 1.0f) + { + out->cosHalfFovExpanded = out->cosHalfFovOuter; + } + else if (-out->cosHalfFovOuter < out->rotationLimit) + { + out->cosHalfFovExpanded = utils::vector::cos_of_sum_of_arc_cos(out->cosHalfFovOuter, out->rotationLimit); + } + else + { + out->cosHalfFovExpanded = -1.0f; + } + } + else + { + out->defName = nullptr; + out->cosHalfFovExpanded = bsp_lights->cosHalfFovOuter; + } + + ++lightIndex; + ++bsp_lights; + ++out; + } + } + + void R_LoadPrimaryLights(unsigned int bsp_version) + { + if (bsp_version > 14) + { + game::s_world->primaryLightCount = game::comworld->primaryLightCount; // Com_GetPrimaryLightCount(); + + if (game::s_world->primaryLightCount <= 1) + { + game::s_world->sunPrimaryLightIndex = 0; + } + else + { + game::s_world->sunPrimaryLightIndex = game::comworld->primaryLights[1].type == 1; // Com_GetPrimaryLight(1u)->type == 1; + } + + for (auto light_index = 0u; light_index < game::s_world->primaryLightCount; ++light_index) + { + const auto primary_light = &game::comworld->primaryLights[light_index]; // Com_GetPrimaryLight(lightIndex); + if (primary_light->defName) + { + game::R_RegisterLightDef(primary_light->defName); + } + } + } + else + { + game::s_world->sunPrimaryLightIndex = 1; + game::s_world->primaryLightCount = 2; + } + } + + void R_InitPrimaryLights(game::GfxLight* primaryLights) + { + for (auto lightIndex = 0u; lightIndex < game::s_world->primaryLightCount; ++lightIndex) + { + const auto in = &game::comworld->primaryLights[lightIndex]; //Com_GetPrimaryLight(lightIndex); + const auto out = &primaryLights[lightIndex]; + + out->type = in->type; + out->canUseShadowMap = in->canUseShadowMap; + out->color[0] = in->color[0]; + out->color[1] = in->color[1]; + out->color[2] = in->color[2]; + out->dir[0] = in->dir[0]; + out->dir[1] = in->dir[1]; + out->dir[2] = in->dir[2]; + out->origin[0] = in->origin[0]; + out->origin[1] = in->origin[1]; + out->origin[2] = in->origin[2]; + out->radius = in->radius; + out->cosHalfFovOuter = in->cosHalfFovOuter; + out->cosHalfFovInner = in->cosHalfFovInner; + out->exponent = static_cast(in->exponent); + out->def = nullptr; + + if (in->defName) + { + out->def = game::R_RegisterLightDef(in->defName); + } + } + } + + void CMod_LoadPlanes() + { + unsigned int count; + auto in = static_cast(d3dbsp::Com_GetBspLump(d3dbsp::LUMP_PLANES, sizeof(game::dplane_t), &count)); + if (!count) + { + game::Com_Error("CMod_LoadPlanes: Map with no planes"); + } + + if (count > 0x10000) + { + game::Com_Error("CMod_LoadPlanes: Number of planes exceeds 65536"); + } + + d3dbsp::cm.planes = reinterpret_cast(game::Hunk_Alloc(sizeof(game::cplane_s) * count)); + d3dbsp::cm.planeCount = static_cast(count); + + game::cplane_s* out = d3dbsp::cm.planes; + + for (auto plane = 0u; plane < count; ++plane) + { + char bits = 0; + + for (auto axis = 0u; axis < 3; ++axis) + { + out->normal[axis] = in->normal[axis]; + if (out->normal[axis] < 0.0f) + { + bits |= 1 << axis; + } + } + + out->dist = in->dist; + char n0; + + if (out->normal[0] == 1.0f) + { + n0 = 0; + } + else + { + char n1; + if (out->normal[1] == 1.0f) + { + n1 = 1; + } + else + { + char n2; + if (out->normal[2] == 1.0f) + { + n2 = 2; + } + else + { + n2 = 3; + } + + n1 = n2; + } + + n0 = n1; + } + + out->type = n0; + out->signbits = bits; + ++in; + ++out; + } + } + void CMod_LoadCollisionVertsAndTris() { unsigned int vert_count; @@ -493,9 +493,9 @@ namespace components d3dbsp::cm.verts = reinterpret_cast(game::Hunk_Alloc(sizeof(float[3]) * vert_count)); d3dbsp::cm.vertCount = static_cast(vert_count); memcpy(d3dbsp::cm.verts, verts, sizeof(float[3]) * vert_count); - - // # + + // # // CMod_LoadCollisionTriangles(); unsigned int tri_count; @@ -504,584 +504,584 @@ namespace components d3dbsp::cm.triIndices = reinterpret_cast(game::Hunk_Alloc(sizeof(uint16_t) * tri_count)); d3dbsp::cm.triCount = static_cast(tri_count) / 3; memcpy(d3dbsp::cm.triIndices, tris, sizeof(uint16_t) * tri_count); - } - + } + const char* Com_EntityString(unsigned int* num_entity_chars) { if (!d3dbsp::Com_IsBspLoaded()) { Assert(); - } - + } + unsigned int count; const char* entity_string = static_cast(d3dbsp::Com_GetBspLump(d3dbsp::LUMP_ENTITIES, 1u, &count)); - + if (num_entity_chars) { *num_entity_chars = count; - } + } return entity_string; - } - + } + game::MapEnts* MapEnts_GetFromString(const char* name, const char* entity_string, int num_entity_chars) { - const auto ents = reinterpret_cast(game::Hunk_Alloc(sizeof(game::MapEnts))); - ents->name = Com_GetHunkStringCopy(name); + const auto ents = reinterpret_cast(game::Hunk_Alloc(sizeof(game::MapEnts))); + ents->name = Com_GetHunkStringCopy(name); - ents->entityString = reinterpret_cast(game::Hunk_Alloc(num_entity_chars)); - memcpy(ents->entityString, entity_string, num_entity_chars); - ents->numEntityChars = num_entity_chars; + ents->entityString = reinterpret_cast(game::Hunk_Alloc(num_entity_chars)); + memcpy(ents->entityString, entity_string, num_entity_chars); + ents->numEntityChars = num_entity_chars; return ents; - } - - void CMod_LoadEntityString() - { - unsigned int numEntityChars; - - const char* entityString = Com_EntityString(&numEntityChars); - d3dbsp::cm.mapEnts = MapEnts_GetFromString(d3dbsp::cm.name, entityString, numEntityChars); - } - - bool d3dbsp::Com_LoadBsp(const char* filename) - { - int h; - comBspGlob.fileSize = game::FS_FOpenFileRead(filename, &h); - - if (!h) - { - game::printf_to_console("[ERR][BSP] Couldn't open %s\n", filename); - return false; - } - - comBspGlob.header = reinterpret_cast(game::Z_Malloc(comBspGlob.fileSize)); - - unsigned int bytesRead; - bytesRead = game::FS_Read(comBspGlob.header, comBspGlob.fileSize, h); - game::FS_FCloseFile(h); - - if (bytesRead != comBspGlob.fileSize) - { - game::Z_Free(comBspGlob.header); - game::printf_to_console("[ERR][BSP] bytesRead != comBspGlob.fileSize"); - return false; - } - - // skip checksum and version checks for now - - memcpy(comBspGlob.name, filename, strlen(filename) + 1); - - return d3dbsp::Com_IsBspLoaded(); - } - - void d3dbsp::shutdown_bsp() - { - d3dbsp::dobj_clear_list(); - - comBspGlob.loadedLumpData = nullptr; - - game::Z_Free(comBspGlob.header); - - comBspGlob.header = nullptr; - comBspGlob.name[0] = 0; - - memset(&d3dbsp::cm, 0, sizeof(d3dbsp::cm)); - memset(&d3dbsp::scene_lights, 0, sizeof(d3dbsp::scene_lights)); - - game::comworld->isInUse = false; - - cdeclcall(void, 0x52E7D0); // R_ShutdownWorld - game::rgp->world = nullptr; - - memset(game::s_world, 0, 0x2D0 /*sizeof(game::GfxWorld)*/); - - if (game::rg->registered) - { - cdeclcall(void, 0x529D50); // R_ResetModelLighting - } - } - - bool d3dbsp::radiant_load_bsp(const char* bsppath, bool reload) - { - const auto con = GetConsoleWindow(); - - if (d3dbsp::Com_IsBspLoaded()) - { - d3dbsp::shutdown_bsp(); - } - - if (d3dbsp::Com_LoadBsp(bsppath)) - { - if (!reload) ShowWindow(con, SW_SHOW); - game::printf_to_console("[BSP] loading bsp: %s\n", bsppath); - - // * - // clipmap - - if(!reload) game::printf_to_console("[BSP] clipmap ..\n"); - - // CM_LoadMapFromBsp - d3dbsp::cm.name = Com_GetHunkStringCopy(bsppath); - CMod_LoadPlanes(); - CMod_LoadCollisionVertsAndTris(); - CMod_LoadEntityString(); - d3dbsp::cm.isInUse = 1; - - - // * - // entities (script_models only for now) - - // spawn: - /* "classname" "script_model" - * "model" "vehicle_80s_sedan1_red_destructible_mp" - * "origin" "-235.1 1394.7 230.2" - * "angles" "358.94 101.765 3.47606" */ - - // exclude: - /* "script_exploder" - * "script_gameobjectname" */ - - if (dvars::bsp_load_entities->current.enabled && d3dbsp::cm.isInUse && d3dbsp::cm.mapEnts && d3dbsp::cm.mapEnts->numEntityChars) - { - if (!reload) game::printf_to_console("[BSP] entities ..\n"); - - // create a spawnvar for each map entity - utils::spawnvars script_models(d3dbsp::cm.mapEnts->entityString); - - // get name, origin and angles for script_models (see spawn/exclude note) - std::vector dobjs; - script_models.get_script_models_for_dobj(dobjs); - - if (!dobjs.empty()) - { - for(radiant_dobj_count = 0; radiant_dobj_count < static_cast(dobjs.size()) && radiant_dobj_count < 512; radiant_dobj_count++) - { - game::DObjModel_s dobjModels = {}; - dobjModels.model = game::R_RegisterModel(dobjs[radiant_dobj_count].model_name.c_str()); - dobjModels.boneName = 0; - dobjModels.ignoreCollision = true; - - game::DObjCreate(&dobjModels, &radiant_dobj[radiant_dobj_count].obj, 1, nullptr, 0); - - utils::vector::copy(dobjs[radiant_dobj_count].origin, radiant_dobj[radiant_dobj_count].pose.origin); - utils::vector::copy(dobjs[radiant_dobj_count].angles, radiant_dobj[radiant_dobj_count].pose.angles); - } - } - - if (!reload) game::printf_to_console("[BSP] loaded %d entities\n", radiant_dobj_count); - } - - - // * - // load com world - - if (!reload) game::printf_to_console("[BSP] primary lights ..\n"); - - Com_LoadPrimaryLights(); - game::comworld->name = Com_GetHunkStringCopy(bsppath); - game::comworld->isInUse = true; - - - // * - // R_LoadPrimaryLights is missing in R_LoadWorldInternal (s_world ...) - // so load it here and nop s_world memset at the beginning of R_LoadWorld->R_LoadWorldInternal - - R_LoadPrimaryLights(d3dbsp::Com_GetBspVersion()); - R_InitPrimaryLights(d3dbsp::scene_lights); - - unsigned int checksum; - - if (!reload) game::printf_to_console("[BSP] the world ..\n"); - - // R_LoadWorld - utils::hook::call(0x52E450)(bsppath, &checksum, 0); - - if (game::s_world->sunPrimaryLightIndex) - { - memcpy(&d3dbsp::scene_lights[game::s_world->sunPrimaryLightIndex], game::s_world->sunLight, sizeof(game::GfxLight)); - } - - game::R_SortWorldSurfaces(); - d3dbsp::loaded_bsp_path = bsppath; - - game::printf_to_console("[BSP] finished loading bsp\n"); - if (!reload) ShowWindow(con, SW_HIDE); - - return true; - } - - return false; - } - - /** - * @brief reload currently loaded bsp\n - * tries to load the bsp for the currently loaded .map otherwise - */ - void d3dbsp::reload_bsp() - { - if (d3dbsp::Com_IsBspLoaded() && !d3dbsp::loaded_bsp_path.empty()) - { - d3dbsp::radiant_load_bsp(d3dbsp::loaded_bsp_path.c_str(), true); - } - else - { - std::string mapname; - if (game::current_map_filepath && game::current_map_filepath != "unnamed.map"s) - { - mapname = std::string(game::current_map_filepath).substr(std::string(game::current_map_filepath).find_last_of("\\") + 1); - utils::replace(mapname, ".map", ".d3dbsp"); - - const bool is_mp = utils::starts_with(mapname, "mp_"); - const std::string bsp_path = (is_mp ? R"(maps\mp\)"s : R"(maps\)"s) + mapname; - - d3dbsp::radiant_load_bsp(bsp_path.c_str()); - } - else - { - game::printf_to_console("Load a .map first!"); - } - } - } - - /** - * @brief run batch to compile bsp - * @param bsp_name plain map name with no extension or pathing - * @param generate_createfx automatically generate createfx files + place into raw instead of bin/IW3xRadiant - */ - void d3dbsp::compile_bsp(const std::string& bsp_name, bool generate_createfx) - { - //game::printf_to_console("^1generate_createfx is %s", generate_createfx ? "true" : "false"); - game::printf_to_console("[BSP] Compiling bsp for map: %s ...", bsp_name.c_str()); - - const auto egui = GET_GUI(ggui::entity_dialog); - - const char* base_path = egui->get_value_for_key_from_epairs(game::g_qeglobals->d_project_entity->epairs, "basepath"); - const char* map_path = egui->get_value_for_key_from_epairs(game::g_qeglobals->d_project_entity->epairs, "mapspath"); - - const bool is_mp = utils::starts_with(bsp_name, "mp_"); - const std::string bsp_path = (is_mp ? R"(maps\mp\)"s : R"(maps\)"s) + bsp_name + ".d3dbsp"; - - std::string bps_args; - bps_args += (dvars::bsp_compile_onlyents->current.enabled ? "-onlyents" : "") + " "s; - bps_args += (dvars::bsp_compile_samplescale_enabled->current.enabled ? ("-samplescale " + std::to_string(dvars::bsp_compile_samplescale->current.value)) : "") + " "s; - bps_args += (dvars::bsp_compile_custom_cmd_enabled->current.enabled ? dvars::bsp_compile_custom_cmd->current.string : "") + " "s; - utils::rtrim(bps_args); - - std::string light_args; - light_args += (dvars::bsp_compile_light_fast->current.enabled ? "-fast" : "") + " "s; - light_args += (dvars::bsp_compile_light_extra->current.enabled ? "-extra" : "") + " "s; - light_args += (dvars::bsp_compile_light_modelshadow->current.enabled ? "-modelshadow" : "") + " "s; - light_args += (dvars::bsp_compile_light_dump->current.enabled ? "-dumpoptions" : "") + " "s; - light_args += (dvars::bsp_compile_light_traces_enabled->current.enabled ? ("-traces " + std::to_string(dvars::bsp_compile_light_traces->current.integer)) : "") + " "s; - light_args += (dvars::bsp_compile_light_custom_cmd_enabled->current.enabled ? dvars::bsp_compile_light_custom_cmd->current.string : "") + " "s; - utils::rtrim(light_args); - - std::string args; - - // launch arg - args += R"(")"s + base_path + R"(\bin\IW3xRadiant\batch\compile_bsp.bat")"s + " "; - - // bsppath - args += R"(")"s + base_path + (is_mp ? R"(\raw\maps\mp\")"s : R"(\raw\maps\")"s) + " "s; - - // mapsourcepath - args += R"(")"s + map_path + R"(\")"s + " "s; - - // treepath - args += R"(")"s + base_path + R"(\")"s + " "s; - - // mapname - args += bsp_name + " "s; - - // parmBSPOptions - args += (!bps_args.empty() ? R"(")" + bps_args + R"(" )" : "- "); - - // parmLightOptions - args += (!light_args.empty() ? R"(")" + light_args + R"(" )" : "- "); - - // compileBSP - args += (dvars::bsp_compile_bsp->current.enabled ? "1 "s : "0 "s); - - // compileLight - args += (dvars::bsp_compile_light->current.enabled ? "1 "s : "0 "s); - - const auto process = components::process::get(); - process->set_process_type(process::PROC_TYPE_BATCH); - process->set_indicator(process::INDICATOR_TYPE_SPINNER); - process->set_output(true); - process->set_arguments(args); - process->set_post_process_callback([bsp_path, generate_createfx] - { - game::printf_to_console("^2[PROCESS] Post-Process Callback"); - - if (d3dbsp::radiant_load_bsp(bsp_path.c_str(), true)) - { - if (dvars::bsp_gen_reflections_on_compile->current.enabled) - { - //components::renderer::on_cam_paint_post_rendercommands - dvars::set_bool(dvars::r_reflectionprobe_generate, true); - } - else - { - if (dvars::bsp_show_bsp_after_compile->current.enabled) - { - command::execute("toggle_bsp_radiant"); - dvars::set_bool(dvars::r_draw_bsp, dvars::bsp_show_bsp_after_compile->current.enabled); - } - } - } - + } + + void CMod_LoadEntityString() + { + unsigned int numEntityChars; + + const char* entityString = Com_EntityString(&numEntityChars); + d3dbsp::cm.mapEnts = MapEnts_GetFromString(d3dbsp::cm.name, entityString, numEntityChars); + } + + bool d3dbsp::Com_LoadBsp(const char* filename) + { + int h; + comBspGlob.fileSize = game::FS_FOpenFileRead(filename, &h); + + if (!h) + { + game::printf_to_console("[ERR][BSP] Couldn't open %s\n", filename); + return false; + } + + comBspGlob.header = reinterpret_cast(game::Z_Malloc(comBspGlob.fileSize)); + + unsigned int bytesRead; + bytesRead = game::FS_Read(comBspGlob.header, comBspGlob.fileSize, h); + game::FS_FCloseFile(h); + + if (bytesRead != comBspGlob.fileSize) + { + game::Z_Free(comBspGlob.header); + game::printf_to_console("[ERR][BSP] bytesRead != comBspGlob.fileSize"); + return false; + } + + // skip checksum and version checks for now + + memcpy(comBspGlob.name, filename, strlen(filename) + 1); + + return d3dbsp::Com_IsBspLoaded(); + } + + void d3dbsp::shutdown_bsp() + { + d3dbsp::dobj_clear_list(); + + comBspGlob.loadedLumpData = nullptr; + + game::Z_Free(comBspGlob.header); + + comBspGlob.header = nullptr; + comBspGlob.name[0] = 0; + + memset(&d3dbsp::cm, 0, sizeof(d3dbsp::cm)); + memset(&d3dbsp::scene_lights, 0, sizeof(d3dbsp::scene_lights)); + + game::comworld->isInUse = false; + + cdeclcall(void, 0x52E7D0); // R_ShutdownWorld + game::rgp->world = nullptr; + + memset(game::s_world, 0, 0x2D0 /*sizeof(game::GfxWorld)*/); + + if (game::rg->registered) + { + cdeclcall(void, 0x529D50); // R_ResetModelLighting + } + } + + bool d3dbsp::radiant_load_bsp(const char* bsppath, bool reload) + { + const auto con = GetConsoleWindow(); + + if (d3dbsp::Com_IsBspLoaded()) + { + d3dbsp::shutdown_bsp(); + } + + if (d3dbsp::Com_LoadBsp(bsppath)) + { + if (!reload) ShowWindow(con, SW_SHOW); + game::printf_to_console("[BSP] loading bsp: %s\n", bsppath); + + // * + // clipmap + + if(!reload) game::printf_to_console("[BSP] clipmap ..\n"); + + // CM_LoadMapFromBsp + d3dbsp::cm.name = Com_GetHunkStringCopy(bsppath); + CMod_LoadPlanes(); + CMod_LoadCollisionVertsAndTris(); + CMod_LoadEntityString(); + d3dbsp::cm.isInUse = 1; + + + // * + // entities (script_models only for now) + + // spawn: + /* "classname" "script_model" + * "model" "vehicle_80s_sedan1_red_destructible_mp" + * "origin" "-235.1 1394.7 230.2" + * "angles" "358.94 101.765 3.47606" */ + + // exclude: + /* "script_exploder" + * "script_gameobjectname" */ + + if (dvars::bsp_load_entities->current.enabled && d3dbsp::cm.isInUse && d3dbsp::cm.mapEnts && d3dbsp::cm.mapEnts->numEntityChars) + { + if (!reload) game::printf_to_console("[BSP] entities ..\n"); + + // create a spawnvar for each map entity + utils::spawnvars script_models(d3dbsp::cm.mapEnts->entityString); + + // get name, origin and angles for script_models (see spawn/exclude note) + std::vector dobjs; + script_models.get_script_models_for_dobj(dobjs); + + if (!dobjs.empty()) + { + for(radiant_dobj_count = 0; radiant_dobj_count < static_cast(dobjs.size()) && radiant_dobj_count < 512; radiant_dobj_count++) + { + game::DObjModel_s dobjModels = {}; + dobjModels.model = game::R_RegisterModel(dobjs[radiant_dobj_count].model_name.c_str()); + dobjModels.boneName = 0; + dobjModels.ignoreCollision = true; + + game::DObjCreate(&dobjModels, &radiant_dobj[radiant_dobj_count].obj, 1, nullptr, 0); + + utils::vector::copy(dobjs[radiant_dobj_count].origin, radiant_dobj[radiant_dobj_count].pose.origin); + utils::vector::copy(dobjs[radiant_dobj_count].angles, radiant_dobj[radiant_dobj_count].pose.angles); + } + } + + if (!reload) game::printf_to_console("[BSP] loaded %d entities\n", radiant_dobj_count); + } + + + // * + // load com world + + if (!reload) game::printf_to_console("[BSP] primary lights ..\n"); + + Com_LoadPrimaryLights(); + game::comworld->name = Com_GetHunkStringCopy(bsppath); + game::comworld->isInUse = true; + + + // * + // R_LoadPrimaryLights is missing in R_LoadWorldInternal (s_world ...) + // so load it here and nop s_world memset at the beginning of R_LoadWorld->R_LoadWorldInternal + + R_LoadPrimaryLights(d3dbsp::Com_GetBspVersion()); + R_InitPrimaryLights(d3dbsp::scene_lights); + + unsigned int checksum; + + if (!reload) game::printf_to_console("[BSP] the world ..\n"); + + // R_LoadWorld + utils::hook::call(0x52E450)(bsppath, &checksum, 0); + + if (game::s_world->sunPrimaryLightIndex) + { + memcpy(&d3dbsp::scene_lights[game::s_world->sunPrimaryLightIndex], game::s_world->sunLight, sizeof(game::GfxLight)); + } + + game::R_SortWorldSurfaces(); + d3dbsp::loaded_bsp_path = bsppath; + + game::printf_to_console("[BSP] finished loading bsp\n"); + if (!reload) ShowWindow(con, SW_HIDE); + + return true; + } + + return false; + } + + /** + * @brief reload currently loaded bsp\n + * tries to load the bsp for the currently loaded .map otherwise + */ + void d3dbsp::reload_bsp() + { + if (d3dbsp::Com_IsBspLoaded() && !d3dbsp::loaded_bsp_path.empty()) + { + d3dbsp::radiant_load_bsp(d3dbsp::loaded_bsp_path.c_str(), true); + } + else + { + std::string mapname; + if (game::current_map_filepath && game::current_map_filepath != "unnamed.map"s) + { + mapname = std::string(game::current_map_filepath).substr(std::string(game::current_map_filepath).find_last_of("\\") + 1); + utils::replace(mapname, ".map", ".d3dbsp"); + + const bool is_mp = utils::starts_with(mapname, "mp_"); + const std::string bsp_path = (is_mp ? R"(maps\mp\)"s : R"(maps\)"s) + mapname; + + d3dbsp::radiant_load_bsp(bsp_path.c_str()); + } + else + { + game::printf_to_console("Load a .map first!"); + } + } + } + + /** + * @brief run batch to compile bsp + * @param bsp_name plain map name with no extension or pathing + * @param generate_createfx automatically generate createfx files + place into raw instead of bin/T5xRadiant + */ + void d3dbsp::compile_bsp(const std::string& bsp_name, bool generate_createfx) + { + //game::printf_to_console("^1generate_createfx is %s", generate_createfx ? "true" : "false"); + game::printf_to_console("[BSP] Compiling bsp for map: %s ...", bsp_name.c_str()); + + const auto egui = GET_GUI(ggui::entity_dialog); + + const char* base_path = egui->get_value_for_key_from_epairs(game::g_qeglobals->d_project_entity->epairs, "basepath"); + const char* map_path = egui->get_value_for_key_from_epairs(game::g_qeglobals->d_project_entity->epairs, "mapspath"); + + const bool is_mp = utils::starts_with(bsp_name, "mp_"); + const std::string bsp_path = (is_mp ? R"(maps\mp\)"s : R"(maps\)"s) + bsp_name + ".d3dbsp"; + + std::string bps_args; + bps_args += (dvars::bsp_compile_onlyents->current.enabled ? "-onlyents" : "") + " "s; + bps_args += (dvars::bsp_compile_samplescale_enabled->current.enabled ? ("-samplescale " + std::to_string(dvars::bsp_compile_samplescale->current.value)) : "") + " "s; + bps_args += (dvars::bsp_compile_custom_cmd_enabled->current.enabled ? dvars::bsp_compile_custom_cmd->current.string : "") + " "s; + utils::rtrim(bps_args); + + std::string light_args; + light_args += (dvars::bsp_compile_light_fast->current.enabled ? "-fast" : "") + " "s; + light_args += (dvars::bsp_compile_light_extra->current.enabled ? "-extra" : "") + " "s; + light_args += (dvars::bsp_compile_light_modelshadow->current.enabled ? "-modelshadow" : "") + " "s; + light_args += (dvars::bsp_compile_light_dump->current.enabled ? "-dumpoptions" : "") + " "s; + light_args += (dvars::bsp_compile_light_traces_enabled->current.enabled ? ("-traces " + std::to_string(dvars::bsp_compile_light_traces->current.integer)) : "") + " "s; + light_args += (dvars::bsp_compile_light_custom_cmd_enabled->current.enabled ? dvars::bsp_compile_light_custom_cmd->current.string : "") + " "s; + utils::rtrim(light_args); + + std::string args; + + // launch arg + args += R"(")"s + base_path + R"(\bin\T5xRadiant\batch\compile_bsp.bat")"s + " "; + + // bsppath + args += R"(")"s + base_path + (is_mp ? R"(\raw\maps\mp\")"s : R"(\raw\maps\")"s) + " "s; + + // mapsourcepath + args += R"(")"s + map_path + R"(\")"s + " "s; + + // treepath + args += R"(")"s + base_path + R"(\")"s + " "s; + + // mapname + args += bsp_name + " "s; + + // parmBSPOptions + args += (!bps_args.empty() ? R"(")" + bps_args + R"(" )" : "- "); + + // parmLightOptions + args += (!light_args.empty() ? R"(")" + light_args + R"(" )" : "- "); + + // compileBSP + args += (dvars::bsp_compile_bsp->current.enabled ? "1 "s : "0 "s); + + // compileLight + args += (dvars::bsp_compile_light->current.enabled ? "1 "s : "0 "s); + + const auto process = components::process::get(); + process->set_process_type(process::PROC_TYPE_BATCH); + process->set_indicator(process::INDICATOR_TYPE_SPINNER); + process->set_output(true); + process->set_arguments(args); + process->set_post_process_callback([bsp_path, generate_createfx] + { + game::printf_to_console("^2[PROCESS] Post-Process Callback"); + + if (d3dbsp::radiant_load_bsp(bsp_path.c_str(), true)) + { + if (dvars::bsp_gen_reflections_on_compile->current.enabled) + { + //components::renderer::on_cam_paint_post_rendercommands + dvars::set_bool(dvars::r_reflectionprobe_generate, true); + } + else + { + if (dvars::bsp_show_bsp_after_compile->current.enabled) + { + command::execute("toggle_bsp_radiant"); + dvars::set_bool(dvars::r_draw_bsp, dvars::bsp_show_bsp_after_compile->current.enabled); + } + } + } + if (generate_createfx) - { + { game::printf_to_console("Generating CreateFX files ..."); components::effects::generate_createfx(true); - } - }, true ); - - process->create_process(); - } - - /** - * @brief run batch to compile bsp for currently loaded .map - */ - void d3dbsp::compile_current_map() - { - std::string d3dbsp_name = std::string(game::current_map_filepath).substr(std::string(game::current_map_filepath).find_last_of("\\") + 1); - utils::erase_substring(d3dbsp_name, ".map"); - - components::d3dbsp::compile_bsp(d3dbsp_name, dvars::bsp_gen_createfx_on_compile->current.enabled); - } - - - // * - // * - - - float* CG_GetEntityOrigin(int scene_model_index) - { - return game::scene->sceneModel[scene_model_index].placement.base.origin; - } - - void __declspec(naked) CG_GetEntityOrigin_stub() - { - const static uint32_t retn_addr = 0x5274D1; - __asm - { - push edi; // curr index in do-while loop (i < sceneModelCount) - call CG_GetEntityOrigin; - add esp, 4; - jmp retn_addr; - } - } - - - // * - // * - - - void d3dbsp::force_dvars() - { - /*if (const auto& sm_enable = game::Dvar_FindVar("sm_enable"); sm_enable && sm_enable->current.enabled) { - dvars::set_bool(sm_enable, false); - }*/ - - if (const auto& r_floatz = game::Dvar_FindVar("r_floatz"); r_floatz && !r_floatz->current.enabled) { - dvars::set_bool(r_floatz, true); - } - - if (const auto& r_distortion = game::Dvar_FindVar("r_distortion"); r_distortion && !r_distortion->current.enabled) { - dvars::set_bool(r_distortion, true); - } - - if (const auto& r_zFeather = game::Dvar_FindVar("r_zFeather"); r_zFeather && !r_zFeather->current.enabled) { - dvars::set_bool(r_zFeather, true); - } - - if (const auto& r_useLayeredMaterials = game::Dvar_FindVar("r_useLayeredMaterials"); r_useLayeredMaterials && r_useLayeredMaterials->current.enabled) { - dvars::set_bool(r_useLayeredMaterials, false); - } - - if (const auto& r_polygonOffsetBias = game::Dvar_FindVar("r_polygonOffsetBias"); r_polygonOffsetBias) { - dvars::set_float(r_polygonOffsetBias, 0.0f); - } - - if (const auto& r_polygonOffsetScale = game::Dvar_FindVar("r_polygonOffsetScale"); r_polygonOffsetScale) { - dvars::set_float(r_polygonOffsetScale, -0.05f); // or radiant brushes/decals start to flicker - } - - if (const auto& r_zNear = game::Dvar_FindVar("r_zNear"); r_zNear) { - dvars::set_float(r_zNear, 4.0f); - } - } - - void d3dbsp::register_dvars() - { - dvars::bsp_load_entities = dvars::register_bool( - /* name */ "bsp_load_entities", - /* default */ true, - /* flags */ game::dvar_flags::saved, - /* desc */ "enable to load entities when loading a bsp (static_models only)"); - - dvars::bsp_show_bsp_after_compile = dvars::register_bool( - /* name */ "bsp_show_bsp_after_compile", - /* default */ true, - /* flags */ game::dvar_flags::saved, - /* desc */ "automatically turn on bsp view after compiling"); - - dvars::bsp_gen_reflections_on_compile = dvars::register_bool( - /* name */ "bsp_gen_reflections_on_compile", - /* default */ true, - /* flags */ game::dvar_flags::saved, - /* desc */ "automatically build reflections when compiling the bsp"); - - dvars::bsp_gen_createfx_on_compile = dvars::register_bool( - /* name */ "bsp_gen_createfx_on_compile", - /* default */ true, - /* flags */ game::dvar_flags::saved, - /* desc */ "automatically generate CreateFX files when compiling the bsp"); - - dvars::r_draw_bsp = dvars::register_bool( - /* name */ "r_draw_bsp", - /* default */ false, - /* flags */ game::dvar_flags::none, - /* desc */ "enable to render bsp (if loaded)"); - - dvars::r_draw_bsp_overwrite_sunlight = dvars::register_bool( - /* name */ "r_draw_bsp_overwrite_sunlight", - /* default */ false, - /* flags */ game::dvar_flags::none, - /* desc */ "enable to overwrite bsp sunlight with fakesun settings"); - - dvars::r_draw_bsp_overwrite_sundir = dvars::register_bool( - /* name */ "r_draw_bsp_overwrite_sundir", - /* default */ false, - /* flags */ game::dvar_flags::none, - /* desc */ "enable to overwrite bsp sundir with fakesun settings"); - - dvars::r_draw_bsp_overwrite_sunspecular = dvars::register_bool( - /* name */ "r_draw_bsp_overwrite_sunspecular", - /* default */ false, - /* flags */ game::dvar_flags::none, - /* desc */ "enable to overwrite bsp sunspecular with fakesun settings"); - } - - d3dbsp::d3dbsp() - { - // # - // * NOTES - // * DONE: load "dynamic" entities like exploding cars (scene.sceneModelCount :: R_AddXModelSurfacesCamera :: R_AddAllSceneEntSurfacesCamera) - // * TODO: ^ CG_ProcessEntity :: CG_ScriptMover :: R_AddDObjToScene - // * ^ G_InitGame :: G_SpawnEntitiesFromString .... G_ModelIndex -> XModelPrecache_LoadObj - - // * TODO: draw sun / load sun dvars from sun file - - // # - // R_LoadWorldInternal patches - - // re-implement a LUMP_UNLAYERED_TRIANGLES check (r_useLayeredMaterials) - utils::hook::detour(0x4161B0, d3dbsp::Com_GetBspLumpBool, HK_JUMP); - - // re-implement Com_GetBspVersion - utils::hook::detour(0x416150, d3dbsp::Com_GetBspVersion, HK_JUMP); - - // re-implement Com_GetBspLump - utils::hook::detour(0x416180, d3dbsp::Com_GetBspLump, HK_JUMP); - - // re-implement CM_GetPlanes - utils::hook::detour(0x4161E0, d3dbsp::CM_GetPlanes, HK_JUMP); - - // re-implement CM_GetPlaneCount - utils::hook::detour(0x4161F0, d3dbsp::CM_GetPlaneCount, HK_JUMP); - - // re-implement CG_GetEntityOrigin in R_ShowCull - utils::hook(0x5274CC, CG_GetEntityOrigin_stub, HOOK_JUMP).install()->quick(); - - - // # - // dirty hacks - - utils::hook::nop(0x5525A2, 5); // Outdoor_ComputeTexels call - utils::hook::nop(0x5101A4, 5); // memset of s_world in R_LoadWorldInternal - - utils::hook::nop(0x41625A, 5); // CM_BoxSightTrace Assert - utils::hook::nop(0x56C8DC, 5); // bspSurf->material->info.name) = %s", "(!lightmapSecondaryFlag) Assert - - utils::hook::nop(0x41637A, 5); // Ragdoll_HandleBody Assert - - - - // Material_Add :: set rgp.needSortMaterials = 1 to 0 (do not re-sort materials when loading new ones; fixes bsp texture issues) - utils::hook::set(0x510CF1 + 6, 0x0); - - // RENDERTARGET_SCENE to FRAMEBUFFER in R_DrawPointLitSurfsCallback - utils::hook::set(0x55BC8F + 1, 0x1); - - // R_LoadSun (not needed and prints irrelevant info) - utils::hook::nop(0x51047D, 5); - - // R_LoadSunThroughDvars :: no longer called because above nop ^ - utils::hook::nop(0x52DAFA, 5); // Com_LoadDvarsFromBuffer (not implemented) - - - - // # - // no bsp culling - - // R_AddCellSceneEntSurfacesInFrustumCmd :: active ents like destructible cars / players (disable all culling) - //utils::hook::nop(0x56998B, 3); - - // R_AddWorldSurfacesPortalWalk :: less culling :: 0x7C -> 0xEB (jl -> jmp) - //utils::hook::set(0x527370, 0xEB); - - // R_AddAabbTreeSurfacesInFrustum_r :: less culling :: 0x74 -> 0xEB (je to jmp) - //utils::hook::set(0x555C4C, 0xEB); - - - // # - // -------------------------- - - - // reload the currently loaded bsp - // tries to automatically load a bsp based of the .map name if no bsp is loaded - command::register_command_with_hotkey("bsp_reload"s, [](auto) - { - components::d3dbsp::reload_bsp(); - }); - - // toggle bsp rendering on/off - command::register_command_with_hotkey("toggle_bsp"s, [this](auto) - { - dvars::set_bool(dvars::r_draw_bsp, !dvars::r_draw_bsp->current.enabled); - }); - - // toggle between bsp and radiant rendering - command::register_command_with_hotkey("toggle_bsp_radiant"s, [this](auto) - { - if (d3dbsp::Com_IsBspLoaded()) - { - const bool tstate = gameview::p_this->get_all_geo_state() || gameview::p_this->get_all_ents_state() || gameview::p_this->get_all_triggers_state() || gameview::p_this->get_all_others_state(); - - const bool gameview_was_enabled = dvars::radiant_gameview->current.enabled; - - dvars::set_bool(dvars::r_draw_bsp, !tstate); - command::execute("toggle_filter_all"); - - if (gameview_was_enabled) - { - components::gameview::p_this->set_state(gameview_was_enabled); - } - } - }); - - command::register_command_with_hotkey("bsp_compile"s, [this](auto) - { - components::d3dbsp::compile_current_map(); - }); - } - - d3dbsp::~d3dbsp() - { - d3dbsp::shutdown_bsp(); - } -} + } + }, true ); + + process->create_process(); + } + + /** + * @brief run batch to compile bsp for currently loaded .map + */ + void d3dbsp::compile_current_map() + { + std::string d3dbsp_name = std::string(game::current_map_filepath).substr(std::string(game::current_map_filepath).find_last_of("\\") + 1); + utils::erase_substring(d3dbsp_name, ".map"); + + components::d3dbsp::compile_bsp(d3dbsp_name, dvars::bsp_gen_createfx_on_compile->current.enabled); + } + + + // * + // * + + + float* CG_GetEntityOrigin(int scene_model_index) + { + return game::scene->sceneModel[scene_model_index].placement.base.origin; + } + + void __declspec(naked) CG_GetEntityOrigin_stub() + { + const static uint32_t retn_addr = 0x5274D1; + __asm + { + push edi; // curr index in do-while loop (i < sceneModelCount) + call CG_GetEntityOrigin; + add esp, 4; + jmp retn_addr; + } + } + + + // * + // * + + + void d3dbsp::force_dvars() + { + /*if (const auto& sm_enable = game::Dvar_FindVar("sm_enable"); sm_enable && sm_enable->current.enabled) { + dvars::set_bool(sm_enable, false); + }*/ + + if (const auto& r_floatz = game::Dvar_FindVar("r_floatz"); r_floatz && !r_floatz->current.enabled) { + dvars::set_bool(r_floatz, true); + } + + if (const auto& r_distortion = game::Dvar_FindVar("r_distortion"); r_distortion && !r_distortion->current.enabled) { + dvars::set_bool(r_distortion, true); + } + + if (const auto& r_zFeather = game::Dvar_FindVar("r_zFeather"); r_zFeather && !r_zFeather->current.enabled) { + dvars::set_bool(r_zFeather, true); + } + + if (const auto& r_useLayeredMaterials = game::Dvar_FindVar("r_useLayeredMaterials"); r_useLayeredMaterials && r_useLayeredMaterials->current.enabled) { + dvars::set_bool(r_useLayeredMaterials, false); + } + + if (const auto& r_polygonOffsetBias = game::Dvar_FindVar("r_polygonOffsetBias"); r_polygonOffsetBias) { + dvars::set_float(r_polygonOffsetBias, 0.0f); + } + + if (const auto& r_polygonOffsetScale = game::Dvar_FindVar("r_polygonOffsetScale"); r_polygonOffsetScale) { + dvars::set_float(r_polygonOffsetScale, -0.05f); // or radiant brushes/decals start to flicker + } + + if (const auto& r_zNear = game::Dvar_FindVar("r_zNear"); r_zNear) { + dvars::set_float(r_zNear, 4.0f); + } + } + + void d3dbsp::register_dvars() + { + dvars::bsp_load_entities = dvars::register_bool( + /* name */ "bsp_load_entities", + /* default */ true, + /* flags */ game::dvar_flags::saved, + /* desc */ "enable to load entities when loading a bsp (static_models only)"); + + dvars::bsp_show_bsp_after_compile = dvars::register_bool( + /* name */ "bsp_show_bsp_after_compile", + /* default */ true, + /* flags */ game::dvar_flags::saved, + /* desc */ "automatically turn on bsp view after compiling"); + + dvars::bsp_gen_reflections_on_compile = dvars::register_bool( + /* name */ "bsp_gen_reflections_on_compile", + /* default */ true, + /* flags */ game::dvar_flags::saved, + /* desc */ "automatically build reflections when compiling the bsp"); + + dvars::bsp_gen_createfx_on_compile = dvars::register_bool( + /* name */ "bsp_gen_createfx_on_compile", + /* default */ true, + /* flags */ game::dvar_flags::saved, + /* desc */ "automatically generate CreateFX files when compiling the bsp"); + + dvars::r_draw_bsp = dvars::register_bool( + /* name */ "r_draw_bsp", + /* default */ false, + /* flags */ game::dvar_flags::none, + /* desc */ "enable to render bsp (if loaded)"); + + dvars::r_draw_bsp_overwrite_sunlight = dvars::register_bool( + /* name */ "r_draw_bsp_overwrite_sunlight", + /* default */ false, + /* flags */ game::dvar_flags::none, + /* desc */ "enable to overwrite bsp sunlight with fakesun settings"); + + dvars::r_draw_bsp_overwrite_sundir = dvars::register_bool( + /* name */ "r_draw_bsp_overwrite_sundir", + /* default */ false, + /* flags */ game::dvar_flags::none, + /* desc */ "enable to overwrite bsp sundir with fakesun settings"); + + dvars::r_draw_bsp_overwrite_sunspecular = dvars::register_bool( + /* name */ "r_draw_bsp_overwrite_sunspecular", + /* default */ false, + /* flags */ game::dvar_flags::none, + /* desc */ "enable to overwrite bsp sunspecular with fakesun settings"); + } + + d3dbsp::d3dbsp() + { + // # + // * NOTES + // * DONE: load "dynamic" entities like exploding cars (scene.sceneModelCount :: R_AddXModelSurfacesCamera :: R_AddAllSceneEntSurfacesCamera) + // * TODO: ^ CG_ProcessEntity :: CG_ScriptMover :: R_AddDObjToScene + // * ^ G_InitGame :: G_SpawnEntitiesFromString .... G_ModelIndex -> XModelPrecache_LoadObj + + // * TODO: draw sun / load sun dvars from sun file + + // # + // R_LoadWorldInternal patches + + // re-implement a LUMP_UNLAYERED_TRIANGLES check (r_useLayeredMaterials) + utils::hook::detour(0x4161B0, d3dbsp::Com_GetBspLumpBool, HK_JUMP); + + // re-implement Com_GetBspVersion + utils::hook::detour(0x416150, d3dbsp::Com_GetBspVersion, HK_JUMP); + + // re-implement Com_GetBspLump + utils::hook::detour(0x416180, d3dbsp::Com_GetBspLump, HK_JUMP); + + // re-implement CM_GetPlanes + utils::hook::detour(0x4161E0, d3dbsp::CM_GetPlanes, HK_JUMP); + + // re-implement CM_GetPlaneCount + utils::hook::detour(0x4161F0, d3dbsp::CM_GetPlaneCount, HK_JUMP); + + // re-implement CG_GetEntityOrigin in R_ShowCull + utils::hook(0x5274CC, CG_GetEntityOrigin_stub, HOOK_JUMP).install()->quick(); + + + // # + // dirty hacks + + utils::hook::nop(0x5525A2, 5); // Outdoor_ComputeTexels call + utils::hook::nop(0x5101A4, 5); // memset of s_world in R_LoadWorldInternal + + utils::hook::nop(0x41625A, 5); // CM_BoxSightTrace Assert + utils::hook::nop(0x56C8DC, 5); // bspSurf->material->info.name) = %s", "(!lightmapSecondaryFlag) Assert + + utils::hook::nop(0x41637A, 5); // Ragdoll_HandleBody Assert + + + + // Material_Add :: set rgp.needSortMaterials = 1 to 0 (do not re-sort materials when loading new ones; fixes bsp texture issues) + utils::hook::set(0x510CF1 + 6, 0x0); + + // RENDERTARGET_SCENE to FRAMEBUFFER in R_DrawPointLitSurfsCallback + utils::hook::set(0x55BC8F + 1, 0x1); + + // R_LoadSun (not needed and prints irrelevant info) + utils::hook::nop(0x51047D, 5); + + // R_LoadSunThroughDvars :: no longer called because above nop ^ + utils::hook::nop(0x52DAFA, 5); // Com_LoadDvarsFromBuffer (not implemented) + + + + // # + // no bsp culling + + // R_AddCellSceneEntSurfacesInFrustumCmd :: active ents like destructible cars / players (disable all culling) + //utils::hook::nop(0x56998B, 3); + + // R_AddWorldSurfacesPortalWalk :: less culling :: 0x7C -> 0xEB (jl -> jmp) + //utils::hook::set(0x527370, 0xEB); + + // R_AddAabbTreeSurfacesInFrustum_r :: less culling :: 0x74 -> 0xEB (je to jmp) + //utils::hook::set(0x555C4C, 0xEB); + + + // # + // -------------------------- + + + // reload the currently loaded bsp + // tries to automatically load a bsp based of the .map name if no bsp is loaded + command::register_command_with_hotkey("bsp_reload"s, [](auto) + { + components::d3dbsp::reload_bsp(); + }); + + // toggle bsp rendering on/off + command::register_command_with_hotkey("toggle_bsp"s, [this](auto) + { + dvars::set_bool(dvars::r_draw_bsp, !dvars::r_draw_bsp->current.enabled); + }); + + // toggle between bsp and radiant rendering + command::register_command_with_hotkey("toggle_bsp_radiant"s, [this](auto) + { + if (d3dbsp::Com_IsBspLoaded()) + { + const bool tstate = gameview::p_this->get_all_geo_state() || gameview::p_this->get_all_ents_state() || gameview::p_this->get_all_triggers_state() || gameview::p_this->get_all_others_state(); + + const bool gameview_was_enabled = dvars::radiant_gameview->current.enabled; + + dvars::set_bool(dvars::r_draw_bsp, !tstate); + command::execute("toggle_filter_all"); + + if (gameview_was_enabled) + { + components::gameview::p_this->set_state(gameview_was_enabled); + } + } + }); + + command::register_command_with_hotkey("bsp_compile"s, [this](auto) + { + components::d3dbsp::compile_current_map(); + }); + } + + d3dbsp::~d3dbsp() + { + d3dbsp::shutdown_bsp(); + } +} diff --git a/src/components/modules/effects.cpp b/src/components/modules/effects.cpp index 6300cba..3ef934e 100644 --- a/src/components/modules/effects.cpp +++ b/src/components/modules/effects.cpp @@ -726,7 +726,7 @@ namespace components else { filepath = dvars::fs_homepath->current.string; - filepath += "\\IW3xRadiant\\createfx\\"s; + filepath += "\\T5xRadiant\\createfx\\"s; } diff --git a/src/components/modules/generate_previews.cpp b/src/components/modules/generate_previews.cpp index 171a7cc..8415714 100644 --- a/src/components/modules/generate_previews.cpp +++ b/src/components/modules/generate_previews.cpp @@ -114,7 +114,7 @@ namespace components // take screenshot std::string file_path = game::Dvar_FindVar("fs_homepath")->current.string; - file_path += R"(\IW3xRadiant\prefab_thumbs\)"; + file_path += R"(\T5xRadiant\prefab_thumbs\)"; auto thumbnail_str = GET_GUI(ggui::prefab_preview_dialog)->get_thumbnail_string(rel_path.has_parent_path() ? rel_path.parent_path() : "", rel_path.filename().string()); thumbnail_str += ".jpg"; diff --git a/src/components/modules/gui.cpp b/src/components/modules/gui.cpp index 675cd10..a7095b4 100644 --- a/src/components/modules/gui.cpp +++ b/src/components/modules/gui.cpp @@ -60,7 +60,7 @@ namespace components io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; // Enable Docking //io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable; // Enable Multi-Viewport / Platform Windows io.ConfigWindowsResizeFromEdges = true; - io.IniFilename = "IW3xRadiant\\imgui.ini"; + io.IniFilename = "T5xRadiant\\imgui.ini"; // implementation ImGui_ImplWin32_Init(cmainframe::activewnd->m_pZWnd->GetWindow()); @@ -478,7 +478,7 @@ namespace components { ImGuiToast toast(ImGuiToastType_Info, 2500); toast.set_title("Snapshot created"); - toast.set_content(R"(D:\COD4Modtools\map_source\snapshots\mp_bsptest.map.5)"); + toast.set_content(R"(D:\BO1Modtools\map_source\snapshots\mp_bsptest.map.5)"); ImGui::InsertNotification(toast); } diff --git a/src/components/modules/main_module.cpp b/src/components/modules/main_module.cpp index 3d6dbd4..ef92529 100644 --- a/src/components/modules/main_module.cpp +++ b/src/components/modules/main_module.cpp @@ -296,7 +296,7 @@ BOOL init_threads() // discord rich presence CreateThread(nullptr, 0, discord_rpc, nullptr, 0, nullptr); - // check for iw3xradiant updates + // check for t5xradiant updates CreateThread(nullptr, 0, update_check, nullptr, 0, nullptr); game::glob::command_thread_running = false; @@ -316,7 +316,7 @@ BOOL init_threads() freopen_s(&file, "CONOUT$", "w", stdout); freopen_s(&file, "CONOUT$", "w", stderr); - SetConsoleTitleA("IW3xRadiant Console"); + SetConsoleTitleA("T5xRadiant Console"); } return TRUE; @@ -325,12 +325,12 @@ BOOL init_threads() namespace components { - void add_iw3xradiant_searchpath() + void add_t5xradiant_searchpath() { if(const auto fs_basepath = game::Dvar_FindVar("fs_basepath"); fs_basepath) { - game::FS_ScanForDir("bin/IW3xRadiant", fs_basepath->current.string, false); + game::FS_ScanForDir("bin/T5xRadiant", fs_basepath->current.string, false); } } @@ -344,7 +344,7 @@ namespace components call Com_Printf_Func; pushad; - call add_iw3xradiant_searchpath; + call add_t5xradiant_searchpath; popad; jmp retn_pt; @@ -456,7 +456,7 @@ namespace components // * // * - // add iw3xradiant search path (imgui images) + // add t5xradiant search path (imgui images) utils::hook(0x4A29A7, fs_scan_base_directory_stub, HOOK_JUMP).install()->quick(); // set max undo memory diff --git a/src/components/modules/mesh_painter.cpp b/src/components/modules/mesh_painter.cpp index 92a5f9e..ab9c620 100644 --- a/src/components/modules/mesh_painter.cpp +++ b/src/components/modules/mesh_painter.cpp @@ -20,7 +20,7 @@ namespace components dvars::fs_homepath) { std::string dir_path = dvars::fs_homepath->current.string; - dir_path += R"(\IW3xRadiant\mesh_painter)"; + dir_path += R"(\T5xRadiant\mesh_painter)"; const auto file = GET_GUI(ggui::file_dialog); file->set_default_path(dir_path); @@ -38,7 +38,7 @@ namespace components if (ofile.is_open()) { - ofile << "// mesh painter list generated by iw3xo-radiant" << std::endl; + ofile << "// mesh painter list generated by t5xo-radiant" << std::endl; ofile << "// # radius, paint threshold, paint density" << std::endl; ofile << "// name, enabled, paint_weight, random_rotation, align_to_ground, z_offset, random_size, size_range[0], size_range[1]" << std::endl; @@ -55,7 +55,7 @@ namespace components } else { - game::printf_to_console("[ERR] [Mesh-Painter] Failed to find open '%s' in 'bin/IW3xRadiant/mesh_painter'", filename.c_str()); + game::printf_to_console("[ERR] [Mesh-Painter] Failed to find open '%s' in 'bin/T5xRadiant/mesh_painter'", filename.c_str()); } }); @@ -69,7 +69,7 @@ namespace components dvars::fs_homepath) { std::string dir_path = dvars::fs_homepath->current.string; - dir_path += R"(\IW3xRadiant\mesh_painter)"; + dir_path += R"(\T5xRadiant\mesh_painter)"; const auto file = GET_GUI(ggui::file_dialog); file->set_default_path(dir_path); @@ -97,7 +97,7 @@ namespace components // read line by line while (std::getline(ifile, input)) { - if (!first_line && input.find("// mesh painter list generated by iw3xo-radiant") == std::string::npos) + if (!first_line && input.find("// mesh painter list generated by t5xo-radiant") == std::string::npos) { // invalid file break; @@ -162,7 +162,7 @@ namespace components } else { - game::printf_to_console("[ERR] [Mesh-Painter] Failed to find open '%s' in 'bin/IW3xRadiant/mesh_painter'", filename.c_str()); + game::printf_to_console("[ERR] [Mesh-Painter] Failed to find open '%s' in 'bin/T5xRadiant/mesh_painter'", filename.c_str()); } }); diff --git a/src/components/modules/patches.cpp b/src/components/modules/patches.cpp index 2d12d79..fa8457a 100644 --- a/src/components/modules/patches.cpp +++ b/src/components/modules/patches.cpp @@ -94,7 +94,7 @@ namespace components void DECLSPEC_NORETURN on_invalid_hwnd_assert() { - game::Com_Error("Failed to initialize renderer. This might indicate that you have not installed the cod4 modtools or are missing parts of it.\n"); + game::Com_Error("Failed to initialize renderer. This might indicate that you have not installed the bo1 modtools or are missing parts of it.\n"); exit(0); } diff --git a/src/components/modules/reflectionprobes.cpp b/src/components/modules/reflectionprobes.cpp index 5e41bd0..4b1d5ed 100644 --- a/src/components/modules/reflectionprobes.cpp +++ b/src/components/modules/reflectionprobes.cpp @@ -32,7 +32,7 @@ namespace components dvars::fs_homepath) { std::string filePath = dvars::fs_homepath->current.string; - filePath += R"(\IW3xRadiant\reflection_probes\)"; + filePath += R"(\T5xRadiant\reflection_probes\)"; std::filesystem::create_directories(filePath); filePath += filename + ".tga"s; @@ -808,7 +808,7 @@ namespace components /* name */ "r_reflectionprobe_export_tga", /* default */ false, /* flags */ game::dvar_flags::none, - /* desc */ "export all reflection probes as tga files when building reflections (bin/IW3xRadiant/reflection_probes)"); + /* desc */ "export all reflection probes as tga files when building reflections (bin/T5xRadiant/reflection_probes)"); } reflectionprobes::reflectionprobes() diff --git a/src/components/modules/renderer.cpp b/src/components/modules/renderer.cpp index 8ad78fd..6e00524 100644 --- a/src/components/modules/renderer.cpp +++ b/src/components/modules/renderer.cpp @@ -451,9 +451,9 @@ namespace components sprintf_s(shader_path, 260u, "%s/raw/shader_bin/%s_%8.8x", game::Dvar_FindVar("fs_basepath")->current.string, prefix_str, shader_hash); if (!r_load_shader_programm(&shader_len, &chachedShader, shader_path)) { - // look for addon shaders in bin/IW3xRadiant/shader_bin + // look for addon shaders in bin/T5xRadiant/shader_bin memset(&shader_path, 0, sizeof(shader_path)); - sprintf_s(shader_path, 260u, "%s/bin/IW3xRadiant/shader_bin/%s_%8.8x", game::Dvar_FindVar("fs_basepath")->current.string, prefix_str, shader_hash); + sprintf_s(shader_path, 260u, "%s/bin/T5xRadiant/shader_bin/%s_%8.8x", game::Dvar_FindVar("fs_basepath")->current.string, prefix_str, shader_hash); if (!r_load_shader_programm(&shader_len, &chachedShader, shader_path)) { @@ -1202,7 +1202,7 @@ namespace components } } - // return handle for loaded technique, loads new technique from "raw/techniques" or "bin/IW3xRadiant/techniques" otherwise + // return handle for loaded technique, loads new technique from "raw/techniques" or "bin/T5xRadiant/techniques" otherwise game::MaterialTechnique* Material_RegisterTechnique(const char* name /*eax*/, int is_renderer_in_use /*edi*/) { const static uint32_t func_addr = 0x519790; @@ -2032,7 +2032,7 @@ namespace components if (dvars::fs_homepath) { std::string filePath = dvars::fs_homepath->current.string; - filePath += "\\IW3xRadiant\\LOG_rendercommands.txt"s; + filePath += "\\T5xRadiant\\LOG_rendercommands.txt"s; log_file.open(filePath.c_str()); if (!log_file.is_open()) diff --git a/src/components/modules/time_wasted.cpp b/src/components/modules/time_wasted.cpp index 27dac07..765fd2a 100644 --- a/src/components/modules/time_wasted.cpp +++ b/src/components/modules/time_wasted.cpp @@ -22,7 +22,7 @@ namespace components void time_wasted::write_entries_to_file() { std::ofstream file; - if (utils::fs::write_file_homepath("IW3xRadiant", "time_wasted.ini", false, file)) + if (utils::fs::write_file_homepath("T5xRadiant", "time_wasted.ini", false, file)) { for (const auto& entry : m_entries) { @@ -38,7 +38,7 @@ namespace components m_entries.clear(); std::ifstream file; - if (utils::fs::open_file_homepath("IW3xRadiant", "time_wasted.ini", false, file)) + if (utils::fs::open_file_homepath("T5xRadiant", "time_wasted.ini", false, file)) { std::string input; std::vector args; diff --git a/src/ggui/effects_editor_gui.cpp b/src/ggui/effects_editor_gui.cpp index e8f9d31..7ed991e 100644 --- a/src/ggui/effects_editor_gui.cpp +++ b/src/ggui/effects_editor_gui.cpp @@ -1648,7 +1648,7 @@ namespace ggui if (elem->elemType == fx_system::FX_ELEM_TYPE_MODEL) { MOD_CHECK(ImGui::Checkbox_FxElemFlag("Enable simulation (PhysX / ODE)", elem, fx_system::FX_ELEM_USE_MODEL_PHYSICS, &physx_enabled)); - TT("This enables PhysX (in radiant) and the stock physics engine in cod4"); + TT("This enables PhysX (in radiant) and the stock physics engine in bo1"); } if (physx_enabled) diff --git a/src/ggui/hotkeys.cpp b/src/ggui/hotkeys.cpp index 361a8df..4f0f6e2 100644 --- a/src/ggui/hotkeys.cpp +++ b/src/ggui/hotkeys.cpp @@ -22,7 +22,7 @@ namespace ggui if (const auto& fs_homepath = game::Dvar_FindVar("fs_homepath"); fs_homepath) { - const char* apply_hint = utils::va("Could not find file 'hotkeys.ini' in\n'%s/IW3xRadiant'.", fs_homepath->current.string); + const char* apply_hint = utils::va("Could not find file 'hotkeys.ini' in\n'%s/T5xRadiant'.", fs_homepath->current.string); ImGui::SetCursorPosX((ImGui::GetWindowWidth() - ImGui::CalcTextSize(apply_hint).x) * 0.5f); ImGui::SetCursorPosY(ImGui::GetCursorPosY() + ImGui::GetWindowHeight() * 0.5f - ImGui::CalcTextSize(apply_hint).y); ImGui::TextUnformatted(apply_hint); @@ -300,7 +300,7 @@ namespace ggui cmd_hotkeys.clear(); std::ifstream ini; - if (utils::fs::open_file_homepath("IW3xRadiant", file, false, ini)) + if (utils::fs::open_file_homepath("T5xRadiant", file, false, ini)) { std::string input; std::vector args; @@ -368,7 +368,7 @@ namespace ggui } game::printf_to_console("[ERR][Hotkeys] Failed to find 'hotkeys.ini'\n"); - game::printf_to_console("[ERR] ^ will be created upon closing radiant with default bindings. Please consider using the ini file that came with iw3xo-radiant.\n"); + game::printf_to_console("[ERR] ^ will be created upon closing radiant with default bindings. Please consider using the ini file that came with t5xo-radiant.\n"); return false; } @@ -754,7 +754,7 @@ namespace ggui } std::ofstream ini; - if (utils::fs::write_file_homepath("IW3xRadiant", "hotkeys.ini", false, ini)) + if (utils::fs::write_file_homepath("T5xRadiant", "hotkeys.ini", false, ini)) { ini << "[Commands]" << std::endl; diff --git a/src/ggui/menubar.cpp b/src/ggui/menubar.cpp index 3745b6f..cbaedd6 100644 --- a/src/ggui/menubar.cpp +++ b/src/ggui/menubar.cpp @@ -174,7 +174,7 @@ namespace ggui { components::effects::generate_createfx(); - } TT("Generate createfx files for current map.\n (bin\\IW3xRadiant\\createfx)"); + } TT("Generate createfx files for current map.\n (bin\\T5xRadiant\\createfx)"); if (ImGui::MenuItem("Pointfile")) { mainframe_cdeclcall(void, 0x423B20); //cmainframe::OnPointfileOpen diff --git a/src/ggui/textures.cpp b/src/ggui/textures.cpp index 163ce44..459e662 100644 --- a/src/ggui/textures.cpp +++ b/src/ggui/textures.cpp @@ -626,7 +626,7 @@ namespace ggui std::ifstream file; std::string dir_path = dvars::fs_homepath->current.string; - dir_path += R"(\IW3xRadiant\texture_favourites\)"; + dir_path += R"(\T5xRadiant\texture_favourites\)"; std::filesystem::create_directories(dir_path); @@ -640,7 +640,7 @@ namespace ggui if (ofile.is_open()) { - ofile << "// texture favourites generated by iw3xo-radiant" << std::endl; + ofile << "// texture favourites generated by t5xo-radiant" << std::endl; ofile << new_list_name << std::endl; ofile.close(); diff --git a/src/ggui/toolbar.cpp b/src/ggui/toolbar.cpp index d70c99b..a50cbb4 100644 --- a/src/ggui/toolbar.cpp +++ b/src/ggui/toolbar.cpp @@ -1144,7 +1144,7 @@ namespace ggui std::string ini_path = fs_homepath->current.string; - ini_path += "\\IW3xRadiant\\" + TB_INI_FILENAME; + ini_path += "\\T5xRadiant\\" + TB_INI_FILENAME; std::ifstream ini; ini.open(ini_path.c_str()); @@ -1260,7 +1260,7 @@ namespace ggui { std::ofstream ini; std::string ini_path = fs_homepath->current.string; - ini_path += "\\IW3xRadiant\\" + TB_INI_FILENAME; + ini_path += "\\T5xRadiant\\" + TB_INI_FILENAME; ini.open(ini_path.c_str()); if (!ini.is_open()) diff --git a/src/utils/filesystem.cpp b/src/utils/filesystem.cpp index b4249cd..340002a 100644 --- a/src/utils/filesystem.cpp +++ b/src/utils/filesystem.cpp @@ -71,7 +71,7 @@ namespace utils::fs } /** - * @return cod4 root path + * @return bo1 root path */ std::string get_basepath() { From 71504e407aba816db71e9492f59c1112fe4b4c16 Mon Sep 17 00:00:00 2001 From: Faber <103538724+FaberTheCatboy@users.noreply.github.com> Date: Fri, 17 Mar 2023 11:14:35 -0700 Subject: [PATCH 5/5] Update README.md --- README.md | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index d8e09f6..2610024 100644 --- a/README.md +++ b/README.md @@ -62,14 +62,14 @@ If you want to buy me a coffee: ___
-### New features not found within the original cod4 radiant: +### New features not found within the original bo1 radiant: + completely revamped user interface with docking, tabs, saved layouts and more (Dear ImGui) + [play](https://xoxor4d.github.io/tutorials/iw3xradiant-using-effects/) && [edit / create](https://xoxor4d.github.io/tutorials/iw3xradiant-effects-editor/) && [export effects as CreateFX](https://xoxor4d.github.io/tutorials/iw3xradiant-createfx/) files right from within radiant (__makes effectsEd completely obsolete__) + Nvidia PhysX integration for [dynamic placement of prefabs](https://xoxor4d.github.io/tutorials/iw3xradiant-physx-prefabs) or [physics-enabled effects](https://xoxor4d.github.io/tutorials/iw3xradiant-physx-effects) (can be turned into misc_models) -+ Nvidia PhysX enabled character movement with cod4 movement mechanics (bouncing) [character movement](https://xoxor4d.github.io/tutorials/iw3xradiant-physx-movement) ++ Nvidia PhysX enabled character movement with bo1 movement mechanics (bouncing) [character movement](https://xoxor4d.github.io/tutorials/iw3xradiant-physx-movement) + [d3dbsp loading](https://xoxor4d.github.io/tutorials/iw3xradiant-d3dbsp) and bsp/light compilation from within radiant + [automatically generate reflections](https://xoxor4d.github.io/tutorials/iw3xradiant-d3dbsp-reflections) within radiant when compiling the maps bsp -+ [live link](https://xoxor4d.github.io/tutorials/iw3xradiant-livelink) (sync. brushes (with collision), camera and worldspawn settings between cod4 and radiant) ++ [live link](https://xoxor4d.github.io/tutorials/iw3xradiant-livelink) (sync. brushes (with collision), camera and worldspawn settings between bo1 and radiant) + [mesh painting](https://xoxor4d.github.io/tutorials/iw3xradiant-mesh-painting) (xmodels/prefabs) with per object settings, random size, angles, weight etc. + 3D guizmo to precisely manipulate entities and brushes from the camera window (ImGuizmo) + a prefab browser with the ability to generate thumbnails + drag and drop prefabs into the scene @@ -112,14 +112,14 @@ ___
-1. Install the Bo1 Modtools -2. Download the latest [release](https://github.com/VenomModding/T5xRadiant/releases) -3. Copy the contents into your cod4 root directory +1. Install the bo1 Modtools +2. Download the latest [release](https://github.com/xoxor4d/iw3xo-radiant/releases) +3. Copy the contents into your bo1 root directory 4. Start `bin/T5xRadiant.exe` - [NIGHTLY]    install latest release, download nightly, unpack and replace `t5xr.dll` within the `bin` folder -                 -> check for additional assets in the __#nightly-builds__ channel (📍) on the [Venom Modding discord](https://discord.gg/QuNcjXbsqY) -- [OPTIONAL]  __bo3-tool-textures.zip__ (unpack and place `.iwi's` into `bin\T5xRadiant\images`) +                 -> check for additional assets in the __#nightly-builds__ channel (📍) on the [iw3xo discord](https://discord.gg/t5jRGbj) +- [OPTIONAL]  __bo3-tool-textures.zip__ (unpack and place `.iwi's` into `bin\IW3xRadiant\images`)
@@ -133,7 +133,7 @@ ___ 2. Copy everything within the assets folder into your bo1-root folder 3. Use __update_submodules.bat__ to update submodules 4. Use __generate-buildfiles.bat__ to build project files with premake -5. Load the solution `(build/t5x-radiant.sln)` and open the iw3r project-settings to setup paths: +5. Load the solution `(build/iw3xo-radiant.sln)` and open the iw3r project-settings to setup paths: > - General       output directory path -> `path-to-bo1-root\bin\` > - Debugging   command -> `path-to-bo1-root\bin\T5xRadiant.exe` > - Debugging   working directory -> `path-to-bo1-root\bin\` @@ -145,18 +145,18 @@ ___ ### How to build the project using VSCode 1. Install C++ Build tools (msbuild) 2. Add msbuild folder to the "PATH" environment variable: -> `%ProgramFiles(x86)%\Microsoft Visual Studio\2019\Community\MSBuild\Current\Bin` +> `%ProgramFiles(x86)%\Microsoft Visual Studio\2022\Community\MSBuild\Current\Bin` 3. Add `BO1_ROOT` environment variable with path to your bo1 directory > `"BO1_ROOT" "D:\BO1-Modtools"` 4. Clone the repo (zip does not include deps!) 5. Copy everything within the assets folder into your bo1-root folder 6. Drag and drop all files from `.vscode/tracked\` into `.vscode\` -7. Open __t5x-radiant.code-workspace__ +7. Open __t5xo-radiant.code-workspace__ 8. Run task: `update_submodules` or open __update_submodules.bat__ 9. Run task: `generate-buildfiles` or open __generate-buildfiles.bat__ -Use provided build-tasks with the option to copy `T5xr.dll` and `T5xr.pdb` to `%BO1_ROOT%/bin` -__Run->Start Debugging__ will build and copy a debug build to to `%BO1_ROOT%/bin` and launch IW3xRadiant. +Use provided build-tasks with the option to copy `t5xr.dll` and `t5xr.pdb` to `%BO1_ROOT%/bin` +__Run->Start Debugging__ will build and copy a debug build to to `%BO1_ROOT%/bin` and launch T5xRadiant.
@@ -164,8 +164,8 @@ ___
-### Optional: -https://github.com/VenomModding/t5xo-dev +### Optional: + https://github.com/xoxor4d/iw3xo-dev ### Project Page: @@ -211,7 +211,7 @@ ___ ### Effect Browser and Playback ![image](readme/feat_effect_browser.gif) -### In-Editor cod4 based movement with bouncing :> +### In-Editor bo1 based movement with bouncing :> ![image](readme/feat_movement.gif)