From 3fa766f730624c7f4c6c6fd3f1bfeefe7c46a5ae Mon Sep 17 00:00:00 2001
From: Amos <k.mazidjatari@gmail.com>
Date: Mon, 19 Jul 2021 04:05:54 -0700
Subject: [PATCH] Set persistent var for all players on connect

And separate serverbrowser from gameconsole
---
 r5dev/include/id3dx.h    |  3 +-
 r5dev/include/opcptc.h   |  6 ----
 r5dev/include/overlay.h  | 73 +++++++++++++++++++++++++++++++++++++---
 r5dev/include/patterns.h |  5 +++
 r5dev/src/dllmain.cpp    |  1 -
 r5dev/src/hooks.cpp      | 50 +++++++++++++++++++--------
 r5dev/src/id3dx.cpp      | 26 ++++++++++----
 r5dev/src/opcptc.cpp     | 10 ------
 r5dev/src/overlay.cpp    | 14 ++++++--
 9 files changed, 144 insertions(+), 44 deletions(-)

diff --git a/r5dev/include/id3dx.h b/r5dev/include/id3dx.h
index 3cb8c6b0..bdd47f1c 100644
--- a/r5dev/include/id3dx.h
+++ b/r5dev/include/id3dx.h
@@ -22,6 +22,7 @@ extern HRESULT __stdcall Present(IDXGISwapChain* pSwapChain, UINT nSyncInterval,
 /////////////////////////////////////////////////////////////////////////////
 // Globals
 extern DWORD g_dThreadId;
-extern BOOL  g_bShowMenu;
+extern BOOL  g_bShowConsole;
+extern BOOL  g_bShowBrowser;
 
 /////////////////////////////////////////////////////////////////////////////
diff --git a/r5dev/include/opcptc.h b/r5dev/include/opcptc.h
index 1aee8376..6989692f 100644
--- a/r5dev/include/opcptc.h
+++ b/r5dev/include/opcptc.h
@@ -5,7 +5,6 @@
 #include "utility.h"
 
 void InstallOpcodes();
-void InstallGlobals();
 inline HANDLE GameProcess = GetCurrentProcess();
 
 namespace
@@ -16,7 +15,6 @@ namespace
 
 	/* -------------- ENGINE ------------------------------------------------------------------------------------------------------------------------------------------------ */
 	DWORD64 dst002 /*0x14043FB90*/ = reinterpret_cast<DWORD64>(PatternScan("r5apex.exe", "48 89 4C 24 08 56 41 55 48 81 EC 68 03 ? ? 4C"));
-	DWORD64 dst003 /*0x140302FF0*/ = reinterpret_cast<DWORD64>(PatternScan("r5apex.exe", "40 53 41 56 41 57 48 83 EC 20 48 8B D9 48 89 74"));
 	DWORD64 dst004 /*0x14022A4A0*/ = reinterpret_cast<DWORD64>(PatternScan("r5apex.exe", "48 83 EC 38 0F 29 74 24 20 48 89 5C 24 40 48 8B"));
 	DWORD64 Host_NewGame /*0x140238DA0*/ = reinterpret_cast<DWORD64>(PatternScan("r5apex.exe", "48 8B C4 ? 41 54 41 ? 48 81 EC ? ? ? ? F2"));
 
@@ -28,9 +26,6 @@ namespace
 
 	/* -------------- ------- ----------------------------------------------------------------------------------------------------------------------------------------------- */
 
-	/* -------------- GLOBALS ----------------------------------------------------------------------------------------------------------------------------------------------- */
-	DWORD64 ofs000 = 0x000000016073B7BC;
-
 	void PrintOAddress() // Test the sigscan results
 	{
 		std::cout << "+--------------------------------------------------------+" << std::endl;
@@ -38,7 +33,6 @@ namespace
 		std::cout << "| dst001                   : " << std::hex << std::uppercase << dst001 << std::setw(20) << " |" << std::endl;
 		std::cout << "+--------------------------------------------------------+" << std::endl;
 		std::cout << "| dst002                   : " << std::hex << std::uppercase << dst002 << std::setw(20) << " |" << std::endl;
-		std::cout << "| dst003                   : " << std::hex << std::uppercase << dst003 << std::setw(20) << " |" << std::endl;
 		std::cout << "| dst004                   : " << std::hex << std::uppercase << dst004 << std::setw(20) << " |" << std::endl;
 		std::cout << "| Host_NewGame             : " << std::hex << std::uppercase << Host_NewGame << std::setw(20) << " |" << std::endl;
 		std::cout << "+--------------------------------------------------------+" << std::endl;
diff --git a/r5dev/include/overlay.h b/r5dev/include/overlay.h
index 017b4eab..189b8eb9 100644
--- a/r5dev/include/overlay.h
+++ b/r5dev/include/overlay.h
@@ -8,7 +8,8 @@
 void PrintDXAddress();
 void InstallDXHooks();
 void RemoveDXHooks();
-void DrawMenu();
+void DrawConsole();
+void DrawBrowser();
 
 /////////////////////////////////////////////////////////////////////////////
 // Internals
@@ -141,12 +142,14 @@ extern CGameConsole* g_GameConsole;
 
 class CCompanion
 {
+private:
+    bool ThemeSet = false;
 public:
     CCompanion();
 
     ////////////////////
-    //     Enums     //
-    //////////////////
+    //     Enums      //
+    ////////////////////
 
     enum class ESection {
         ServerBrowser,
@@ -163,7 +166,7 @@ public:
 
     ////////////////////
     // Server Browser //
-    ///////////////////
+    ////////////////////
     ImVector<ServerListing*> ServerList;
     ServerListing* SelectedServer;
     ImGuiTextFilter ServerBrowserFilter;
@@ -189,6 +192,68 @@ public:
         CurrentSection = section;
     }
 
+    ////////////////////
+    //     Style      //
+    ////////////////////
+    void SetStyleVar()
+    {
+        ImGuiStyle& style = ImGui::GetStyle();
+        ImVec4* colors = style.Colors;
+
+        colors[ImGuiCol_Text] = ImVec4(0.81f, 0.81f, 0.81f, 1.00f);
+        colors[ImGuiCol_TextDisabled] = ImVec4(0.56f, 0.56f, 0.56f, 1.00f);
+        colors[ImGuiCol_WindowBg] = ImVec4(0.27f, 0.27f, 0.27f, 1.00f);
+        colors[ImGuiCol_ChildBg] = ImVec4(0.00f, 0.00f, 0.00f, 1.00f);
+        colors[ImGuiCol_PopupBg] = ImVec4(0.27f, 0.27f, 0.27f, 1.00f);
+        colors[ImGuiCol_Border] = ImVec4(0.41f, 0.41f, 0.41f, 1.00f);
+        colors[ImGuiCol_BorderShadow] = ImVec4(0.04f, 0.04f, 0.04f, 0.64f);
+        colors[ImGuiCol_FrameBg] = ImVec4(0.13f, 0.13f, 0.13f, 1.00f);
+        colors[ImGuiCol_FrameBgHovered] = ImVec4(0.19f, 0.19f, 0.19f, 1.00f);
+        colors[ImGuiCol_FrameBgActive] = ImVec4(0.24f, 0.24f, 0.24f, 1.00f);
+        colors[ImGuiCol_TitleBg] = ImVec4(0.22f, 0.22f, 0.22f, 1.00f);
+        colors[ImGuiCol_TitleBgActive] = ImVec4(0.27f, 0.27f, 0.27f, 1.00f);
+        colors[ImGuiCol_TitleBgCollapsed] = ImVec4(0.00f, 0.00f, 0.00f, 1.00f);
+        colors[ImGuiCol_MenuBarBg] = ImVec4(0.22f, 0.22f, 0.22f, 1.00f);
+        colors[ImGuiCol_ScrollbarBg] = ImVec4(0.10f, 0.10f, 0.10f, 1.00f);
+        colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.41f, 0.41f, 0.41f, 1.00f);
+        colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.53f, 0.53f, 0.53f, 1.00f);
+        colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.63f, 0.63f, 0.63f, 1.00f);
+        colors[ImGuiCol_CheckMark] = ImVec4(0.61f, 0.61f, 0.61f, 1.00f);
+        colors[ImGuiCol_SliderGrab] = ImVec4(0.41f, 0.41f, 0.41f, 1.00f);
+        colors[ImGuiCol_SliderGrabActive] = ImVec4(0.53f, 0.53f, 0.53f, 1.00f);
+        colors[ImGuiCol_Button] = ImVec4(0.35f, 0.35f, 0.35f, 1.00f);
+        colors[ImGuiCol_ButtonHovered] = ImVec4(0.45f, 0.45f, 0.45f, 1.00f);
+        colors[ImGuiCol_ButtonActive] = ImVec4(0.52f, 0.52f, 0.52f, 1.00f);
+        colors[ImGuiCol_Header] = ImVec4(0.35f, 0.35f, 0.35f, 1.00f);
+        colors[ImGuiCol_HeaderHovered] = ImVec4(0.45f, 0.45f, 0.45f, 1.00f);
+        colors[ImGuiCol_HeaderActive] = ImVec4(0.53f, 0.53f, 0.53f, 1.00f);
+        colors[ImGuiCol_Separator] = ImVec4(0.53f, 0.53f, 0.57f, 1.00f);
+        colors[ImGuiCol_SeparatorHovered] = ImVec4(0.53f, 0.53f, 0.53f, 1.00f);
+        colors[ImGuiCol_SeparatorActive] = ImVec4(0.63f, 0.63f, 0.63f, 1.00f);
+        colors[ImGuiCol_ResizeGrip] = ImVec4(0.41f, 0.41f, 0.41f, 1.00f);
+        colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.52f, 0.52f, 0.52f, 1.00f);
+        colors[ImGuiCol_ResizeGripActive] = ImVec4(0.63f, 0.63f, 0.63f, 1.00f);
+        colors[ImGuiCol_Tab] = ImVec4(0.18f, 0.18f, 0.18f, 1.00f);
+        colors[ImGuiCol_TabHovered] = ImVec4(0.39f, 0.39f, 0.39f, 1.00f);
+        colors[ImGuiCol_TabActive] = ImVec4(0.39f, 0.39f, 0.39f, 1.00f);
+
+        style.WindowBorderSize = 0.0f;
+        style.FrameBorderSize = 1.0f;
+        style.ChildBorderSize = 1.0f;
+        style.PopupBorderSize = 1.0f;
+        style.TabBorderSize = 1.0f;
+
+        style.WindowRounding = 2.5f;
+        style.FrameRounding = 0.0f;
+        style.ChildRounding = 0.0f;
+        style.PopupRounding = 0.0f;
+        style.TabRounding = 1.0f;
+        style.ScrollbarRounding = 1.0f;
+
+        style.ItemSpacing = ImVec2(4, 4);
+        style.WindowPadding = ImVec2(5, 5);
+    }
+
     void RefreshServerList();
     void SendHostingPostRequest(char* mapName);
     void CompMenu();
diff --git a/r5dev/include/patterns.h b/r5dev/include/patterns.h
index a130b08f..5068576a 100644
--- a/r5dev/include/patterns.h
+++ b/r5dev/include/patterns.h
@@ -44,6 +44,11 @@ namespace
 	DWORD64 p_CHLClient_FrameStageNotify = /*0x1405C0740*/ reinterpret_cast<DWORD64>(PatternScan("r5apex.exe", "48 83 EC 28 89 15 ?? ?? ?? ??"));
 	void (*org_CHLClient_FrameStageNotify)(void* rcx, int curStage) = (void (*)(void*, int))p_CHLClient_FrameStageNotify;
 
+	////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+	/* ==== CCLIENT ========================================================================================================================================================= */
+	DWORD64 p_Persistence_IsReady = /*0x140315CF0*/ reinterpret_cast<DWORD64>(PatternScan("r5apex.exe", "3B 15 ?? ?? ?? ?? 7D 33"));
+	bool (*org_Persistence_IsReady)(__int64 entidx, int client) = (bool(*)(__int64, int))p_Persistence_IsReady;
+
 	////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 	/* ==== UTILITY ========================================================================================================================================================= */
 	DWORD64 p_MSG_EngineError = /*0x140295600*/ reinterpret_cast<DWORD64>(PatternScan("r5apex.exe", "48 89 5C 24 08 48 89 74 24 10 57 48 81 EC 30 08 00 00 48 8B DA 48 8B F9 E8 ?? ?? ?? FF 33 F6 48"));
diff --git a/r5dev/src/dllmain.cpp b/r5dev/src/dllmain.cpp
index 6dfe2b5f..ddc7b946 100644
--- a/r5dev/src/dllmain.cpp
+++ b/r5dev/src/dllmain.cpp
@@ -21,7 +21,6 @@ void InitializeR5Dev()
     InstallIPHooks();
     InstallDXHooks();
     InstallOpcodes();
-    InstallGlobals();
     SetupDXSwapChain();
     printf("+-----------------------------------------------------------------------------+\n");
     printf("|   R5 DEV -- INITIALIZED -------------------------------------------------   |\n");
diff --git a/r5dev/src/hooks.cpp b/r5dev/src/hooks.cpp
index f8420908..647e10ad 100644
--- a/r5dev/src/hooks.cpp
+++ b/r5dev/src/hooks.cpp
@@ -108,15 +108,13 @@ __int64 HSQVM_LoadRson(const char* rson_name)
 		printf("\n");
 		return org_SQVM_LoadRson(filepath);
 	}
-	else
-	{
-		printf("\n");
-		printf("##################################################\n");
-		printf("] '%s'\n", rson_name);
-		printf("##################################################\n");
-		printf("\n");
-		return org_SQVM_LoadRson(rson_name);
-	}
+
+	printf("\n");
+	printf("##################################################\n");
+	printf("] '%s'\n", rson_name);
+	printf("##################################################\n");
+	printf("\n");
+	return org_SQVM_LoadRson(rson_name);
 }
 
 bool HSQVM_LoadScript(void* sqvm, const char* script_path, const char* script_name, int flag)
@@ -156,15 +154,37 @@ bool HSQVM_LoadScript(void* sqvm, const char* script_path, const char* script_na
 
 int HMSG_EngineError(char* fmt, va_list args)
 {
-	char buf[1024];
-	printf("ENGINE ERROR #####################################\n");
+	printf("\nENGINE ERROR #####################################\n");
 	vprintf(fmt, args);
-	vsnprintf(buf, IM_ARRAYSIZE(buf), fmt, args);
-	buf[IM_ARRAYSIZE(buf) - 1] = 0;
-	Items.push_back(Strdup(buf));
 	return org_MSG_EngineError(fmt, args);
 }
 
+// TODO: turn this into a playerstruct constructor if it ever becomes necessary
+bool HPersistence_IsReady(__int64 entidx, int client)
+{
+	static bool isPersistenceVarSet[256];
+
+	// TODO: Maybe not hardcode
+	DWORD64 playerStructBase = 0x16073B200;
+	DWORD64 playerStructSize = 0x4A4C0;
+	DWORD64 persistenceVar = 0x5BC;
+
+	DWORD64 targetPlayerStruct = playerStructBase + client * playerStructSize;
+
+	*(char*)(targetPlayerStruct + persistenceVar) = (char)0x5;
+
+	if (!isPersistenceVarSet[client])
+	{
+		printf("\n");
+		printf("##################################################\n");
+		printf("] SETTING PERSISTENCE VAR FOR CLIENT #%d\n", client);
+		printf("##################################################\n");
+		printf("\n");
+		isPersistenceVarSet[client] = true;
+	}
+	return org_Persistence_IsReady;
+}
+
 //#################################################################################
 // MANAGEMENT
 //#################################################################################
@@ -189,6 +209,7 @@ void InstallENHooks()
 	///////////////////////////////////////////////////////////////////////////////
 	// Hook Utility functions
 	DetourAttach((LPVOID*)&org_MSG_EngineError, &HMSG_EngineError);
+	DetourAttach((LPVOID*)&org_Persistence_IsReady, &HPersistence_IsReady);
 
 	///////////////////////////////////////////////////////////////////////////////
 	// Commit the transaction
@@ -224,6 +245,7 @@ void RemoveENHooks()
 	///////////////////////////////////////////////////////////////////////////////
 	// Unhook Utility functions
 	DetourDetach((LPVOID*)&org_MSG_EngineError, &HMSG_EngineError);
+	DetourDetach((LPVOID*)&org_Persistence_IsReady, &HPersistence_IsReady);
 
 	///////////////////////////////////////////////////////////////////////////////
 	// Commit the transaction
diff --git a/r5dev/src/id3dx.cpp b/r5dev/src/id3dx.cpp
index d3199812..02f04f09 100644
--- a/r5dev/src/id3dx.cpp
+++ b/r5dev/src/id3dx.cpp
@@ -33,7 +33,8 @@ typedef BOOL(WINAPI* IPostMessageA)(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM l
 typedef BOOL(WINAPI* IPostMessageW)(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
 
 ///////////////////////////////////////////////////////////////////////////////////
-extern BOOL                     g_bShowMenu                 = false;
+extern BOOL                     g_bShowConsole              = false;
+extern BOOL                     g_bShowBrowser              = false;
 static BOOL                     g_bInitMenu                 = false;
 static BOOL                     g_bInitialized              = false;
 static BOOL                     g_bPresentHooked            = false;
@@ -69,10 +70,17 @@ LRESULT CALLBACK HwndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
 	{
 		if (wParam == VK_OEM_3 || wParam == VK_INSERT) // For everyone without a US keyboard layout.
 		{
-			g_bShowMenu = !g_bShowMenu;
+			g_bShowConsole = !g_bShowConsole;
 		}
 	}
-	if (g_bShowMenu)
+	if (uMsg == WM_SYSKEYDOWN)
+	{
+		if (wParam == VK_F10)
+		{
+			g_bShowBrowser = !g_bShowBrowser;
+		}
+	}
+	if (g_bShowConsole || g_bShowBrowser)
 	{//////////////////////////////////////////////////////////////////////////////
 		ImGui_ImplWin32_WndProcHandler(hWnd, uMsg, wParam, lParam);
 		g_bBlockInput = true;
@@ -264,10 +272,15 @@ void DrawImGui()
 
 	ImGui::NewFrame();
 
-	if (g_bShowMenu)
+	if (g_bShowConsole)
 	{
 		GameGlobals::InputSystem->EnableInput(false); // Disable input.
-		DrawMenu();
+		DrawConsole();
+	}
+	if(g_bShowBrowser)
+	{
+		GameGlobals::InputSystem->EnableInput(false); // Disable input.
+		DrawBrowser();
 	}
 	else
 	{
@@ -351,7 +364,8 @@ HRESULT GetDeviceAndCtxFromSwapchain(IDXGISwapChain* pSwapChain, ID3D11Device**
 
 HRESULT __stdcall GetResizeBuffers(IDXGISwapChain* pSwapChain, UINT nBufferCount, UINT nWidth, UINT nHeight, DXGI_FORMAT dxFormat, UINT nSwapChainFlags)
 {
-	g_bShowMenu       = false;
+	g_bShowConsole    = false;
+	g_bShowBrowser    = false;
 	g_bInitialized    = false;
 	g_bPresentHooked  = false;
 
diff --git a/r5dev/src/opcptc.cpp b/r5dev/src/opcptc.cpp
index 64eb122d..df506351 100644
--- a/r5dev/src/opcptc.cpp
+++ b/r5dev/src/opcptc.cpp
@@ -15,9 +15,6 @@ void InstallOpcodes() /* .TEXT */
 	// JNE --> JMP | Allow games to be loaded without the optional texture streaming file
 	WriteProcessMemory(GameProcess, LPVOID(dst002 + 0x8E5), "\xEB\x19", 2, NULL);
 	//-------------------------------------------------------------------------
-	// MOV --> NOP | Prevent PDATA global being initialized as NULL
-	WriteProcessMemory(GameProcess, LPVOID(dst003 + 0x174), "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90", 14, NULL);
-	//-------------------------------------------------------------------------
 	// JNE --> JMP | Prevent connect command from crashing by invalid call to UI function
 	WriteProcessMemory(GameProcess, LPVOID(dst004 + 0x1D6), "\xEB\x27", 2, NULL);
 	//-------------------------------------------------------------------------
@@ -30,10 +27,3 @@ void InstallOpcodes() /* .TEXT */
 	// JA  --> JMP | Prevent FairFight anti-cheat from initializing on the server
 	WriteProcessMemory(GameProcess, LPVOID(dst007 + 0x61), "\xE9\xED\x00\x00\x00\x00", 6, NULL);
 }
-
-void InstallGlobals() /* .DATA */
-{
-	//-------------------------------------------------------------------------
-	//  00  --> 05  | Set PDATA global to enable clientcommand codecallback on the server
-	WriteProcessMemory(GameProcess, LPVOID(ofs000), "\x05", 1, NULL);
-}
diff --git a/r5dev/src/overlay.cpp b/r5dev/src/overlay.cpp
index 75663218..321363e0 100644
--- a/r5dev/src/overlay.cpp
+++ b/r5dev/src/overlay.cpp
@@ -615,6 +615,12 @@ void CCompanion::SettingsSection()
 
 void CCompanion::Draw(const char* title)
 {
+    if (!ThemeSet)
+    {
+        SetStyleVar();
+        ThemeSet = true;
+    }
+
     ImGui::SetNextWindowSize(ImVec2(800, 890), ImGuiCond_FirstUseEver);
     ImGui::SetWindowPos(ImVec2(-500, 50), ImGuiCond_FirstUseEver);
 
@@ -687,11 +693,15 @@ void Strtrim(char* s)
 // ENTRYPOINT
 //#############################################################################
 
-void DrawMenu()
+void DrawConsole()
 {
     static CGameConsole console;
     g_GameConsole = &console;
-    static CCompanion browser;
     console.Draw("Console");
+}
+
+void DrawBrowser()
+{
+    static CCompanion browser;
     browser.Draw("Companion");
 }
\ No newline at end of file