From 33ba9ed11ffccb3f5256438cfee5d6d69edbcd99 Mon Sep 17 00:00:00 2001
From: IcePixelx <41352111+PixieCore@users.noreply.github.com>
Date: Tue, 13 Jul 2021 18:38:48 +0200
Subject: [PATCH] Added CInputSystem Interface and use a different method of
 disabling game input.

---
 r5dev/include/gameclasses.h | 249 ++++++++++++++++++++++++++++++++++++
 r5dev/r5dev.vcxproj         |   1 +
 r5dev/r5dev.vcxproj.filters |   3 +
 r5dev/src/dllmain.cpp       |   1 +
 r5dev/src/id3dx.cpp         |  18 +--
 r5dev/src/overlay.cpp       |   8 +-
 6 files changed, 263 insertions(+), 17 deletions(-)
 create mode 100644 r5dev/include/gameclasses.h

diff --git a/r5dev/include/gameclasses.h b/r5dev/include/gameclasses.h
new file mode 100644
index 00000000..e68b5323
--- /dev/null
+++ b/r5dev/include/gameclasses.h
@@ -0,0 +1,249 @@
+#pragma once
+
+/////////////////////////////////////////////////////////////////////////////
+// Enums
+
+#define MAX_SPLITSCREEN_CLIENT_BITS 2
+#define MAX_SPLITSCREEN_CLIENTS	( 1 << MAX_SPLITSCREEN_CLIENT_BITS ) // 4
+
+enum
+{
+	MAX_JOYSTICKS = MAX_SPLITSCREEN_CLIENTS,
+	MOUSE_BUTTON_COUNT = 5,
+};
+
+enum JoystickAxis_t
+{
+	JOY_AXIS_X = 0,
+	JOY_AXIS_Y,
+	JOY_AXIS_Z,
+	JOY_AXIS_R,
+	JOY_AXIS_U,
+	JOY_AXIS_V,
+	MAX_JOYSTICK_AXES,
+};
+
+enum
+{
+	JOYSTICK_MAX_BUTTON_COUNT = 32,
+	JOYSTICK_POV_BUTTON_COUNT = 4,
+	JOYSTICK_AXIS_BUTTON_COUNT = MAX_JOYSTICK_AXES * 2,
+};
+
+#define JOYSTICK_BUTTON_INTERNAL( _joystick, _button ) ( JOYSTICK_FIRST_BUTTON + ((_joystick) * JOYSTICK_MAX_BUTTON_COUNT) + (_button) )
+#define JOYSTICK_POV_BUTTON_INTERNAL( _joystick, _button ) ( JOYSTICK_FIRST_POV_BUTTON + ((_joystick) * JOYSTICK_POV_BUTTON_COUNT) + (_button) )
+#define JOYSTICK_AXIS_BUTTON_INTERNAL( _joystick, _button ) ( JOYSTICK_FIRST_AXIS_BUTTON + ((_joystick) * JOYSTICK_AXIS_BUTTON_COUNT) + (_button) )
+
+#define JOYSTICK_BUTTON( _joystick, _button ) ( (ButtonCode_t)JOYSTICK_BUTTON_INTERNAL( _joystick, _button ) )
+#define JOYSTICK_POV_BUTTON( _joystick, _button ) ( (ButtonCode_t)JOYSTICK_POV_BUTTON_INTERNAL( _joystick, _button ) )
+#define JOYSTICK_AXIS_BUTTON( _joystick, _button ) ( (ButtonCode_t)JOYSTICK_AXIS_BUTTON_INTERNAL( _joystick, _button ) )
+
+enum ButtonCode_t
+{
+	BUTTON_CODE_INVALID = -1,
+	BUTTON_CODE_NONE = 0,
+
+	KEY_FIRST = 0,
+
+	KEY_NONE = KEY_FIRST,
+	KEY_0,
+	KEY_1,
+	KEY_2,
+	KEY_3,
+	KEY_4,
+	KEY_5,
+	KEY_6,
+	KEY_7,
+	KEY_8,
+	KEY_9,
+	KEY_A,
+	KEY_B,
+	KEY_C,
+	KEY_D,
+	KEY_E,
+	KEY_F,
+	KEY_G,
+	KEY_H,
+	KEY_I,
+	KEY_J,
+	KEY_K,
+	KEY_L,
+	KEY_M,
+	KEY_N,
+	KEY_O,
+	KEY_P,
+	KEY_Q,
+	KEY_R,
+	KEY_S,
+	KEY_T,
+	KEY_U,
+	KEY_V,
+	KEY_W,
+	KEY_X,
+	KEY_Y,
+	KEY_Z,
+	KEY_PAD_0,
+	KEY_PAD_1,
+	KEY_PAD_2,
+	KEY_PAD_3,
+	KEY_PAD_4,
+	KEY_PAD_5,
+	KEY_PAD_6,
+	KEY_PAD_7,
+	KEY_PAD_8,
+	KEY_PAD_9,
+	KEY_PAD_DIVIDE,
+	KEY_PAD_MULTIPLY,
+	KEY_PAD_MINUS,
+	KEY_PAD_PLUS,
+	KEY_PAD_ENTER,
+	KEY_PAD_DECIMAL,
+	KEY_LBRACKET,
+	KEY_RBRACKET,
+	KEY_SEMICOLON,
+	KEY_APOSTROPHE,
+	KEY_BACKQUOTE,
+	KEY_COMMA,
+	KEY_PERIOD,
+	KEY_SLASH,
+	KEY_BACKSLASH,
+	KEY_MINUS,
+	KEY_EQUAL,
+	KEY_ENTER,
+	KEY_SPACE,
+	KEY_BACKSPACE,
+	KEY_TAB,
+	KEY_CAPSLOCK,
+	KEY_NUMLOCK,
+	KEY_ESCAPE,
+	KEY_SCROLLLOCK,
+	KEY_INSERT,
+	KEY_DELETE,
+	KEY_HOME,
+	KEY_END,
+	KEY_PAGEUP,
+	KEY_PAGEDOWN,
+	KEY_BREAK,
+	KEY_LSHIFT,
+	KEY_RSHIFT,
+	KEY_LALT,
+	KEY_RALT,
+	KEY_LCONTROL,
+	KEY_RCONTROL,
+	KEY_LWIN,
+	KEY_RWIN,
+	KEY_APP,
+	KEY_UP,
+	KEY_LEFT,
+	KEY_DOWN,
+	KEY_RIGHT,
+	KEY_F1,
+	KEY_F2,
+	KEY_F3,
+	KEY_F4,
+	KEY_F5,
+	KEY_F6,
+	KEY_F7,
+	KEY_F8,
+	KEY_F9,
+	KEY_F10,
+	KEY_F11,
+	KEY_F12,
+	KEY_CAPSLOCKTOGGLE,
+	KEY_NUMLOCKTOGGLE,
+	KEY_SCROLLLOCKTOGGLE,
+
+	KEY_LAST = KEY_SCROLLLOCKTOGGLE,
+	KEY_COUNT = KEY_LAST - KEY_FIRST + 1,
+
+	// Mouse
+	MOUSE_FIRST = KEY_LAST + 1,
+
+	MOUSE_LEFT = MOUSE_FIRST,
+	MOUSE_RIGHT,
+	MOUSE_MIDDLE,
+	MOUSE_4,
+	MOUSE_5,
+	MOUSE_WHEEL_UP,		// A fake button which is 'pressed' and 'released' when the wheel is moved up
+	MOUSE_WHEEL_DOWN,	// A fake button which is 'pressed' and 'released' when the wheel is moved down
+
+	MOUSE_LAST = MOUSE_WHEEL_DOWN,
+	MOUSE_COUNT = MOUSE_LAST - MOUSE_FIRST + 1,
+
+	// Joystick
+	JOYSTICK_FIRST = MOUSE_LAST + 1,
+
+	JOYSTICK_FIRST_BUTTON = JOYSTICK_FIRST,
+	JOYSTICK_LAST_BUTTON = JOYSTICK_BUTTON_INTERNAL(MAX_JOYSTICKS - 1, JOYSTICK_MAX_BUTTON_COUNT - 1),
+	JOYSTICK_FIRST_POV_BUTTON,
+	JOYSTICK_LAST_POV_BUTTON = JOYSTICK_POV_BUTTON_INTERNAL(MAX_JOYSTICKS - 1, JOYSTICK_POV_BUTTON_COUNT - 1),
+	JOYSTICK_FIRST_AXIS_BUTTON,
+	JOYSTICK_LAST_AXIS_BUTTON = JOYSTICK_AXIS_BUTTON_INTERNAL(MAX_JOYSTICKS - 1, JOYSTICK_AXIS_BUTTON_COUNT - 1),
+
+	JOYSTICK_LAST = JOYSTICK_LAST_AXIS_BUTTON,
+
+	BUTTON_CODE_LAST,
+	BUTTON_CODE_COUNT = BUTTON_CODE_LAST - KEY_FIRST + 1,
+
+	// Helpers for XBox 360
+	KEY_XBUTTON_UP = JOYSTICK_FIRST_POV_BUTTON,	// POV buttons
+	KEY_XBUTTON_RIGHT,
+	KEY_XBUTTON_DOWN,
+	KEY_XBUTTON_LEFT,
+
+	KEY_XBUTTON_A = JOYSTICK_FIRST_BUTTON,		// Buttons
+	KEY_XBUTTON_B,
+	KEY_XBUTTON_X,
+	KEY_XBUTTON_Y,
+	KEY_XBUTTON_LEFT_SHOULDER,
+	KEY_XBUTTON_RIGHT_SHOULDER,
+	KEY_XBUTTON_BACK,
+	KEY_XBUTTON_START,
+	KEY_XBUTTON_STICK1,
+	KEY_XBUTTON_STICK2,
+	KEY_XBUTTON_INACTIVE_START,
+
+	KEY_XSTICK1_RIGHT = JOYSTICK_FIRST_AXIS_BUTTON,	// XAXIS POSITIVE
+	KEY_XSTICK1_LEFT,							// XAXIS NEGATIVE
+	KEY_XSTICK1_DOWN,							// YAXIS POSITIVE
+	KEY_XSTICK1_UP,								// YAXIS NEGATIVE
+	KEY_XBUTTON_LTRIGGER,						// ZAXIS POSITIVE
+	KEY_XBUTTON_RTRIGGER,						// ZAXIS NEGATIVE
+	KEY_XSTICK2_RIGHT,							// UAXIS POSITIVE
+	KEY_XSTICK2_LEFT,							// UAXIS NEGATIVE
+	KEY_XSTICK2_DOWN,							// VAXIS POSITIVE
+	KEY_XSTICK2_UP,								// VAXIS NEGATIVE
+};
+
+// Buttons are not confirmed to be the same. They have been always the same throughout the source engine. Lets hope they did not change them.
+
+/////////////////////////////////////////////////////////////////////////////
+// Classes and Structs
+
+class CInputSystem
+{
+public:
+	void EnableInput(bool bEnabled)
+	{
+		using OriginalFn = void(__thiscall*)(CInputSystem*, bool);
+		(*reinterpret_cast<OriginalFn**>(this))[10](this, bEnabled); // EnableInput is virtual function index 10 in the CInputSystem virtual table.
+	}
+
+	void EnableMessagePump(bool bEnabled)
+	{
+		using OriginalFn = void(__thiscall*)(CInputSystem*, bool);
+		(*reinterpret_cast<OriginalFn**>(this))[11](this, bEnabled); // EnableMessagePump is virtual function index 11 in the CInputSystem virtual table.
+	}
+
+	bool IsButtonDown(ButtonCode_t Button)
+	{
+		using OriginalFn = bool(__thiscall*)(CInputSystem*, ButtonCode_t);
+		return (*reinterpret_cast<OriginalFn**>(this))[13](this, Button); // IsButtonDown is virtual function index 13 in the CInputSystem virtual table.
+	}
+
+private:
+	char pad_0000[16]; //0x0000
+public:
+	bool m_bEnabled; //0x0010 IsInputEnabled variable.
+	bool m_bPumpEnabled; //0x0011 EnabledMessagePump variable.
+};
\ No newline at end of file
diff --git a/r5dev/r5dev.vcxproj b/r5dev/r5dev.vcxproj
index f2b70e96..7bcbab13 100644
--- a/r5dev/r5dev.vcxproj
+++ b/r5dev/r5dev.vcxproj
@@ -289,6 +289,7 @@
     <ClInclude Include="..\external\spdlog\include\version.h" />
     <ClInclude Include="include\console.h" />
     <ClInclude Include="include\enums.h" />
+    <ClInclude Include="include\gameclasses.h" />
     <ClInclude Include="include\hooks.h" />
     <ClInclude Include="include\id3dx.h" />
     <ClInclude Include="include\input.h" />
diff --git a/r5dev/r5dev.vcxproj.filters b/r5dev/r5dev.vcxproj.filters
index 12511512..5679d0d7 100644
--- a/r5dev/r5dev.vcxproj.filters
+++ b/r5dev/r5dev.vcxproj.filters
@@ -449,6 +449,9 @@
     <ClInclude Include="..\external\spdlog\include\sinks\qt_sinks.h">
       <Filter>External Libraries\spdlog\Header Files\sinks</Filter>
     </ClInclude>
+    <ClInclude Include="include\gameclasses.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <None Include="r5dev.def">
diff --git a/r5dev/src/dllmain.cpp b/r5dev/src/dllmain.cpp
index 2f9331b1..6dfe2b5f 100644
--- a/r5dev/src/dllmain.cpp
+++ b/r5dev/src/dllmain.cpp
@@ -8,6 +8,7 @@
 #include "opcptc.h"
 #include "console.h"
 #include "utility.h"
+#include "gameclasses.h"
 
 //#############################################################################
 // INITIALIZATION
diff --git a/r5dev/src/id3dx.cpp b/r5dev/src/id3dx.cpp
index 0c72bbbb..17d41e83 100644
--- a/r5dev/src/id3dx.cpp
+++ b/r5dev/src/id3dx.cpp
@@ -12,6 +12,7 @@
 #include "detours.h"
 #include "overlay.h"
 #include "patterns.h"
+#include "gameclasses.h"
 
 #include "imgui.h"
 #include "imgui_impl_dx11.h"
@@ -262,23 +263,16 @@ void DrawImGui()
 
 	ImGui::NewFrame();
 
+	static CInputSystem* InputSystem = *reinterpret_cast<CInputSystem**>(0x14D40B380);
+
 	if (g_bShowMenu)
 	{
-		bShowMenu = true;
-		if (!g_bInitMenu)
-		{
-			CommandExecute(NULL, "gameui_activate");
-			g_bInitMenu = true;
-		}
+		InputSystem->EnableInput(false); // Disable input.
 		ShowGameConsole(&bShowMenu);
 	}
-	else if(!g_bShowMenu)
+	else if (!g_bShowMenu)
 	{
-		if (g_bInitMenu)
-		{
-			CommandExecute(NULL, "gameui_hide");
-			g_bInitMenu = false;
-		}
+		InputSystem->EnableInput(true); // Enable input.
 	}
 
 	ImGui::EndFrame();
diff --git a/r5dev/src/overlay.cpp b/r5dev/src/overlay.cpp
index 4f1f99cd..01cd67ab 100644
--- a/r5dev/src/overlay.cpp
+++ b/r5dev/src/overlay.cpp
@@ -182,14 +182,12 @@ public:
 
         ImGui::SetNextWindowSize(ImVec2(840, 600), ImGuiCond_FirstUseEver);
         ImGui::SetWindowPos(ImVec2(-1000, 50), ImGuiCond_FirstUseEver);
-        if (!ImGui::Begin(title, p_open))
+
+        if (!ImGui::Begin(title, NULL)) // Passing a bool only causes problems if you Begin a new window. I would not suggest to use it.
         {
             ImGui::End(); return;
         }
-        if (*p_open == NULL)
-        {
-            g_bShowMenu = false;
-        }
+
         ///////////////////////////////////////////////////////////////////////
         if (ImGui::SmallButton("Developer mode"))
         {