diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000..c9ca975
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,11 @@
+cmake_minimum_required(VERSION 2.8)
+project(cstrike-basehook)
+
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -std=c++14 -I./include -m32 -Wall -Wextra -Wpedantic")
+set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -static-libstdc++ -m32 -lSDL2")
+
+file(GLOB_RECURSE SOURCE_FILES src/*.cpp include/*.cpp)
+
+add_library(cstrike-basehook SHARED ${SOURCE_FILES})
+
+target_link_libraries(cstrike-basehook)
diff --git a/src/Basehook.cpp b/src/Basehook.cpp
new file mode 100644
index 0000000..d5b7628
--- /dev/null
+++ b/src/Basehook.cpp
@@ -0,0 +1,113 @@
+/*
+
+ cstrike-basehook-linux -- Internal base for Counter-Strike: Source.
+ Copyright (C) 2016, aixxe. (www.aixxe.net)
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with cstrike-basehook-linux. If not, see .
+
+*/
+
+#include "Basehook.h"
+#include "Hooks/Hooks.h"
+
+ICvar* cvar = nullptr;
+IPanel* panel = nullptr;
+ISurface* matsurface = nullptr;
+IVModelInfoClient* modelinfo = nullptr;
+ILauncherMgr* launchermgr = nullptr;
+IInputSystem* inputsystem = nullptr;
+IInputInternal* inputinternal = nullptr;
+IVEngineClient* engine = nullptr;
+IVModelRender* modelrender = nullptr;
+IVDebugOverlay* debugoverlay = nullptr;
+IBaseClientDLL* clientdll = nullptr;
+IMaterialSystem* matsystem = nullptr;
+IClientEntityList* entitylist = nullptr;
+IGameEventManager2* gameevents = nullptr;
+
+CInput* input = nullptr;
+CGlobalVarsBase* globalvars = nullptr;
+
+CRC32_ProcessBufferFn CRC32_ProcessBuffer = NULL;
+
+NetVars netvars;
+
+std::unique_ptr sdl_hook;
+std::unique_ptr panel_hook;
+std::unique_ptr clientdll_hook;
+std::unique_ptr modelrender_hook;
+std::unique_ptr inputinternal_hook;
+
+extern "C" void __attribute__((constructor)) css_basehook_open() {
+ // Get class pointers from game libraries using partial interface versions.
+ cvar = GetInterface("bin/libvstdlib.so", "VEngineCvar0");
+ panel = GetInterface("bin/vgui2.so", "VGUI_Panel0");
+ matsurface = GetInterface("bin/vguimatsurface.so", "VGUI_Surface0");
+ modelinfo = GetInterface("bin/engine.so", "VModelInfoClient0");
+ inputsystem = GetInterface("bin/inputsystem.so", "InputSystemVersion0");
+ inputinternal = GetInterface("bin/vgui2.so", "VGUI_InputInternal0");
+ engine = GetInterface("bin/engine.so", "VEngineClient0");
+ modelrender = GetInterface("bin/engine.so", "VEngineModel0");
+ debugoverlay = GetInterface("bin/engine.so", "VDebugOverlay0");
+ clientdll = GetInterface("bin/client.so", "VClient0");
+ matsystem = GetInterface("bin/materialsystem.so", "VMaterialSystem0");
+ entitylist = GetInterface("bin/client.so", "VClientEntityList0");
+ gameevents = GetInterface("bin/engine.so", "GAMEEVENTSMANAGER002");
+
+ // Scan for the 'CRC32_ProcessBuffer' function.
+ CRC32_ProcessBuffer = reinterpret_cast(
+ FindPattern("bin/client.so", "\x55\x89\xE5\x57\x56\x53\x83\xEC\x08\x8B\x4D\x10", "xxxxxxxxxxxx")
+ );
+
+ // Hook 'FrameStageNotify' and 'CreateMove' from IBaseClientDLL.
+ clientdll_hook = std::make_unique(clientdll);
+ clientdll_hook->HookFunction(reinterpret_cast(Hooks::CreateMove), 21);
+ clientdll_hook->HookFunction(reinterpret_cast(Hooks::FrameStageNotify), 35);
+
+ // Hook 'PaintTraverse' from IPanel.
+ panel_hook = std::make_unique(panel);
+ panel_hook->HookFunction(reinterpret_cast(Hooks::PaintTraverse), 42);
+
+ // Hook 'DrawModelExecute' from IVModelRender.
+ modelrender_hook = std::make_unique(modelrender);
+ modelrender_hook->HookFunction(reinterpret_cast(Hooks::DrawModelExecute), 19);
+
+ // Hook 'PumpWindowsMessageLoop' and 'ShowPixels' from ILauncherMgr.
+ launchermgr = **reinterpret_cast(
+ FindPattern("bin/launcher.so", "\x24\x8B\x1D\x00\x00\x00\x00", "xxx????") + 3
+ );
+
+ sdl_hook = std::make_unique(launchermgr);
+ sdl_hook->HookFunction(reinterpret_cast(Hooks::PumpWindowsMessageLoop), 15);
+ sdl_hook->HookFunction(reinterpret_cast(Hooks::ShowPixels), 29);
+
+ // Hook 'SetKeyCodeState' and 'SetMouseCodeState' from IInputInternal.
+ inputinternal_hook = std::make_unique(inputinternal);
+ inputinternal_hook->HookFunction(reinterpret_cast(Hooks::SetKeyCodeState), 83);
+ inputinternal_hook->HookFunction(reinterpret_cast(Hooks::SetMouseCodeState), 84);
+
+ // Get a pointer to CInput from 'IN_ActivateMouse' in IBaseClientDLL.
+ input = **reinterpret_cast(
+ clientdll_hook->GetOriginalFunction(14) + 1
+ );
+
+ // Get a pointer to CGlobalVarsBase from 'HUDUpdate' in IBaseClientDLL.
+ globalvars = **reinterpret_cast(
+ clientdll_hook->GetOriginalFunction(11) + 8
+ );
+}
+
+extern "C" void __attribute__((destructor)) css_basehook_close() {
+ cvar->ConsoleColorPrintf(Color(255, 150, 150), "Unloaded from game successfully.\n");
+}
\ No newline at end of file
diff --git a/src/Basehook.h b/src/Basehook.h
new file mode 100644
index 0000000..1a8aa8a
--- /dev/null
+++ b/src/Basehook.h
@@ -0,0 +1,14 @@
+#pragma once
+
+#include
+#include
+
+#include
+#include
+
+#include "Utilities/Linker.h"
+#include "Utilities/FindPattern.h"
+#include "Utilities/Interfaces.h"
+#include "Utilities/NetVars.h"
+
+extern NetVars netvars;
\ No newline at end of file
diff --git a/src/Hooks/CreateMove.cpp b/src/Hooks/CreateMove.cpp
new file mode 100644
index 0000000..1ba6d2c
--- /dev/null
+++ b/src/Hooks/CreateMove.cpp
@@ -0,0 +1,21 @@
+#include "Hooks.h"
+
+typedef void (*CreateMove_t) (IBaseClientDLL*, int, float, bool);
+
+void Hooks::CreateMove(IBaseClientDLL* thisptr, int sequence, float frametime, bool active) {
+ // Get the original function and store it statically.
+ static CreateMove_t oCreateMove = clientdll_hook->GetOriginalFunction(21);
+
+ // Call original 'IBaseClientDLL::CreateMove'.
+ oCreateMove(thisptr, sequence, frametime, active);
+
+ // Get the current user command.
+ CUserCmd* cmd = input->GetUserCmd(sequence);
+
+ if (cmd->buttons & IN_JUMP) {
+ cmd->buttons |= IN_ATTACK;
+ }
+
+ // Re-calculate the command checksum after making changes.
+ input->VerifyUserCmd(cmd, sequence);
+}
\ No newline at end of file
diff --git a/src/Hooks/DrawModelExecute.cpp b/src/Hooks/DrawModelExecute.cpp
new file mode 100644
index 0000000..6ee884d
--- /dev/null
+++ b/src/Hooks/DrawModelExecute.cpp
@@ -0,0 +1,11 @@
+#include "Hooks.h"
+
+typedef void (*DrawModelExecute_t) (IVModelRender*, DrawModelState_t const&, ModelRenderInfo_t const&, matrix3x4_t*);
+
+void Hooks::DrawModelExecute(IVModelRender* thisptr, DrawModelState_t const& drawmodelstate, ModelRenderInfo_t const& modelrenderinfo, matrix3x4_t* bonetoworld) {
+ // Get the original function and store it statically.
+ static DrawModelExecute_t oDrawModelExecute = modelrender_hook->GetOriginalFunction(19);
+
+ // Call original 'IVModelRender::DrawModelExecute'.
+ oDrawModelExecute(thisptr, drawmodelstate, modelrenderinfo, bonetoworld);
+}
\ No newline at end of file
diff --git a/src/Hooks/FrameStageNotify.cpp b/src/Hooks/FrameStageNotify.cpp
new file mode 100644
index 0000000..d20aa00
--- /dev/null
+++ b/src/Hooks/FrameStageNotify.cpp
@@ -0,0 +1,11 @@
+#include "Hooks.h"
+
+typedef void (*FrameStageNotify_t) (IBaseClientDLL*, ClientFrameStage_t);
+
+void Hooks::FrameStageNotify(IBaseClientDLL* thisptr, ClientFrameStage_t stage) {
+ // Get the original function and store it statically.
+ static FrameStageNotify_t oFrameStageNotify = clientdll_hook->GetOriginalFunction(35);
+
+ // Call original 'IBaseClientDLL::FrameStageNotify'.
+ oFrameStageNotify(thisptr, stage);
+}
\ No newline at end of file
diff --git a/src/Hooks/Hooks.h b/src/Hooks/Hooks.h
new file mode 100644
index 0000000..dc7ebbc
--- /dev/null
+++ b/src/Hooks/Hooks.h
@@ -0,0 +1,29 @@
+#pragma once
+
+#include "../Basehook.h"
+
+namespace Hooks {
+ // IBaseClientDLL
+ void CreateMove(IBaseClientDLL*, int, float, bool);
+ void FrameStageNotify(IBaseClientDLL*, ClientFrameStage_t);
+
+ // IPanel
+ void PaintTraverse(IPanel*, VPANEL, bool, bool);
+
+ // IVModelRender
+ void DrawModelExecute(IVModelRender*, DrawModelState_t const&, ModelRenderInfo_t const&, matrix3x4_t*);
+
+ // ILauncherMgr
+ void PumpWindowsMessageLoop(ILauncherMgr*);
+ void ShowPixels(ILauncherMgr*, CShowPixelsParams*);
+
+ // IInputInternal
+ void SetKeyCodeState(IInputInternal*, KeyCode, bool);
+ void SetMouseCodeState(IInputInternal*, MouseCode, MouseCodeState_t);
+}
+
+extern std::unique_ptr sdl_hook;
+extern std::unique_ptr panel_hook;
+extern std::unique_ptr clientdll_hook;
+extern std::unique_ptr modelrender_hook;
+extern std::unique_ptr inputinternal_hook;
\ No newline at end of file
diff --git a/src/Hooks/PaintTraverse.cpp b/src/Hooks/PaintTraverse.cpp
new file mode 100644
index 0000000..9eca49a
--- /dev/null
+++ b/src/Hooks/PaintTraverse.cpp
@@ -0,0 +1,11 @@
+#include "Hooks.h"
+
+typedef void (*PaintTraverse_t) (IPanel*, VPANEL, bool, bool);
+
+void Hooks::PaintTraverse(IPanel* thisptr, VPANEL vpanel, bool force_repaint, bool allow_force) {
+ // Get the original function and store it statically.
+ static PaintTraverse_t oPaintTraverse = panel_hook->GetOriginalFunction(42);
+
+ // Call original 'IPanel::PaintTraverse'.
+ oPaintTraverse(thisptr, vpanel, force_repaint, allow_force);
+}
\ No newline at end of file
diff --git a/src/Hooks/PumpWindowsMessageLoop.cpp b/src/Hooks/PumpWindowsMessageLoop.cpp
new file mode 100644
index 0000000..ad723aa
--- /dev/null
+++ b/src/Hooks/PumpWindowsMessageLoop.cpp
@@ -0,0 +1,11 @@
+#include "Hooks.h"
+
+typedef void (*PumpWindowsMessageLoop_t) (ILauncherMgr*);
+
+void Hooks::PumpWindowsMessageLoop(ILauncherMgr* thisptr) {
+ // Get the original function and store it statically.
+ static PumpWindowsMessageLoop_t oPumpWindowsMessageLoop = sdl_hook->GetOriginalFunction(15);
+
+ // Call original 'ILauncherMgr::PumpWindowsMessageLoop'.
+ oPumpWindowsMessageLoop(thisptr);
+}
\ No newline at end of file
diff --git a/src/Hooks/SetKeyCodeState.cpp b/src/Hooks/SetKeyCodeState.cpp
new file mode 100644
index 0000000..0b32be3
--- /dev/null
+++ b/src/Hooks/SetKeyCodeState.cpp
@@ -0,0 +1,14 @@
+#include "Hooks.h"
+
+typedef void (*SetKeyCodeState_t) (IInputInternal*, KeyCode, bool);
+
+void Hooks::SetKeyCodeState(IInputInternal* thisptr, KeyCode code, bool pressed) {
+ // Get the original function and store it statically.
+ static SetKeyCodeState_t oSetKeyCodeState = inputinternal_hook->GetOriginalFunction(83);
+
+ // Print to console every time a key is pressed or released.
+ cvar->ConsoleColorPrintf(Color(150, 150, 255, 255), "IInputInternal::SetKeyCodeState - code: %i, pressed: %i\n", code, pressed);
+
+ // Call original 'IInputInternal::SetKeyCodeState'.
+ oSetKeyCodeState(thisptr, code, pressed);
+}
\ No newline at end of file
diff --git a/src/Hooks/SetMouseCodeState.cpp b/src/Hooks/SetMouseCodeState.cpp
new file mode 100644
index 0000000..bc2db9e
--- /dev/null
+++ b/src/Hooks/SetMouseCodeState.cpp
@@ -0,0 +1,14 @@
+#include "Hooks.h"
+
+typedef void (*SetMouseCodeState_t) (IInputInternal*, MouseCode, MouseCodeState_t);
+
+void Hooks::SetMouseCodeState(IInputInternal* thisptr, MouseCode code, MouseCodeState_t state) {
+ // Get the original function and store it statically.
+ static SetMouseCodeState_t oSetMouseCodeState = inputinternal_hook->GetOriginalFunction(84);
+
+ // Print to console every time a mouse button is clicked, double-clicked or released.
+ cvar->ConsoleColorPrintf(Color(150, 150, 255, 255), "IInputInternal::SetMouseCodeState - code: %i, state: %i\n", code, state);
+
+ // Call original 'IInputInternal::SetMouseCodeState'.
+ oSetMouseCodeState(thisptr, code, state);
+}
\ No newline at end of file
diff --git a/src/Hooks/ShowPixels.cpp b/src/Hooks/ShowPixels.cpp
new file mode 100644
index 0000000..f73042e
--- /dev/null
+++ b/src/Hooks/ShowPixels.cpp
@@ -0,0 +1,44 @@
+#include "Hooks.h"
+
+#include
+#include
+
+typedef void (*ShowPixels_t) (ILauncherMgr*, CShowPixelsParams*);
+
+void Hooks::ShowPixels(ILauncherMgr* thisptr, CShowPixelsParams* params) {
+ // Get the original function and store it statically.
+ static ShowPixels_t oShowPixels = sdl_hook->GetOriginalFunction(29);
+
+ if (!params->m_noBlit)
+ return oShowPixels(thisptr, params);
+
+ // Also store the game window, original and user contexts statically.
+ static SDL_Window* window = reinterpret_cast(launchermgr->GetWindowRef());
+
+ static PseudoGLContextPtr original_context = launchermgr->GetMainContext();
+ static PseudoGLContextPtr user_context = nullptr;
+
+ // Set up our context on first execution.
+ if (!user_context) {
+ user_context = launchermgr->CreateExtraContext();
+ ImGui_ImplSdl_Init(window);
+ }
+
+ // Switch to our context.
+ launchermgr->MakeContextCurrent(user_context);
+
+ // Start ImGui rendering.
+ ImGui_ImplSdl_NewFrame(window);
+
+ // Draw some test stuff.
+ ImGui::Text("Hello, world!");
+
+ // Finish ImGui rendering.
+ ImGui::Render();
+
+ // Switch back to the game context.
+ launchermgr->MakeContextCurrent(original_context);
+
+ // Call original 'ILauncherMgr::ShowPixels'.
+ oShowPixels(thisptr, params);
+}
\ No newline at end of file