diff --git a/premake5.lua b/premake5.lua index 8a68253c..6a6b7642 100644 --- a/premake5.lua +++ b/premake5.lua @@ -5,7 +5,7 @@ solution "iw4x" project "iw4x" kind "SharedLib" language "C++" - files { "src/**.hpp", "src/**.cpp" } + files { "./src/**.hpp", "./src/**.cpp" } --toolset "v120" -- Compatibility for users configuration "Normal" diff --git a/src/Components/Modules/Window.cpp b/src/Components/Modules/Window.cpp index c50fc2fd..e39d020f 100644 --- a/src/Components/Modules/Window.cpp +++ b/src/Components/Modules/Window.cpp @@ -2,7 +2,9 @@ namespace Components { + HWND Window::MainWindow; Dvar::Var Window::NoBorder; + BOOL Window::CursorVisible; void __declspec(naked) Window::StyleHookStub() { @@ -18,10 +20,74 @@ namespace Components __asm retn } + void Window::DrawCursorStub() + { + Window::CursorVisible = TRUE; + } + + int WINAPI Window::ShowCursorHook(BOOL show) + { + if (GetForegroundWindow() == Window::MainWindow) + { + static int count = 0; + (show ? ++count : --count); + + if (count >= 0) + { + Window::CursorVisible = TRUE; + } + + return count; + } + + return ShowCursor(show); + } + + HWND WINAPI Window::CreateMainWindow(DWORD dwExStyle, LPCSTR lpClassName, LPCSTR lpWindowName, DWORD dwStyle, int X, int Y, int nWidth, int nHeight, HWND hWndParent, HMENU hMenu, HINSTANCE hInstance, LPVOID lpParam) + { + Window::MainWindow = CreateWindowExA(dwExStyle, lpClassName, lpWindowName, dwStyle, X, Y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam); + return Window::MainWindow; + } + Window::Window() { // Borderless window Window::NoBorder = Dvar::Register("r_noborder", true, Game::dvar_flag::DVAR_FLAG_SAVED, "Do not use a border in windowed mode"); Utils::Hook(0x507643, Window::StyleHookStub, HOOK_CALL).Install()->Quick(); + + // Main window creation + Utils::Hook::Nop(0x5076AA, 1); + Utils::Hook(0x5076AB, Window::CreateMainWindow, HOOK_CALL).Install()->Quick(); + + // Mark the cursor as visible + Utils::Hook(0x48E5D3, Window::DrawCursorStub, HOOK_CALL).Install()->Quick(); + + // Draw the cursor if necessary + Renderer::OnFrame([] () + { + if (GetForegroundWindow() == Window::MainWindow) + { + int value = 0; + + if (Window::CursorVisible) + { + // TODO: Apply custom cursor + SetCursor(LoadCursor(NULL, IDC_ARROW)); + + while ((value = ShowCursor(TRUE)) < 0); + while (value > 0) { value = ShowCursor(FALSE); } // Set display counter to 0 + } + else + { + while ((value = ShowCursor(FALSE)) >= 0); + while (value < -1) { value = ShowCursor(TRUE); } // Set display counter to -1 + } + + Window::CursorVisible = FALSE; + } + }); + + // Don't let the game interact with the native cursor + Utils::Hook::Set(0x6D7348, Window::ShowCursorHook); } } diff --git a/src/Components/Modules/Window.hpp b/src/Components/Modules/Window.hpp index 0ec8ec53..7e507d8d 100644 --- a/src/Components/Modules/Window.hpp +++ b/src/Components/Modules/Window.hpp @@ -8,5 +8,15 @@ namespace Components static Dvar::Var NoBorder; static void Window::StyleHookStub(); + + private: + static BOOL CursorVisible; + + static int WINAPI ShowCursorHook(BOOL show); + static void DrawCursorStub(); + + static HWND MainWindow; + + static HWND WINAPI CreateMainWindow(DWORD dwExStyle, LPCSTR lpClassName, LPCSTR lpWindowName, DWORD dwStyle, int X, int Y, int nWidth, int nHeight, HWND hWndParent, HMENU hMenu, HINSTANCE hInstance, LPVOID lpParam); }; } diff --git a/src/STDInclude.hpp b/src/STDInclude.hpp index 8883ccb4..ceb1108b 100644 --- a/src/STDInclude.hpp +++ b/src/STDInclude.hpp @@ -10,10 +10,6 @@ #include #include -#pragma comment(lib, "Winmm.lib") -#pragma comment(lib, "Crypt32.lib") -#pragma comment(lib, "Ws2_32.lib") - #include #include #include @@ -32,3 +28,8 @@ #include "Game\Functions.hpp" #include "Components\Loader.hpp" + +// Libraries +#pragma comment(lib, "Winmm.lib") +#pragma comment(lib, "Crypt32.lib") +#pragma comment(lib, "Ws2_32.lib")