├── .gitignore ├── .gitmodules ├── LICENSE ├── README.md ├── SDK ├── inc │ ├── enums.h │ ├── main.h │ ├── nativeCaller.h │ ├── natives.h │ └── types.h └── samples │ ├── ImguiTrainer.sln │ ├── ImguiTrainer │ ├── ImguiTrainer.vcxproj │ ├── ImguiTrainer.vcxproj.filters │ ├── keyboard.cpp │ ├── keyboard.h │ ├── main.cpp │ ├── script.cpp │ └── script.h │ ├── NativeTrainer.sln │ ├── NativeTrainer │ ├── NativeTrainer.vcxproj │ ├── NativeTrainer.vcxproj.filters │ ├── keyboard.cpp │ ├── keyboard.h │ ├── main.cpp │ ├── script.cpp │ └── script.h │ ├── Pools.sln │ └── Pools │ ├── Pools.vcxproj │ ├── Pools.vcxproj.filters │ ├── main.cpp │ ├── script.cpp │ └── script.h ├── ScriptHookV.sln └── ScriptHookV ├── ASI Loader ├── ASILoader.cpp └── ASILoader.h ├── DirectX ├── D3d11Hook.cpp └── D3d11Hook.h ├── Hooking ├── Hooking.cpp └── Hooking.h ├── Injector ├── Injection.cpp ├── Injection.h ├── Injector.rc.k ├── Injector.vcxproj ├── Injector.vcxproj.filters ├── NT Stuff.h ├── Resource.rc ├── icon.ico ├── main.cpp ├── registry.cpp ├── registry.h └── resource.h ├── Input ├── InputHook.cpp └── InputHook.h ├── LICENSE-ntauthority.txt ├── ScriptHookV.cpp ├── ScriptHookV.h ├── ScriptHookV.vcxproj ├── Scripting ├── HashMapData.h ├── NativeInvoker.cpp ├── NativeInvoker.h ├── Pools.cpp ├── Pools.h ├── ScriptEngine.cpp ├── ScriptEngine.h ├── ScriptManager.cpp ├── ScriptManager.h └── ScriptThread.h ├── StackWalker ├── include │ ├── StackWalker.cpp │ └── StackWalker.h └── lib │ ├── Debug │ ├── StackWalker.lib │ └── StackWalker.pdb │ └── Release │ └── StackWalker.lib ├── Utility ├── General.cpp ├── General.h ├── Log.cpp ├── Log.h ├── PEImage.cpp ├── PEImage.h ├── Pattern.h ├── Versioning.cpp └── Versioning.h ├── detours ├── include │ ├── detours.h │ └── detver.h ├── lib.X64 │ ├── detours.lib │ └── detours.pdb └── src │ ├── Makefile │ ├── creatwth.cpp │ ├── detours.cpp │ ├── detours.h │ ├── detver.h │ ├── disasm.cpp │ ├── image.cpp │ ├── modules.cpp │ └── uimports.cpp └── packages.config /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.sln.docstates 8 | 9 | # Build results 10 | 11 | [Dd]ebug/ 12 | [Rr]elease/ 13 | build/ 14 | [Bb]in/ 15 | [Oo]bj/ 16 | 17 | # Enable "build/" folder in the NuGet Packages folder since NuGet packages use it for MSBuild targets 18 | !packages/*/build/ 19 | 20 | # MSTest test Results 21 | [Tt]est[Rr]esult*/ 22 | [Bb]uild[Ll]og.* 23 | 24 | *_i.c 25 | *_p.c 26 | *.ilk 27 | *.meta 28 | *.obj 29 | *.pch 30 | *.pdb 31 | *.pgc 32 | *.pgd 33 | *.rsp 34 | *.sbr 35 | *.tlb 36 | *.tli 37 | *.tlh 38 | *.tmp 39 | *.tmp_proj 40 | *.log 41 | *.vspscc 42 | *.vssscc 43 | .builds 44 | *.pidb 45 | *.log 46 | *.scc 47 | *.rar 48 | 49 | # Visual C++ cache files 50 | ipch/ 51 | *.aps 52 | *.ncb 53 | *.opensdf 54 | *.sdf 55 | *.cachefile 56 | 57 | # Visual Studio profiler 58 | *.psess 59 | *.vsp 60 | *.vspx 61 | 62 | # Guidance Automation Toolkit 63 | *.gpState 64 | 65 | # ReSharper is a .NET coding add-in 66 | _ReSharper*/ 67 | *.[Rr]e[Ss]harper 68 | 69 | # TeamCity is a build add-in 70 | _TeamCity* 71 | 72 | # DotCover is a Code Coverage Tool 73 | *.dotCover 74 | 75 | # NCrunch 76 | *.ncrunch* 77 | .*crunch*.local.xml 78 | 79 | # Installshield output folder 80 | [Ee]xpress/ 81 | 82 | # DocProject is a documentation generator add-in 83 | DocProject/buildhelp/ 84 | DocProject/Help/*.HxT 85 | DocProject/Help/*.HxC 86 | DocProject/Help/*.hhc 87 | DocProject/Help/*.hhk 88 | DocProject/Help/*.hhp 89 | DocProject/Help/Html2 90 | DocProject/Help/html 91 | 92 | # Click-Once directory 93 | publish/ 94 | 95 | # Publish Web Output 96 | *.Publish.xml 97 | 98 | # NuGet Packages Directory 99 | ## TODO: If you have NuGet Package Restore enabled, uncomment the next line 100 | #packages/ 101 | 102 | # Windows Azure Build Output 103 | csx 104 | *.build.csdef 105 | 106 | # Windows Store app package directory 107 | AppPackages/ 108 | 109 | # Others 110 | sql/ 111 | *.Cache 112 | ClientBin/ 113 | [Ss]tyle[Cc]op.* 114 | ~$* 115 | *~ 116 | *.dbmdl 117 | *.[Pp]ublish.xml 118 | *.pfx 119 | *.publishsettings 120 | 121 | # RIA/Silverlight projects 122 | Generated_Code/ 123 | 124 | # Backup & report files from converting an old project file to a newer 125 | # Visual Studio version. Backup files are not needed, because we have git ;-) 126 | _UpgradeReport_Files/ 127 | Backup*/ 128 | UpgradeLog*.XML 129 | UpgradeLog*.htm 130 | 131 | # SQL Server files 132 | App_Data/*.mdf 133 | App_Data/*.ldf 134 | 135 | 136 | #LightSwitch generated files 137 | GeneratedArtifacts/ 138 | _Pvt_Extensions/ 139 | ModelManifest.xml 140 | 141 | # ========================= 142 | # Windows detritus 143 | # ========================= 144 | 145 | # Windows image file caches 146 | Thumbs.db 147 | ehthumbs.db 148 | 149 | # Folder config file 150 | Desktop.ini 151 | 152 | # Recycle Bin used on file shares 153 | $RECYCLE.BIN/ 154 | 155 | # Mac desktop service store files 156 | .DS_Store 157 | *.opendb 158 | *.db 159 | packages 160 | *.db-shm 161 | *.db-wal 162 | /SDK/lib/ScriptHookV.lib 163 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "SDK/samples/ImguiTrainer/imgui"] 2 | path = SDK/samples/ImguiTrainer/imgui 3 | url = https://github.com/ocornut/imgui.git 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ScriptHookV 2 | - ScriptHookV is a standalone script hook for Grand Theft Auto V. 3 | 4 | ## Features 5 | - Custom *.asi loader which is compatible with existing GTA:V mods 6 | - Ability to create standalone mods/scripts 7 | - in addition to the imports in the original ScriptHook by Alexander Blade 8 | we can 'changeScriptThread' | registerRawStreamingFile 9 | 10 | ## Usage 11 | - *.asi scripts will load from an /asi directory directly from where you inject this dll, 12 | or alternatively directly from the GTAV directory itself. 13 | - You can unload all loaded *.asi using PageUp_key, Reload them all using PageDown_key. 14 | - For Developers of ScriptHook itself you can unload the whole hook using End_key. 15 | 16 | ## Credits 17 | - [NTAuthority/citizenMP](http://tohjo.eu/citidev/citizenmp) Some inspiration taken from these guys but entirely rewritten. 18 | - [Alexander Blade](http://www.dev-c.com/) For his ScriptHookV SDK files which can also be used with our ScriptHookV. 19 | - [Brick] For his Memory Class / joaat function and advice. 20 | -------------------------------------------------------------------------------- /SDK/inc/main.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #define IMPORT __declspec(dllimport) 7 | 8 | /*Input*/ 9 | typedef void(*TWndProcFn)(UINT, WPARAM, LPARAM); 10 | IMPORT void WndProcHandlerRegister(TWndProcFn handler); 11 | IMPORT void WndProcHandlerUnregister(TWndProcFn handler); 12 | 13 | /* keyboard */ 14 | typedef void(*KeyboardHandler)(DWORD, WORD, BYTE, BOOL, BOOL, BOOL, BOOL); 15 | IMPORT void keyboardHandlerRegister(KeyboardHandler handler); 16 | IMPORT void keyboardHandlerUnregister(KeyboardHandler handler); 17 | 18 | /* D3d SwapChain */ 19 | typedef void(*PresentCallback)(void *); 20 | IMPORT void presentCallbackRegister(PresentCallback cb); 21 | IMPORT void presentCallbackUnregister(PresentCallback cb); 22 | 23 | /* textures */ 24 | IMPORT int createTexture(char *texFileName); 25 | IMPORT void drawTexture(int id, int index, int level, int time, 26 | float sizeX, float sizeY, float centerX, float centerY, 27 | float posX, float posY, float rotation, float screenHeightScaleFactor, 28 | float r, float g, float b, float a); 29 | 30 | /* scripts */ 31 | IMPORT void changeScriptThread(UINT32 hash); 32 | IMPORT void scriptWait(DWORD time); 33 | IMPORT void scriptRegister(HMODULE module, void(*LP_SCRIPT_MAIN)()); 34 | IMPORT void scriptRegisterAdditionalThread(HMODULE module, void(*LP_SCRIPT_MAIN)()); 35 | IMPORT void scriptUnregister(HMODULE module); 36 | IMPORT void scriptUnregister(void(*LP_SCRIPT_MAIN)()); // deprecated 37 | IMPORT void nativeInit(UINT64 hash); 38 | IMPORT void nativePush64(UINT64 val); 39 | IMPORT PUINT64 nativeCall(); 40 | 41 | /* Functions */ 42 | static void WAIT(DWORD time) { scriptWait(time); } 43 | static void TERMINATE() { WAIT(MAXDWORD); } 44 | 45 | /* global variables */ 46 | IMPORT UINT64 *getGlobalPtr(int globalId); 47 | 48 | /* World Pools */ 49 | IMPORT int worldGetAllVehicles(int *arr, int arrSize); 50 | IMPORT int worldGetAllPeds(int *arr, int arrSize); 51 | IMPORT int worldGetAllObjects(int *arr, int arrSize); 52 | IMPORT int worldGetAllPickups(int *arr, int arrSize); 53 | 54 | /* game version */ 55 | IMPORT int getGameVersion(); 56 | 57 | /* misc */ 58 | IMPORT BYTE *getScriptHandleBaseAddress(int handle); 59 | IMPORT int registerRawStreamingFile(const std::string& fileName, const std::string& registerAs); -------------------------------------------------------------------------------- /SDK/inc/natives.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Give-Two/ScriptHookV/11b97e8933f5eb219102992910be5a94087354d6/SDK/inc/natives.h -------------------------------------------------------------------------------- /SDK/inc/types.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | typedef DWORD Void; 6 | typedef DWORD Any; 7 | typedef DWORD uint; 8 | typedef DWORD Hash; 9 | typedef int Entity; 10 | typedef int Player; 11 | typedef int FireId; 12 | typedef int Ped; 13 | typedef int Vehicle; 14 | typedef int Cam; 15 | typedef int CarGenerator; 16 | typedef int Group; 17 | typedef int Train; 18 | typedef int Pickup; 19 | typedef int Object; 20 | typedef int Weapon; 21 | typedef int Interior; 22 | typedef int Blip; 23 | typedef int Texture; 24 | typedef int TextureDict; 25 | typedef int CoverPoint; 26 | typedef int Camera; 27 | typedef int TaskSequence; 28 | typedef int ColourIndex; 29 | typedef int Sphere; 30 | typedef int ScrHandle; 31 | 32 | #define PI 3.141592653589793238462643383279502884L 33 | 34 | struct Vector2 35 | { 36 | float x, y; 37 | 38 | Vector2() 39 | : x(0.f) 40 | , y(0.f) 41 | { } 42 | 43 | Vector2(float x, float y) 44 | : x(x) 45 | , y(y) 46 | { } 47 | }; 48 | 49 | struct Vector3 50 | { 51 | public: 52 | alignas(8) float x; 53 | alignas(8) float y; 54 | alignas(8) float z; 55 | 56 | public: 57 | Vector3() 58 | : x(0.f) 59 | , y(0.f) 60 | , z(0.f) 61 | { } 62 | 63 | Vector3(float x, float y, float z) 64 | : x(x) 65 | , y(y) 66 | , z(z) 67 | { } 68 | 69 | Vector3(float arr[3]) 70 | : x(arr[0]) 71 | , y(arr[1]) 72 | , z(arr[2]) 73 | { } 74 | }; 75 | 76 | struct Vector4 77 | { 78 | float x; 79 | float y; 80 | float z; 81 | float w; 82 | 83 | Vector4() 84 | : x(0.f) 85 | , y(0.f) 86 | , z(0.f) 87 | , w(0.f) 88 | { } 89 | 90 | Vector4(float x, float y, float z, float w) 91 | : x(x) 92 | , y(y) 93 | , z(z) 94 | , w(w) 95 | { } 96 | }; -------------------------------------------------------------------------------- /SDK/samples/ImguiTrainer.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2013 4 | VisualStudioVersion = 12.0.30723.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ImguiTrainer", "ImguiTrainer\ImguiTrainer.vcxproj", "{8D82F34A-1D64-465B-84B1-37F89AD3D20B}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Release|x64 = Release|x64 11 | EndGlobalSection 12 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 13 | {8D82F34A-1D64-465B-84B1-37F89AD3D20B}.Release|x64.ActiveCfg = Release|x64 14 | {8D82F34A-1D64-465B-84B1-37F89AD3D20B}.Release|x64.Build.0 = Release|x64 15 | EndGlobalSection 16 | GlobalSection(SolutionProperties) = preSolution 17 | HideSolutionNode = FALSE 18 | EndGlobalSection 19 | EndGlobal 20 | -------------------------------------------------------------------------------- /SDK/samples/ImguiTrainer/ImguiTrainer.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Release 6 | x64 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | {8D82F34A-1D64-465B-84B1-37F89AD3D20B} 32 | Win32Proj 33 | ImguiTrainer 34 | ImguiTrainer 35 | 10.0.16299.0 36 | 37 | 38 | 39 | DynamicLibrary 40 | false 41 | v141 42 | true 43 | MultiByte 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | false 54 | .asi 55 | bin\$(Configuration)\ 56 | tmp\$(Configuration)\ 57 | 58 | 59 | 60 | Level3 61 | 62 | 63 | MaxSpeed 64 | true 65 | true 66 | WIN32;NDEBUG;_WINDOWS;_USRDLL;ImguiTrainer_EXPORTS;%(PreprocessorDefinitions) 67 | MultiThreaded 68 | Fast 69 | $(ProjectDir)imgui;$(ProjectDir)imgui\examples\directx11_example;%(AdditionalIncludeDirectories) 70 | stdcpp17 71 | 72 | 73 | Windows 74 | false 75 | true 76 | true 77 | d3d11.lib;d3dcompiler.lib;dxgi.lib;imm32.lib;%(AdditionalDependencies) 78 | ..\..\lib\ScriptHookV.lib %(AdditionalOptions) 79 | 80 | 81 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /SDK/samples/ImguiTrainer/ImguiTrainer.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | include 16 | 17 | 18 | include 19 | 20 | 21 | include 22 | 23 | 24 | 25 | include 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | {fe82bd4a-2d14-486a-8be5-8bf6b50a2414} 35 | 36 | 37 | -------------------------------------------------------------------------------- /SDK/samples/ImguiTrainer/keyboard.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | THIS FILE IS A PART OF GTA V SCRIPT HOOK SDK 3 | http://dev-c.com 4 | (C) Alexander Blade 2015 5 | */ 6 | 7 | #include "keyboard.h" 8 | 9 | const int KEYS_SIZE = 255; 10 | 11 | struct { 12 | DWORD time; 13 | BOOL isWithAlt; 14 | BOOL wasDownBefore; 15 | BOOL isUpNow; 16 | } keyStates[KEYS_SIZE]; 17 | 18 | void OnKeyboardMessage(DWORD key, WORD repeats, BYTE scanCode, BOOL isExtended, BOOL isWithAlt, BOOL wasDownBefore, BOOL isUpNow) 19 | { 20 | if (key < KEYS_SIZE) 21 | { 22 | keyStates[key].time = GetTickCount(); 23 | keyStates[key].isWithAlt = isWithAlt; 24 | keyStates[key].wasDownBefore = wasDownBefore; 25 | keyStates[key].isUpNow = isUpNow; 26 | } 27 | } 28 | 29 | const int NOW_PERIOD = 100, MAX_DOWN = 5000; // ms 30 | 31 | bool IsKeyDown(DWORD key) 32 | { 33 | return (key < KEYS_SIZE) ? ((GetTickCount() < keyStates[key].time + MAX_DOWN) && !keyStates[key].isUpNow) : false; 34 | } 35 | 36 | bool IsKeyJustUp(DWORD key, bool exclusive) 37 | { 38 | bool b = (key < KEYS_SIZE) ? (GetTickCount() < keyStates[key].time + NOW_PERIOD && keyStates[key].isUpNow) : false; 39 | if (b && exclusive) 40 | ResetKeyState(key); 41 | return b; 42 | } 43 | 44 | void ResetKeyState(DWORD key) 45 | { 46 | if (key < KEYS_SIZE) 47 | memset(&keyStates[key], 0, sizeof(keyStates[0])); 48 | } -------------------------------------------------------------------------------- /SDK/samples/ImguiTrainer/keyboard.h: -------------------------------------------------------------------------------- 1 | /* 2 | THIS FILE IS A PART OF GTA V SCRIPT HOOK SDK 3 | http://dev-c.com 4 | (C) Alexander Blade 2015 5 | */ 6 | 7 | #pragma once 8 | 9 | #include "script.h" 10 | 11 | #define KeyState(key) GetAsyncKeyState(key) & 0x8000 12 | // parameters are the same as with aru's ScriptHook for IV 13 | void OnKeyboardMessage(DWORD key, WORD repeats, BYTE scanCode, BOOL isExtended, BOOL isWithAlt, BOOL wasDownBefore, BOOL isUpNow); 14 | bool IsKeyDown(DWORD key); 15 | bool IsKeyJustUp(DWORD key, bool exclusive = true); 16 | void ResetKeyState(DWORD key); -------------------------------------------------------------------------------- /SDK/samples/ImguiTrainer/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | THIS FILE IS A PART OF GTA V SCRIPT HOOK SDK 3 | http://dev-c.com 4 | (C) Alexander Blade 2015 5 | */ 6 | 7 | #include "..\..\inc\main.h" 8 | #include "script.h" 9 | #include "keyboard.h" 10 | 11 | BOOL APIENTRY DllMain(HMODULE hInstance, DWORD reason, LPVOID lpReserved) 12 | { 13 | switch (reason) 14 | { 15 | case DLL_PROCESS_ATTACH: 16 | scriptRegister(hInstance, ScriptMain); 17 | WndProcHandlerRegister(OnWndProcMessage); 18 | keyboardHandlerRegister(OnKeyboardMessage); 19 | presentCallbackRegister(PresentHook); 20 | break; 21 | case DLL_PROCESS_DETACH: 22 | scriptUnregister(hInstance); 23 | WndProcHandlerUnregister(OnWndProcMessage); 24 | keyboardHandlerUnregister(OnKeyboardMessage); 25 | presentCallbackUnregister(PresentHook); 26 | break; 27 | } 28 | return TRUE; 29 | } -------------------------------------------------------------------------------- /SDK/samples/ImguiTrainer/script.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Give-Two/ScriptHookV/11b97e8933f5eb219102992910be5a94087354d6/SDK/samples/ImguiTrainer/script.cpp -------------------------------------------------------------------------------- /SDK/samples/ImguiTrainer/script.h: -------------------------------------------------------------------------------- 1 | /* 2 | THIS FILE IS A PART OF GTA V SCRIPT HOOK SDK 3 | http://dev-c.com 4 | (C) Alexander Blade 2015 5 | */ 6 | 7 | #pragma once 8 | 9 | #define WIN32_LEAN_AND_MEAN 10 | #ifndef NOMINMAX 11 | #define NOMINMAX 12 | #endif //NOMINMAX 13 | 14 | #include "..\..\inc\natives.h" 15 | #include "..\..\inc\types.h" 16 | #include "..\..\inc\enums.h" 17 | 18 | #include "..\..\inc\main.h" 19 | 20 | #include 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | #include 34 | #include 35 | #include 36 | #include 37 | 38 | void ScriptMain(); 39 | void PresentHook(void *swapChain); 40 | void OnWndProcMessage(UINT uMsg, WPARAM wParam, LPARAM lParam); 41 | 42 | void CallOnResult(const std::function& result, const std::function& call); 43 | extern std::deque> g_nativeQueue; 44 | #define NQ_ g_nativeQueue.push_back([&] { 45 | #define _NQ }); 46 | 47 | namespace utils 48 | { 49 | constexpr unsigned char ToLowerLookupTable[256] = 50 | { 51 | 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 52 | 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 53 | 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 54 | 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 55 | 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 56 | 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x5B, 0x2F, 0x5D, 0x5E, 0x5F, 57 | 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 58 | 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F, 59 | 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 60 | 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F, 61 | 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 62 | 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 63 | 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 64 | 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, 65 | 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, 66 | 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF, 67 | }; 68 | 69 | constexpr std::uint32_t joaatc(const char* string, std::size_t length) 70 | { 71 | std::uint32_t hash = 0; 72 | 73 | for (std::size_t i = 0; i < length; ++i) 74 | { 75 | hash = static_cast(hash) + ToLowerLookupTable[string[i]]; 76 | hash = static_cast(hash) + (hash << 10); 77 | hash = static_cast(hash) ^ (hash >> 6); 78 | } 79 | 80 | hash = static_cast(hash) + (hash << 3); 81 | hash = static_cast(hash) ^ (hash >> 11); 82 | hash = static_cast(hash) + (hash << 15); 83 | 84 | return hash; 85 | } 86 | 87 | /* String */ 88 | template 89 | T process_arg(T value) noexcept 90 | { 91 | return value; 92 | } 93 | 94 | template 95 | std::string string_format(const std::string& format, Args const & ... args) 96 | { 97 | const auto fmt = format.c_str(); 98 | const size_t size = std::snprintf(nullptr, 0, fmt, process_arg(args) ...) + 1; 99 | auto buf = std::make_unique(size); 100 | std::snprintf(buf.get(), size, fmt, process_arg(args) ...); 101 | auto res = std::string(buf.get(), buf.get() + size - 1); 102 | return res; 103 | } 104 | } 105 | 106 | constexpr std::uint32_t operator""_joaat(const char* string, std::size_t length) 107 | { 108 | return utils::joaatc(string, length); 109 | } 110 | 111 | #define FMT(FM, ...) \ 112 | ( false \ 113 | ? std::to_string(printf(FM, ##__VA_ARGS__)) \ 114 | : utils::string_format(FM, ##__VA_ARGS__ ) \ 115 | ) -------------------------------------------------------------------------------- /SDK/samples/NativeTrainer.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2013 4 | VisualStudioVersion = 12.0.30723.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NativeTrainer", "NativeTrainer\NativeTrainer.vcxproj", "{8D82F34A-1D64-465B-84B1-37F89AD3D20B}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Release|x64 = Release|x64 11 | EndGlobalSection 12 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 13 | {8D82F34A-1D64-465B-84B1-37F89AD3D20B}.Release|x64.ActiveCfg = Release|x64 14 | {8D82F34A-1D64-465B-84B1-37F89AD3D20B}.Release|x64.Build.0 = Release|x64 15 | EndGlobalSection 16 | GlobalSection(SolutionProperties) = preSolution 17 | HideSolutionNode = FALSE 18 | EndGlobalSection 19 | EndGlobal 20 | -------------------------------------------------------------------------------- /SDK/samples/NativeTrainer/NativeTrainer.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Release 6 | x64 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | {8D82F34A-1D64-465B-84B1-37F89AD3D20B} 24 | Win32Proj 25 | NativeTrainer 26 | NativeTrainer 27 | 10.0.15063.0 28 | 29 | 30 | 31 | DynamicLibrary 32 | false 33 | v141 34 | true 35 | MultiByte 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | false 46 | .asi 47 | bin\$(Configuration)\ 48 | tmp\$(Configuration)\ 49 | 50 | 51 | 52 | Level3 53 | 54 | 55 | MaxSpeed 56 | true 57 | true 58 | WIN32;NDEBUG;_WINDOWS;_USRDLL;NativeTrainer_EXPORTS;%(PreprocessorDefinitions) 59 | MultiThreaded 60 | Fast 61 | 62 | 63 | Windows 64 | false 65 | true 66 | true 67 | ..\..\lib\ScriptHookV.lib %(AdditionalOptions) 68 | 69 | 70 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /SDK/samples/NativeTrainer/NativeTrainer.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | include 12 | 13 | 14 | include 15 | 16 | 17 | include 18 | 19 | 20 | 21 | include 22 | 23 | 24 | 25 | 26 | {fe82bd4a-2d14-486a-8be5-8bf6b50a2414} 27 | 28 | 29 | -------------------------------------------------------------------------------- /SDK/samples/NativeTrainer/keyboard.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | THIS FILE IS A PART OF GTA V SCRIPT HOOK SDK 3 | http://dev-c.com 4 | (C) Alexander Blade 2015 5 | */ 6 | 7 | #include "keyboard.h" 8 | 9 | const int KEYS_SIZE = 255; 10 | 11 | struct { 12 | DWORD time; 13 | BOOL isWithAlt; 14 | BOOL wasDownBefore; 15 | BOOL isUpNow; 16 | } keyStates[KEYS_SIZE]; 17 | 18 | void OnKeyboardMessage(DWORD key, WORD repeats, BYTE scanCode, BOOL isExtended, BOOL isWithAlt, BOOL wasDownBefore, BOOL isUpNow) 19 | { 20 | if (key < KEYS_SIZE) 21 | { 22 | keyStates[key].time = GetTickCount(); 23 | keyStates[key].isWithAlt = isWithAlt; 24 | keyStates[key].wasDownBefore = wasDownBefore; 25 | keyStates[key].isUpNow = isUpNow; 26 | } 27 | } 28 | 29 | const int NOW_PERIOD = 100, MAX_DOWN = 5000; // ms 30 | 31 | bool IsKeyDown(DWORD key) 32 | { 33 | return (key < KEYS_SIZE) ? ((GetTickCount() < keyStates[key].time + MAX_DOWN) && !keyStates[key].isUpNow) : false; 34 | } 35 | 36 | bool IsKeyJustUp(DWORD key, bool exclusive) 37 | { 38 | bool b = (key < KEYS_SIZE) ? (GetTickCount() < keyStates[key].time + NOW_PERIOD && keyStates[key].isUpNow) : false; 39 | if (b && exclusive) 40 | ResetKeyState(key); 41 | return b; 42 | } 43 | 44 | void ResetKeyState(DWORD key) 45 | { 46 | if (key < KEYS_SIZE) 47 | memset(&keyStates[key], 0, sizeof(keyStates[0])); 48 | } -------------------------------------------------------------------------------- /SDK/samples/NativeTrainer/keyboard.h: -------------------------------------------------------------------------------- 1 | /* 2 | THIS FILE IS A PART OF GTA V SCRIPT HOOK SDK 3 | http://dev-c.com 4 | (C) Alexander Blade 2015 5 | */ 6 | 7 | #pragma once 8 | 9 | #include 10 | 11 | // parameters are the same as with aru's ScriptHook for IV 12 | void OnKeyboardMessage(DWORD key, WORD repeats, BYTE scanCode, BOOL isExtended, BOOL isWithAlt, BOOL wasDownBefore, BOOL isUpNow); 13 | 14 | bool IsKeyDown(DWORD key); 15 | bool IsKeyJustUp(DWORD key, bool exclusive = true); 16 | void ResetKeyState(DWORD key); -------------------------------------------------------------------------------- /SDK/samples/NativeTrainer/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | THIS FILE IS A PART OF GTA V SCRIPT HOOK SDK 3 | http://dev-c.com 4 | (C) Alexander Blade 2015 5 | */ 6 | 7 | #include "..\..\inc\main.h" 8 | #include "script.h" 9 | #include "keyboard.h" 10 | 11 | BOOL APIENTRY DllMain(HMODULE hInstance, DWORD reason, LPVOID lpReserved) 12 | { 13 | switch (reason) 14 | { 15 | case DLL_PROCESS_ATTACH: 16 | scriptRegister(hInstance, ScriptMain); 17 | keyboardHandlerRegister(OnKeyboardMessage); 18 | break; 19 | case DLL_PROCESS_DETACH: 20 | scriptUnregister(hInstance); 21 | keyboardHandlerUnregister(OnKeyboardMessage); 22 | break; 23 | } 24 | return TRUE; 25 | } -------------------------------------------------------------------------------- /SDK/samples/NativeTrainer/script.h: -------------------------------------------------------------------------------- 1 | /* 2 | THIS FILE IS A PART OF GTA V SCRIPT HOOK SDK 3 | http://dev-c.com 4 | (C) Alexander Blade 2015 5 | */ 6 | 7 | #pragma once 8 | 9 | #include "..\..\inc\natives.h" 10 | #include "..\..\inc\types.h" 11 | #include "..\..\inc\enums.h" 12 | 13 | #include "..\..\inc\main.h" 14 | 15 | void ScriptMain(); -------------------------------------------------------------------------------- /SDK/samples/Pools.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2013 4 | VisualStudioVersion = 12.0.30723.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Pools", "Pools\Pools.vcxproj", "{8D82F34A-1D64-465B-84B1-37F89AD3D20B}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Release|x64 = Release|x64 11 | EndGlobalSection 12 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 13 | {8D82F34A-1D64-465B-84B1-37F89AD3D20B}.Release|x64.ActiveCfg = Release|x64 14 | {8D82F34A-1D64-465B-84B1-37F89AD3D20B}.Release|x64.Build.0 = Release|x64 15 | EndGlobalSection 16 | GlobalSection(SolutionProperties) = preSolution 17 | HideSolutionNode = FALSE 18 | EndGlobalSection 19 | EndGlobal 20 | -------------------------------------------------------------------------------- /SDK/samples/Pools/Pools.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Release 6 | x64 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | {8D82F34A-1D64-465B-84B1-37F89AD3D20B} 22 | Win32Proj 23 | Pools 24 | Pools 25 | 10.0.15063.0 26 | 27 | 28 | 29 | DynamicLibrary 30 | false 31 | v141 32 | true 33 | MultiByte 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | false 44 | .asi 45 | bin\$(Configuration)\ 46 | tmp\$(Configuration)\ 47 | 48 | 49 | 50 | Level3 51 | 52 | 53 | MaxSpeed 54 | true 55 | true 56 | WIN32;NDEBUG;_WINDOWS;_USRDLL;Pools_EXPORTS;%(PreprocessorDefinitions) 57 | MultiThreaded 58 | Fast 59 | 60 | 61 | Windows 62 | false 63 | true 64 | true 65 | ..\..\lib\ScriptHookV.lib %(AdditionalOptions) 66 | 67 | 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /SDK/samples/Pools/Pools.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | include 10 | 11 | 12 | include 13 | 14 | 15 | include 16 | 17 | 18 | 19 | include 20 | 21 | 22 | 23 | 24 | {5d58942b-ebbf-4d0a-9526-359e3a556796} 25 | 26 | 27 | -------------------------------------------------------------------------------- /SDK/samples/Pools/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | THIS FILE IS A PART OF GTA V SCRIPT HOOK SDK 3 | http://dev-c.com 4 | (C) Alexander Blade 2015 5 | */ 6 | 7 | #include "..\..\inc\main.h" 8 | #include "script.h" 9 | 10 | BOOL APIENTRY DllMain(HMODULE hInstance, DWORD reason, LPVOID lpReserved) 11 | { 12 | switch (reason) 13 | { 14 | case DLL_PROCESS_ATTACH: 15 | scriptRegister(hInstance, ScriptMain); 16 | break; 17 | case DLL_PROCESS_DETACH: 18 | scriptUnregister(hInstance); 19 | break; 20 | } 21 | return TRUE; 22 | } -------------------------------------------------------------------------------- /SDK/samples/Pools/script.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | THIS FILE IS A PART OF GTA V SCRIPT HOOK SDK 3 | http://dev-c.com 4 | (C) Alexander Blade 2015 5 | */ 6 | 7 | #include "script.h" 8 | #include 9 | 10 | DWORD vehUpdateTime; 11 | DWORD pedUpdateTime; 12 | 13 | void update() 14 | { 15 | // we don't want to mess with missions in this example 16 | if (GAMEPLAY::GET_MISSION_FLAG()) 17 | return; 18 | 19 | Player player = PLAYER::PLAYER_ID(); 20 | Ped playerPed = PLAYER::PLAYER_PED_ID(); 21 | 22 | // check if player ped exists and control is on (e.g. not in a cutscene) 23 | if (!ENTITY::DOES_ENTITY_EXIST(playerPed) || !PLAYER::IS_PLAYER_CONTROL_ON(player)) 24 | return; 25 | 26 | // get all vehicles 27 | const int ARR_SIZE = 1024; 28 | Vehicle vehicles[ARR_SIZE]; 29 | int count = worldGetAllVehicles(vehicles, ARR_SIZE); 30 | 31 | // randomize all vehicle colours every 200 ms 32 | // setting only primary or secondary color per update 33 | if (vehUpdateTime + 200 < GetTickCount()) 34 | { 35 | vehUpdateTime = GetTickCount(); 36 | for (int i = 0; i < count; i++) 37 | { 38 | int primary = 0, secondary = 0; 39 | VEHICLE::GET_VEHICLE_COLOURS(vehicles[i], &primary, &secondary); 40 | if (rand() % 2) 41 | VEHICLE::SET_VEHICLE_COLOURS(vehicles[i], rand() % (VehicleColorBrushedGold + 1), secondary); 42 | else 43 | VEHICLE::SET_VEHICLE_COLOURS(vehicles[i], primary, rand() % (VehicleColorBrushedGold + 1)); 44 | } 45 | } 46 | 47 | /* 48 | // delete all vehicles 49 | for (int i = 0; i < count; i++) 50 | { 51 | if (!ENTITY::IS_ENTITY_A_MISSION_ENTITY(vehicles[i])) 52 | ENTITY::SET_ENTITY_AS_MISSION_ENTITY(vehicles[i], TRUE, TRUE); 53 | VEHICLE::DELETE_VEHICLE(&vehicles[i]); 54 | } 55 | */ 56 | 57 | // let's track all exising helis and planes and other vehicles in air 58 | for (int i = 0; i < count; i++) 59 | { 60 | Hash model = ENTITY::GET_ENTITY_MODEL(vehicles[i]); 61 | if (VEHICLE::IS_THIS_MODEL_A_HELI(model) || VEHICLE::IS_THIS_MODEL_A_PLANE(model) || ENTITY::IS_ENTITY_IN_AIR(vehicles[i])) 62 | { 63 | Vector3 v = ENTITY::GET_ENTITY_COORDS(vehicles[i], TRUE); 64 | float x, y; 65 | if (GRAPHICS::GET_SCREEN_COORD_FROM_WORLD_COORD(v.x, v.y, v.z, &x, &y)) 66 | { 67 | Vector3 plv = ENTITY::GET_ENTITY_COORDS(playerPed, TRUE); 68 | float dist = GAMEPLAY::GET_DISTANCE_BETWEEN_COORDS(plv.x, plv.y, plv.z, v.x, v.y, v.z, TRUE); 69 | // draw text if vehicle isn't close to the player 70 | if (dist > 15.0) 71 | { 72 | int health = ENTITY::GET_ENTITY_HEALTH(vehicles[i]); 73 | const char* name = VEHICLE::GET_DISPLAY_NAME_FROM_VEHICLE_MODEL(model); 74 | // print text in a box 75 | char text[256]; 76 | sprintf_s(text, "^\n%s\n| Height %.02f\n| Distance %.02f\n| Health %d", name, v.z, dist, health); 77 | UI::SET_TEXT_FONT(0); 78 | UI::SET_TEXT_SCALE(0.2, 0.2); 79 | UI::SET_TEXT_COLOUR(255, 255, 255, 255); 80 | UI::SET_TEXT_WRAP(0.0, 1.0); 81 | UI::SET_TEXT_CENTRE(0); 82 | UI::SET_TEXT_DROPSHADOW(0, 0, 0, 0, 0); 83 | UI::SET_TEXT_EDGE(1, 0, 0, 0, 205); 84 | UI::BEGIN_TEXT_COMMAND_DISPLAY_TEXT("STRING"); 85 | UI::ADD_TEXT_COMPONENT_SUBSTRING_PLAYER_NAME(text); 86 | UI::END_TEXT_COMMAND_DISPLAY_TEXT(x, y, 0); 87 | // box 88 | GRAPHICS::DRAW_RECT(x + 0.027f, y + 0.043f, 0.058f, 0.056f, 75, 75, 75, 75, 0); 89 | } 90 | } 91 | } 92 | } 93 | 94 | // get all peds 95 | Ped peds[ARR_SIZE]; 96 | count = worldGetAllPeds(peds, ARR_SIZE); 97 | 98 | // randmoize peds 99 | if (pedUpdateTime + 200 < GetTickCount()) 100 | { 101 | pedUpdateTime = GetTickCount(); 102 | for (int i = 0; i < count; i++) 103 | { 104 | // if (rand() % 2 != 0) continue; 105 | if (peds[i] != playerPed && PED::IS_PED_HUMAN(peds[i]) && !ENTITY::IS_ENTITY_DEAD(peds[i], 0)) 106 | { 107 | for (int component = 0; component < 12; component++) 108 | { 109 | if (rand() % 2 != 0) continue; 110 | for (int j = 0; j < 100; j++) 111 | { 112 | int drawable = rand() % 10; 113 | int texture = rand() % 10; 114 | if (PED::IS_PED_COMPONENT_VARIATION_VALID(peds[i], component, drawable, texture)) 115 | { 116 | PED::SET_PED_COMPONENT_VARIATION(peds[i], component, drawable, texture, 0); 117 | break; 118 | } 119 | } 120 | } 121 | } 122 | } 123 | } 124 | 125 | // get all objects 126 | Object objects[ARR_SIZE]; 127 | count = worldGetAllObjects(objects, ARR_SIZE); 128 | 129 | // mark objects on the screen around the player 130 | 131 | // there are lots of objects in some places so we need to 132 | // remove possibilty of text being drawn on top of another text 133 | // thats why we will check distance between text on screen 134 | std::vector> coordsOnScreen; 135 | for (int i = 0; i < count; i++) 136 | { 137 | Hash model = ENTITY::GET_ENTITY_MODEL(objects[i]); 138 | Vector3 v = ENTITY::GET_ENTITY_COORDS(objects[i], TRUE); 139 | float x, y; 140 | if (GRAPHICS::GET_SCREEN_COORD_FROM_WORLD_COORD(v.x, v.y, v.z, &x, &y)) 141 | { 142 | // select objects only around 143 | Vector3 plv = ENTITY::GET_ENTITY_COORDS(playerPed, TRUE); 144 | float dist = GAMEPLAY::GET_DISTANCE_BETWEEN_COORDS(plv.x, plv.y, plv.z, v.x, v.y, v.z, TRUE); 145 | if (dist < 200.0) 146 | { 147 | // check if the text fits on screen 148 | bool bFitsOnscreen = true; 149 | for (auto iter = coordsOnScreen.begin(); iter != coordsOnScreen.end(); iter++) 150 | { 151 | float textDist = sqrtf((iter->first - x)*(iter->first - x) + (iter->second - y)*(iter->second - y)); 152 | if (textDist < 0.05) 153 | { 154 | bFitsOnscreen = false; 155 | break; 156 | } 157 | } 158 | // if text doesn't fit then skip draw 159 | if (!bFitsOnscreen) continue; 160 | 161 | // add text coords to the vector 162 | coordsOnScreen.push_back({ x, y }); 163 | 164 | // print text in a box 165 | char text[256]; 166 | sprintf_s(text, "^\n%08X\n%.02f", model, dist); 167 | UI::SET_TEXT_FONT(0); 168 | UI::SET_TEXT_SCALE(0.2, 0.2); 169 | UI::SET_TEXT_COLOUR(200, 255, 200, 255); 170 | UI::SET_TEXT_WRAP(0.0, 1.0); 171 | UI::SET_TEXT_CENTRE(0); 172 | UI::SET_TEXT_DROPSHADOW(0, 0, 0, 0, 0); 173 | UI::SET_TEXT_EDGE(1, 0, 0, 0, 205); 174 | UI::BEGIN_TEXT_COMMAND_DISPLAY_TEXT("STRING"); 175 | UI::ADD_TEXT_COMPONENT_SUBSTRING_PLAYER_NAME(text); 176 | UI::END_TEXT_COMMAND_DISPLAY_TEXT(x, y, 0); 177 | // box 178 | GRAPHICS::DRAW_RECT(x + 0.017f, y + 0.029f, 0.04f, 0.032f, 20, 20, 20, 75, 0); 179 | } 180 | } 181 | } 182 | 183 | // get all pickups 184 | Pickup pickups[ARR_SIZE]; 185 | count = worldGetAllPickups(pickups, ARR_SIZE); 186 | 187 | // move pickups around the player 188 | for (int i = 0; i < count; i++) 189 | { 190 | Vector3 v = ENTITY::GET_ENTITY_COORDS(pickups[i], TRUE); 191 | Vector3 plv = ENTITY::GET_ENTITY_COORDS(playerPed, TRUE); 192 | float dist = GAMEPLAY::GET_DISTANCE_BETWEEN_COORDS(plv.x, plv.y, plv.z, v.x, v.y, v.z, TRUE); 193 | if (dist > 5.0) 194 | { 195 | ENTITY::SET_ENTITY_COORDS(pickups[i], plv.x, plv.y, plv.z, 0, 0, 0, FALSE); 196 | } 197 | 198 | else GRAPHICS::DRAW_MARKER(2, plv.x, plv.y, plv.z + 5.f, 0.0f, 0.0f, 0.0f, 180.0f, 0.0f, 0.0f, 0.75f, 0.75f, 0.75f, 204, 204, 1, 100, false, true, 2, false, false, false, false); 199 | } 200 | 201 | // let's add explosions to grenades in air, looks awesome ! 202 | DWORD mhash = 0x1152354B; // for grenade launcher use 0x741FD3C4 203 | for (int i = 0; i < count; i++) 204 | { 205 | Hash model = ENTITY::GET_ENTITY_MODEL(objects[i]); 206 | if (model == mhash && ENTITY::IS_ENTITY_IN_AIR(objects[i])) 207 | { 208 | Vector3 v = ENTITY::GET_ENTITY_COORDS(objects[i], TRUE); 209 | Vector3 plv = ENTITY::GET_ENTITY_COORDS(playerPed, TRUE); 210 | // make sure that explosion won't hurt the player 211 | float dist = GAMEPLAY::GET_DISTANCE_BETWEEN_COORDS(plv.x, plv.y, plv.z, v.x, v.y, v.z, TRUE); 212 | if (dist > 10.0) 213 | { 214 | // only 1/3 of expolsions will have the sound 215 | FIRE::ADD_EXPLOSION(v.x, v.y, v.z, ExplosionTypeGrenadeL, 1.0, rand() % 3 == 0, FALSE, 0.f, FALSE); 216 | } 217 | } 218 | } 219 | } 220 | 221 | void main() 222 | { 223 | while (true) 224 | { 225 | update(); 226 | WAIT(0); 227 | } 228 | } 229 | 230 | void ScriptMain() 231 | { 232 | srand(GetTickCount()); 233 | main(); 234 | } 235 | -------------------------------------------------------------------------------- /SDK/samples/Pools/script.h: -------------------------------------------------------------------------------- 1 | /* 2 | THIS FILE IS A PART OF GTA V SCRIPT HOOK SDK 3 | http://dev-c.com 4 | (C) Alexander Blade 2015 5 | */ 6 | 7 | #pragma once 8 | 9 | #include "..\..\inc\natives.h" 10 | #include "..\..\inc\types.h" 11 | #include "..\..\inc\enums.h" 12 | 13 | #include "..\..\inc\main.h" 14 | 15 | void ScriptMain(); -------------------------------------------------------------------------------- /ScriptHookV.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.26430.16 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ScriptHookV", "ScriptHookV\ScriptHookV.vcxproj", "{B77FAE3F-A179-425D-B361-64F125CC3168}" 7 | EndProject 8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Injector", "ScriptHookV\Injector\Injector.vcxproj", "{B113859C-0C89-47C5-A09D-DAC2DAE84A12}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Release|x64 = Release|x64 13 | EndGlobalSection 14 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 15 | {B77FAE3F-A179-425D-B361-64F125CC3168}.Release|x64.ActiveCfg = Release|x64 16 | {B77FAE3F-A179-425D-B361-64F125CC3168}.Release|x64.Build.0 = Release|x64 17 | {B113859C-0C89-47C5-A09D-DAC2DAE84A12}.Release|x64.ActiveCfg = Release|x64 18 | {B113859C-0C89-47C5-A09D-DAC2DAE84A12}.Release|x64.Build.0 = Release|x64 19 | EndGlobalSection 20 | GlobalSection(SolutionProperties) = preSolution 21 | HideSolutionNode = FALSE 22 | EndGlobalSection 23 | EndGlobal 24 | -------------------------------------------------------------------------------- /ScriptHookV/ASI Loader/ASILoader.cpp: -------------------------------------------------------------------------------- 1 | #include "ASILoader.h" 2 | #include "..\Utility\PEImage.h" 3 | 4 | using namespace Utility; 5 | 6 | void LoadPlugins(const std::string& asiSearchFolder) 7 | { 8 | const std::string asiSearchQuery = asiSearchFolder + "\\*.asi"; 9 | WIN32_FIND_DATAA fileData; 10 | HANDLE fileHandle = FindFirstFileA(asiSearchQuery.c_str(), &fileData); 11 | if (fileHandle != INVALID_HANDLE_VALUE) 12 | { 13 | do 14 | { 15 | const std::string pluginPath = asiSearchFolder + "\\" + fileData.cFileName; 16 | 17 | LOG_PRINT("Loading \"%s\"", pluginPath.c_str()); 18 | 19 | // Load Image 20 | if (HMODULE module = LoadLibraryA(pluginPath.c_str())) 21 | { 22 | LOG_PRINT("\tLoaded \"%s\" => 0x%p", fileData.cFileName, module); 23 | Utility::playwindowsSound("ding.wav"); 24 | } 25 | else 26 | { 27 | DWORD errorMessageID = ::GetLastError(); 28 | if (errorMessageID) 29 | { 30 | LPSTR messageBuffer = nullptr; 31 | size_t size = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, errorMessageID, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&messageBuffer, 0, NULL); 32 | std::string message(messageBuffer, size); 33 | //Free the buffer. 34 | LocalFree(messageBuffer); 35 | LOG_ERROR("\tFailed to load: %s", message.c_str()); 36 | } 37 | else LOG_ERROR("\tFailed to load"); 38 | Utility::playwindowsSound("chord.wav"); 39 | } 40 | 41 | } while (FindNextFileA(fileHandle, &fileData)); 42 | 43 | FindClose(fileHandle); 44 | } 45 | } 46 | 47 | void ASILoader::Initialize() 48 | { 49 | LOG_PRINT( "Loading *.asi plugins" ); 50 | 51 | std::string ScriptHookFolder = GetOurModuleFolder() + "\\asi"; 52 | std::string GtaVFolder = GetRunningExecutableFolder(); 53 | 54 | LoadPlugins(ScriptHookFolder); 55 | LoadPlugins(GtaVFolder); 56 | 57 | LOG_PRINT( "Finished loading *.asi plugins" ); 58 | } 59 | -------------------------------------------------------------------------------- /ScriptHookV/ASI Loader/ASILoader.h: -------------------------------------------------------------------------------- 1 | #ifndef __ASI_LOADER_H__ 2 | #define __ASI_LOADER_H__ 3 | 4 | #include "..\ScriptHookV.h" 5 | 6 | namespace ASILoader 7 | { 8 | void Initialize(); 9 | }; 10 | 11 | #endif // __ASI_LOADER_H__ -------------------------------------------------------------------------------- /ScriptHookV/DirectX/D3d11Hook.cpp: -------------------------------------------------------------------------------- 1 | // DX11Hook.cpp 2 | 3 | #include "D3d11Hook.h" 4 | #include "..\Hooking\Hooking.h" 5 | #include "..\Scripting\ScriptEngine.h" 6 | 7 | using namespace Hooking; 8 | 9 | DX11Hook g_D3DHook; 10 | 11 | //texture declariations 12 | std::unordered_map CreateTextureArray; 13 | struct ScriptTex { DXTEXTURE2D tex; int id; }; 14 | struct ReloadTex { int id; std::wstring name; }; 15 | std::vector DrawTextureArray; 16 | std::vector ReloadArray; 17 | int DrawTextureArrayIndex = 0; 18 | static Vector2 windowSize = Vector2(); 19 | //==================================================================================================================================================================== 20 | // Function hook stubs 21 | 22 | // IDXGISwapChain::Present 23 | DetourHook Detour_Present; 24 | HRESULT WINAPI Present(IDXGISwapChain* chain, UINT syncInterval, UINT flags) 25 | { 26 | if (g_HookState == HookStateRunning && !g_D3DHook.m_IsResizing) 27 | { 28 | if (g_D3DHook.m_pSwapchain == nullptr) 29 | { 30 | g_D3DHook.m_pSwapchain = chain; 31 | g_D3DHook.InitializeDevices(); 32 | } 33 | else 34 | { 35 | BOOL fullscreenState; 36 | if (SUCCEEDED(chain->GetFullscreenState(&fullscreenState, nullptr))) 37 | { 38 | if (fullscreenState != g_D3DHook.m_fullscreenState) 39 | { 40 | g_D3DHook.m_IsResizing = true; 41 | 42 | g_D3DHook.ReleaseDevices(false); 43 | 44 | g_D3DHook.m_fullscreenState = fullscreenState; 45 | 46 | Detour_Present(chain, syncInterval, flags); 47 | 48 | g_D3DHook.m_IsResizing = false; 49 | } 50 | 51 | } 52 | 53 | g_D3DHook.Draw(); 54 | } 55 | } 56 | 57 | return Detour_Present(chain, syncInterval, flags); 58 | } 59 | 60 | // IDXGISwapChain::ResizeBuffers 61 | DetourHook Detour_ResizeBuffers; 62 | HRESULT WINAPI ResizeBuffers(IDXGISwapChain* chain, UINT BufferCount, UINT Width, UINT Height, DXGI_FORMAT NewFormat, UINT SwapChainFlags) 63 | { 64 | if (g_HookState == HookStateRunning) 65 | { 66 | g_D3DHook.m_IsResizing = true; 67 | 68 | g_D3DHook.ReleaseDevices(false); 69 | 70 | Detour_ResizeBuffers(chain, BufferCount, Width, Height, NewFormat, SwapChainFlags); 71 | 72 | g_D3DHook.m_IsResizing = false; 73 | 74 | return HRESULT(); 75 | } 76 | 77 | return Detour_ResizeBuffers(chain, BufferCount, Width, Height, NewFormat, SwapChainFlags); 78 | } 79 | 80 | //==================================================================================================================================================================== 81 | //Ensure SwapChain Vtable and perform function hooks 82 | 83 | enum eSwapChainVtableIndices : int 84 | { 85 | SC_QUERYINTERFACE, 86 | SC_ADDREF, 87 | SC_RELEASE, 88 | SC_SETPRIVATEDATA, 89 | SC_SETPRIVATEDATAINTERFACE, 90 | SC_GETPRIVATEDATA, 91 | SC_GETPARENT, 92 | SC_GETDEVICE, 93 | SC_PRESENT, 94 | SC_GETBUFFER, 95 | SC_SETFULLSCREENSTATE, 96 | SC_GETFULLSCREENSTATE, 97 | SC_GETDESC, 98 | SC_RESIZEBUFFERS, 99 | SC_RESIZETARGET, 100 | SC_GETCONTAININGOUTPUT, 101 | SC_GETFRAMESTATISTICS, 102 | SC_GETLASTPRESENTCOUNT, 103 | }; 104 | 105 | bool DX11Hook::InitializeHooks() 106 | { 107 | HMODULE hD3D11DLL = 0; 108 | while (!hD3D11DLL) 109 | { 110 | hD3D11DLL = GetModuleHandle("d3d11.dll"); 111 | Sleep(100); 112 | } 113 | 114 | if (auto swapchain = rage::GetGtaSwapChain()) 115 | { 116 | PVOID* pVTable = *(PVOID**)swapchain; 117 | 118 | Detour_Present.Hook(RCast(Present, pVTable[SC_PRESENT]), &Present, "IDXGISwapChainPresent"); 119 | 120 | Detour_ResizeBuffers.Hook(RCast(ResizeBuffers, pVTable[SC_RESIZEBUFFERS]), &ResizeBuffers, "IDXGISwapChainResizeBuffers"); 121 | 122 | return true; 123 | } 124 | 125 | return false; 126 | } 127 | 128 | //==================================================================================================================================================================== 129 | //Device Initialization and drawing functions 130 | 131 | void DX11Hook::InitializeDevices() 132 | { 133 | if (m_pSwapchain) 134 | { 135 | //get device and context 136 | if (SUCCEEDED(m_pSwapchain->GetDevice(__uuidof(ID3D11Device), (void **)&m_pDevice))) 137 | { 138 | m_pSwapchain->GetDevice(__uuidof(m_pDevice), (void**)&m_pDevice); 139 | m_pDevice->GetImmediateContext(&m_pContext); 140 | 141 | m_pCommonState.reset(new CommonStates(m_pDevice)); 142 | m_pSpriteBatch.reset(new SpriteBatch(m_pContext)); 143 | m_pBatch.reset(new PrimitiveBatch(m_pContext)); 144 | m_stateSaver.reset(new StateSaver()); 145 | } 146 | 147 | // use the back buffer address to create the render target 148 | if (SUCCEEDED(m_pSwapchain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&m_pRenderTargetTexture))) 149 | { 150 | m_pDevice->CreateRenderTargetView(m_pRenderTargetTexture, NULL, &m_pRenderTargetView); 151 | m_pRenderTargetTexture->Release(); 152 | ReloadTextures(); 153 | } 154 | 155 | BOOL fullscreenState; 156 | if (SUCCEEDED(m_pSwapchain->GetFullscreenState(&fullscreenState, nullptr))) 157 | { 158 | m_fullscreenState = fullscreenState; 159 | windowSize = GetResolution(); 160 | } 161 | } 162 | } 163 | 164 | void DX11Hook::ReleaseDevices(bool unhook) 165 | { 166 | g_D3DHook.m_pRenderTargetTexture->Release(); 167 | Utility::SafeRelease(m_pRenderTargetTexture); 168 | g_D3DHook.m_pRenderTargetView->Release(); 169 | Utility::SafeRelease(m_pRenderTargetView); 170 | g_D3DHook.m_pContext->Release(); 171 | Utility::SafeRelease(m_pContext); 172 | g_D3DHook.m_pDevice->Release(); 173 | Utility::SafeRelease(m_pDevice); 174 | g_D3DHook.m_pSwapchain->Release(); 175 | Utility::SafeRelease(m_pSwapchain); 176 | m_stateSaver.release(); 177 | LOG_DEBUG("Unloaded D3DX11 Devices"); 178 | 179 | if (unhook) 180 | { 181 | Detour_ResizeBuffers.UnHook(); 182 | Detour_Present.UnHook(); 183 | } 184 | } 185 | 186 | void DX11Hook::Draw() 187 | { 188 | if (m_pSwapchain) 189 | { 190 | CreateTextures(); 191 | 192 | if (!DrawTextureArray.empty()) 193 | { 194 | m_pSpriteBatch->Begin(SpriteSortMode::SpriteSortMode_BackToFront, m_pCommonState->NonPremultiplied()); 195 | m_restoreState = m_stateSaver->saveCurrentState(m_pContext); 196 | m_pBatch->Begin(); 197 | 198 | for (auto& t : DrawTextureArray) 199 | { 200 | if (t.tex.bEnabled) t.tex.Draw(*m_pSpriteBatch); 201 | } 202 | 203 | m_pBatch->End(); 204 | m_pSpriteBatch->End(); 205 | 206 | if (m_restoreState) 207 | m_stateSaver->restoreSavedState(); 208 | } 209 | 210 | for (auto & function : m_PresentCallbacks) 211 | { 212 | m_restoreState = m_stateSaver->saveCurrentState(m_pContext); 213 | function(m_pSwapchain); 214 | if (m_restoreState) 215 | m_stateSaver->restoreSavedState(); 216 | } 217 | } 218 | } 219 | 220 | Vector2 DX11Hook::GetResolution() 221 | { 222 | D3D11_VIEWPORT vp; 223 | UINT nvp = 1; 224 | m_pContext->RSGetViewports(&nvp, &vp); 225 | return Vector2(vp.Width, vp.Height); 226 | } 227 | 228 | //==================================================================================================================================================================== 229 | //Custom Texture loading via WIC 230 | 231 | void DX11Hook::CreateTextures() 232 | { 233 | for (auto it = CreateTextureArray.begin(); it != CreateTextureArray.end(); ++it) 234 | { 235 | DXTEXTURE2D t; 236 | if (SUCCEEDED(CreateWICTextureFromFile(m_pDevice, it->second.c_str(), t.resource.GetAddressOf(), t.view.GetAddressOf(), 0))) 237 | { 238 | t.resource.As(&t.texture); 239 | t.texture->GetDesc(&t.desc); 240 | ScriptTex Temptex; 241 | Temptex.id = it->first; 242 | Temptex.tex = t; 243 | DrawTextureArray.push_back(Temptex); 244 | ReloadTex tempR; 245 | tempR.id = it->first; 246 | tempR.name = it->second; 247 | ReloadArray.push_back(tempR); 248 | } 249 | else 250 | { 251 | std::string string = Utility::wstr_to_str(it->second); 252 | LOG_ERROR("Unable to Load Texture %s = %d", string.c_str(), it->first); 253 | } 254 | } 255 | 256 | CreateTextureArray.clear(); 257 | } 258 | 259 | void DX11Hook::ReloadTextures() 260 | { 261 | for (auto it : ReloadArray) 262 | { 263 | DXTEXTURE2D t; 264 | if (SUCCEEDED(CreateWICTextureFromFile(m_pDevice, it.name.c_str(), t.resource.GetAddressOf(), t.view.GetAddressOf(), 0))) 265 | { 266 | t.resource.As(&t.texture); 267 | t.texture->GetDesc(&t.desc); 268 | ScriptTex Temptex; 269 | Temptex.id = it.id; 270 | Temptex.tex = t; 271 | DrawTextureArray.push_back(Temptex); 272 | } 273 | else 274 | { 275 | std::string string = Utility::wstr_to_str(it.name); 276 | LOG_ERROR("Unable to Load Texture %s = %d", string.c_str(), it.id); 277 | } 278 | } 279 | } 280 | 281 | int DX11Hook::CreateTexture(const char *texFileName) 282 | { 283 | // convert the filename from UTF-8... 284 | std::string fileNameStr = texFileName; 285 | std::wstring passedFileName = Utility::str_to_wstr(fileNameStr); 286 | std::wstring retFileName = passedFileName; 287 | 288 | // then, try finding the requested file. 289 | bool found = false; 290 | 291 | // absolute path 292 | if (passedFileName[1] == L':' || passedFileName[0] == '\\') 293 | { 294 | LOG_PRINT("File found %s", fileNameStr.c_str()); 295 | found = true; 296 | } 297 | 298 | // not found at all? 299 | if (!found) 300 | { 301 | LOG_ERROR("File not found %s", fileNameStr.c_str()); 302 | return -1; 303 | } 304 | 305 | DrawTextureArrayIndex++; 306 | CreateTextureArray[DrawTextureArrayIndex] = retFileName; 307 | return DrawTextureArrayIndex; 308 | } 309 | 310 | void DX11Hook::DrawTexture(int id, int index, int level, int time, float sizeX, float sizeY, float centerX, float centerY, float posX, float posY, float rotation, float screenHeightScaleFactor, float r, float g, float b, float a) 311 | { 312 | for (auto& t : DrawTextureArray) 313 | { 314 | if (t.id == id) 315 | t.tex.SetProperties(id, index, level, time, sizeX, sizeY, centerX, centerY, posX, posY, rotation, screenHeightScaleFactor, r, g, b, a); 316 | } 317 | } 318 | 319 | //==================================================================================================================================================================== 320 | //State Saver Class 321 | 322 | // Construct 323 | StateSaver::StateSaver() : 324 | m_savedState(false), 325 | m_featureLevel(D3D_FEATURE_LEVEL_11_0), 326 | m_pContext(NULL), 327 | m_primitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_UNDEFINED), 328 | m_pInputLayout(NULL), 329 | m_pBlendState(NULL), 330 | m_sampleMask(0xffffffff), 331 | m_pDepthStencilState(NULL), 332 | m_stencilRef(0), 333 | m_pRasterizerState(NULL), 334 | m_pPSSRV(NULL), 335 | m_pSamplerState(NULL), 336 | m_pVS(NULL), 337 | m_numVSClassInstances(0), 338 | m_pVSConstantBuffer(NULL), 339 | m_pGS(NULL), 340 | m_numGSClassInstances(0), 341 | m_pGSConstantBuffer(NULL), 342 | m_pGSSRV(NULL), 343 | m_pPS(NULL), 344 | m_numPSClassInstances(0), 345 | m_pHS(NULL), 346 | m_numHSClassInstances(0), 347 | m_pDS(NULL), 348 | m_numDSClassInstances(0), 349 | m_pVB(NULL), 350 | m_vertexStride(0), 351 | m_vertexOffset(0), 352 | m_pIndexBuffer(NULL), 353 | m_indexFormat(DXGI_FORMAT_UNKNOWN), 354 | m_indexOffset(0) 355 | { 356 | for (int i = 0; i < 4; ++i) 357 | { 358 | m_blendFactor[i] = 0.0f; 359 | } 360 | for (int i = 0; i < 256; ++i) 361 | { 362 | m_pVSClassInstances[i] = NULL; 363 | m_pGSClassInstances[i] = NULL; 364 | m_pPSClassInstances[i] = NULL; 365 | m_pHSClassInstances[i] = NULL; 366 | m_pDSClassInstances[i] = NULL; 367 | } 368 | } 369 | 370 | // Destruct 371 | StateSaver::~StateSaver() 372 | { 373 | releaseSavedState(); 374 | } 375 | 376 | // Save all states that are changed by the font-wrapper when drawing a string 377 | bool StateSaver::saveCurrentState(ID3D11DeviceContext *pContext) 378 | { 379 | if (m_savedState) releaseSavedState(); 380 | if (pContext == NULL) return false; 381 | 382 | ID3D11Device *pDevice; 383 | pContext->GetDevice(&pDevice); 384 | if (pDevice != NULL) 385 | { 386 | m_featureLevel = pDevice->GetFeatureLevel(); 387 | pDevice->Release(); 388 | } 389 | 390 | pContext->AddRef(); 391 | m_pContext = pContext; 392 | 393 | m_pContext->IAGetPrimitiveTopology(&m_primitiveTopology); 394 | m_pContext->IAGetInputLayout(&m_pInputLayout); 395 | 396 | m_pContext->OMGetBlendState(&m_pBlendState, m_blendFactor, &m_sampleMask); 397 | m_pContext->OMGetDepthStencilState(&m_pDepthStencilState, &m_stencilRef); 398 | 399 | m_pContext->RSGetState(&m_pRasterizerState); 400 | 401 | m_numVSClassInstances = 256; 402 | m_pContext->VSGetShader(&m_pVS, m_pVSClassInstances, &m_numVSClassInstances); 403 | m_pContext->VSGetConstantBuffers(0, 1, &m_pVSConstantBuffer); 404 | 405 | m_numPSClassInstances = 256; 406 | m_pContext->PSGetShader(&m_pPS, m_pPSClassInstances, &m_numPSClassInstances); 407 | m_pContext->PSGetShaderResources(0, 1, &m_pPSSRV); 408 | pContext->PSGetSamplers(0, 1, &m_pSamplerState); 409 | 410 | if (m_featureLevel >= D3D_FEATURE_LEVEL_10_0) 411 | { 412 | m_numGSClassInstances = 256; 413 | m_pContext->GSGetShader(&m_pGS, m_pGSClassInstances, &m_numGSClassInstances); 414 | m_pContext->GSGetConstantBuffers(0, 1, &m_pGSConstantBuffer); 415 | 416 | m_pContext->GSGetShaderResources(0, 1, &m_pGSSRV); 417 | 418 | if (m_featureLevel >= D3D_FEATURE_LEVEL_11_0) 419 | { 420 | m_numHSClassInstances = 256; 421 | m_pContext->HSGetShader(&m_pHS, m_pHSClassInstances, &m_numHSClassInstances); 422 | 423 | m_numDSClassInstances = 256; 424 | m_pContext->DSGetShader(&m_pDS, m_pDSClassInstances, &m_numDSClassInstances); 425 | } 426 | } 427 | 428 | m_pContext->IAGetVertexBuffers(0, 1, &m_pVB, &m_vertexStride, &m_vertexOffset); 429 | 430 | m_pContext->IAGetIndexBuffer(&m_pIndexBuffer, &m_indexFormat, &m_indexOffset); 431 | 432 | m_savedState = true; 433 | 434 | return true; 435 | } 436 | 437 | 438 | // Restore state 439 | bool StateSaver::restoreSavedState() 440 | { 441 | if (!m_savedState) return false; 442 | 443 | m_pContext->IASetPrimitiveTopology(m_primitiveTopology); 444 | m_pContext->IASetInputLayout(m_pInputLayout); 445 | 446 | m_pContext->OMSetBlendState(m_pBlendState, m_blendFactor, m_sampleMask); 447 | m_pContext->OMSetDepthStencilState(m_pDepthStencilState, m_stencilRef); 448 | 449 | m_pContext->RSSetState(m_pRasterizerState); 450 | 451 | m_pContext->VSSetShader(m_pVS, m_pVSClassInstances, m_numVSClassInstances); 452 | m_pContext->VSSetConstantBuffers(0, 1, &m_pVSConstantBuffer); 453 | 454 | m_pContext->PSSetShader(m_pPS, m_pPSClassInstances, m_numPSClassInstances); 455 | m_pContext->PSSetShaderResources(0, 1, &m_pPSSRV); 456 | m_pContext->PSSetSamplers(0, 1, &m_pSamplerState); 457 | 458 | if (m_featureLevel >= D3D_FEATURE_LEVEL_10_0) 459 | { 460 | m_pContext->GSSetShader(m_pGS, m_pGSClassInstances, m_numGSClassInstances); 461 | m_pContext->GSSetConstantBuffers(0, 1, &m_pGSConstantBuffer); 462 | 463 | m_pContext->GSSetShaderResources(0, 1, &m_pGSSRV); 464 | 465 | if (m_featureLevel >= D3D_FEATURE_LEVEL_11_0) 466 | { 467 | m_pContext->HSSetShader(m_pHS, m_pHSClassInstances, m_numHSClassInstances); 468 | 469 | m_pContext->DSSetShader(m_pDS, m_pDSClassInstances, m_numDSClassInstances); 470 | } 471 | } 472 | 473 | m_pContext->IASetVertexBuffers(0, 1, &m_pVB, &m_vertexStride, &m_vertexOffset); 474 | 475 | m_pContext->IASetIndexBuffer(m_pIndexBuffer, m_indexFormat, m_indexOffset); 476 | 477 | return true; 478 | } 479 | 480 | 481 | // Release state 482 | void StateSaver::releaseSavedState() 483 | { 484 | m_primitiveTopology = D3D11_PRIMITIVE_TOPOLOGY_UNDEFINED; 485 | Utility::SafeRelease(m_pInputLayout); 486 | Utility::SafeRelease(m_pBlendState); 487 | for (int i = 0; i < 4; ++i) 488 | m_blendFactor[i] = 0.0f; 489 | m_sampleMask = 0xffffffff; 490 | Utility::SafeRelease(m_pDepthStencilState); 491 | m_stencilRef = 0; 492 | Utility::SafeRelease(m_pRasterizerState); 493 | Utility::SafeRelease(m_pPSSRV); 494 | Utility::SafeRelease(m_pSamplerState); 495 | Utility::SafeRelease(m_pVS); 496 | for (UINT i = 0; i < m_numVSClassInstances; ++i) 497 | Utility::SafeRelease(m_pVSClassInstances[i]); 498 | m_numVSClassInstances = 0; 499 | Utility::SafeRelease(m_pVSConstantBuffer); 500 | Utility::SafeRelease(m_pGS); 501 | for (UINT i = 0; i < m_numGSClassInstances; ++i) 502 | Utility::SafeRelease(m_pGSClassInstances[i]); 503 | m_numGSClassInstances = 0; 504 | Utility::SafeRelease(m_pGSConstantBuffer); 505 | Utility::SafeRelease(m_pGSSRV); 506 | Utility::SafeRelease(m_pPS); 507 | for (UINT i = 0; i < m_numPSClassInstances; ++i) 508 | Utility::SafeRelease(m_pPSClassInstances[i]); 509 | m_numPSClassInstances = 0; 510 | Utility::SafeRelease(m_pHS); 511 | for (UINT i = 0; i < m_numHSClassInstances; ++i) 512 | Utility::SafeRelease(m_pHSClassInstances[i]); 513 | m_numHSClassInstances = 0; 514 | Utility::SafeRelease(m_pDS); 515 | for (UINT i = 0; i < m_numDSClassInstances; ++i) 516 | Utility::SafeRelease(m_pDSClassInstances[i]); 517 | m_numDSClassInstances = 0; 518 | Utility::SafeRelease(m_pVB); 519 | m_vertexStride = 0; 520 | m_vertexOffset = 0; 521 | Utility::SafeRelease(m_pIndexBuffer); 522 | m_indexFormat = DXGI_FORMAT_UNKNOWN; 523 | m_indexOffset = 0; 524 | 525 | Utility::SafeRelease(m_pContext); 526 | m_featureLevel = D3D_FEATURE_LEVEL_11_0; 527 | 528 | m_savedState = false; 529 | } 530 | -------------------------------------------------------------------------------- /ScriptHookV/DirectX/D3d11Hook.h: -------------------------------------------------------------------------------- 1 | #ifndef _DXHOOK_H_ 2 | #define _DXHOOK_H_ 3 | 4 | #include "..\..\SDK\inc\types.h" 5 | #include "..\ScriptHookV.h" 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | using namespace DirectX; 25 | using namespace Microsoft::WRL; 26 | 27 | typedef void(*PresentCallback)(void *); 28 | 29 | class StateSaver 30 | { 31 | // Public functions 32 | public: 33 | StateSaver(); 34 | ~StateSaver(); 35 | 36 | bool saveCurrentState(ID3D11DeviceContext *pContext); 37 | bool restoreSavedState(); 38 | void releaseSavedState(); 39 | 40 | // Internal data 41 | private: 42 | bool m_savedState; 43 | D3D_FEATURE_LEVEL m_featureLevel; 44 | ID3D11DeviceContext *m_pContext; 45 | D3D11_PRIMITIVE_TOPOLOGY m_primitiveTopology; 46 | ID3D11InputLayout *m_pInputLayout; 47 | ID3D11BlendState *m_pBlendState; 48 | FLOAT m_blendFactor[4]; 49 | UINT m_sampleMask; 50 | ID3D11DepthStencilState *m_pDepthStencilState; 51 | UINT m_stencilRef; 52 | ID3D11RasterizerState *m_pRasterizerState; 53 | ID3D11ShaderResourceView *m_pPSSRV; 54 | ID3D11SamplerState *m_pSamplerState; 55 | ID3D11VertexShader *m_pVS; 56 | ID3D11ClassInstance *m_pVSClassInstances[256]; 57 | UINT m_numVSClassInstances; 58 | ID3D11Buffer *m_pVSConstantBuffer; 59 | ID3D11GeometryShader *m_pGS; 60 | ID3D11ClassInstance *m_pGSClassInstances[256]; 61 | UINT m_numGSClassInstances; 62 | ID3D11Buffer *m_pGSConstantBuffer; 63 | ID3D11ShaderResourceView *m_pGSSRV; 64 | ID3D11PixelShader *m_pPS; 65 | ID3D11ClassInstance *m_pPSClassInstances[256]; 66 | UINT m_numPSClassInstances; 67 | ID3D11HullShader *m_pHS; 68 | ID3D11ClassInstance *m_pHSClassInstances[256]; 69 | UINT m_numHSClassInstances; 70 | ID3D11DomainShader *m_pDS; 71 | ID3D11ClassInstance *m_pDSClassInstances[256]; 72 | UINT m_numDSClassInstances; 73 | ID3D11Buffer *m_pVB; 74 | UINT m_vertexStride; 75 | UINT m_vertexOffset; 76 | ID3D11Buffer *m_pIndexBuffer; 77 | DXGI_FORMAT m_indexFormat; 78 | UINT m_indexOffset; 79 | 80 | StateSaver(const StateSaver&); 81 | }; 82 | 83 | class DX11Hook 84 | { 85 | public: 86 | DX11Hook() 87 | { } 88 | 89 | void Draw(); 90 | bool InitializeHooks(); 91 | void InitializeDevices(); 92 | void ReleaseDevices(bool unhook); 93 | 94 | Vector2 GetResolution(); 95 | int CreateTexture(const char *texFileName); 96 | void DrawTexture(int id, int index, int level, int time, float sizeX, float sizeY, float centerX, float centerY, float posX, float posY, float rotation, float screenHeightScaleFactor, float r, float g, float b, float a); 97 | bool AddCallback(PresentCallback callback) { return m_PresentCallbacks.insert(callback).second; } 98 | bool RemoveCallback(PresentCallback callback) { return m_PresentCallbacks.erase(callback) != 0; } 99 | void CreateTextures(); 100 | void ReloadTextures(); 101 | 102 | IDXGISwapChain* m_pSwapchain = nullptr; 103 | ID3D11Device* m_pDevice = nullptr; 104 | ID3D11DeviceContext* m_pContext = nullptr; 105 | ID3D11RenderTargetView* m_pRenderTargetView = nullptr; 106 | ID3D11Texture2D* m_pRenderTargetTexture = nullptr; 107 | std::set m_PresentCallbacks; 108 | 109 | std::unique_ptr> m_pBatch; 110 | std::unique_ptr m_pSpriteBatch; 111 | std::unique_ptr m_pCommonState; 112 | std::unique_ptr m_stateSaver; 113 | BOOL m_fullscreenState = -1; 114 | bool m_restoreState = false; 115 | bool m_IsResizing = false; 116 | }; 117 | 118 | extern DX11Hook g_D3DHook; 119 | 120 | class DXTEXTURE2D 121 | { 122 | private: 123 | int id; 124 | int index; 125 | int level; 126 | int time; 127 | float sizeX, sizeY; 128 | float centerX, centerY; 129 | float posX, posY; 130 | float rotation; 131 | float screenHeightScaleFactor; // Not used 132 | float r, g, b, a; 133 | public: 134 | bool bEnabled; 135 | DWORD64 disableTime; 136 | Microsoft::WRL::ComPtr view; 137 | Microsoft::WRL::ComPtr resource; 138 | Microsoft::WRL::ComPtr texture; 139 | CD3D11_TEXTURE2D_DESC desc; 140 | 141 | DXTEXTURE2D() : bEnabled(false), disableTime(0) 142 | { 143 | desc.Width = 256; 144 | desc.Height = 256; 145 | desc.MipLevels = 0; 146 | desc.ArraySize = 1; 147 | desc.Format = DXGI_FORMAT_UNKNOWN; 148 | desc.SampleDesc.Count = 1; 149 | desc.SampleDesc.Quality = 0; 150 | desc.Usage = D3D11_USAGE_DEFAULT; 151 | desc.BindFlags = (D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET); 152 | desc.CPUAccessFlags = 0; 153 | desc.MiscFlags = D3D11_RESOURCE_MISC_GENERATE_MIPS; 154 | } 155 | float scale_image(const float width, const float height, const float scalex, const float scaley) 156 | { 157 | float ret = 1.0f; 158 | if (width > height) 159 | ret = width * scalex; 160 | if (height > width) 161 | ret = height * scaley; 162 | return ret; 163 | } 164 | void Draw(DirectX::SpriteBatch& pSpriteBatch) 165 | { 166 | DirectX::XMVECTOR colour = { r,g,b,a }; 167 | pSpriteBatch.Draw(view.Get(), 168 | DirectX::XMFLOAT2(posX * g_D3DHook.GetResolution().x, posY * g_D3DHook.GetResolution().y), 169 | nullptr, 170 | colour, 171 | (rotation * 2 * float(PI)), 172 | DirectX::XMFLOAT2(centerX * desc.Width, centerY * desc.Height), 173 | scale_image(g_D3DHook.GetResolution().x / desc.Width, g_D3DHook.GetResolution().y / desc.Height, sizeX * 2, sizeY * 2), 174 | DirectX::SpriteEffects::SpriteEffects_None); 175 | //float(9 - (std::abs(index) % 10)) / 10); 176 | if (GetTickCount64() > disableTime) bEnabled = false; 177 | } 178 | 179 | void SetProperties(int id_, int index_, int level_, int time_, float sizeX_, float sizeY_, float centerX_, float centerY_, float posX_, float posY_, float rotation_, float screenHeightScaleFactor_, float r_, float g_, float b_, float a_) 180 | { 181 | bEnabled = true; 182 | id = id_; 183 | index = index_; 184 | level = level_; 185 | time = time_; 186 | sizeX = sizeX_; 187 | sizeY = sizeY_; 188 | centerX = centerX_; 189 | centerY = centerY_; 190 | posX = posX_; 191 | posY = posY_; 192 | rotation = rotation_; 193 | screenHeightScaleFactor = screenHeightScaleFactor_; 194 | r = r_; 195 | g = g_; 196 | b = b_; 197 | a = a_; 198 | disableTime = GetTickCount64() + time; 199 | } 200 | }; 201 | 202 | #endif //_DXHOOK_H_ 203 | -------------------------------------------------------------------------------- /ScriptHookV/Hooking/Hooking.cpp: -------------------------------------------------------------------------------- 1 | #include "Hooking.h" 2 | 3 | #include "..\Input\InputHook.h" 4 | 5 | #include "..\DirectX\D3d11Hook.h" 6 | 7 | #include "..\Scripting\ScriptEngine.h" 8 | #include "..\Scripting\NativeInvoker.h" 9 | #include "..\Scripting\ScriptThread.h" 10 | #include "..\Scripting\ScriptManager.h" 11 | 12 | using namespace Hooking; 13 | 14 | // Gta Natives 15 | 16 | // system::wait 17 | DetourHook Detour_System_Wait; 18 | void __fastcall System_Wait(scrNativeCallContext* context) 19 | { 20 | switch (g_HookState) 21 | { 22 | case HookStateRunning: 23 | { 24 | ScriptManager::MainFiber(); 25 | } break; 26 | 27 | case HookStateExiting: 28 | { 29 | ScriptManager::UnloadHook(); 30 | } break; 31 | 32 | default: 33 | break; 34 | } 35 | 36 | return Detour_System_Wait(context); 37 | } 38 | 39 | // Gta Functions 40 | 41 | // NativeRegistration 42 | DetourHook<__int64 __fastcall(__int64, __int64, __int64)> Detour_NativeRegistration; 43 | __int64 __fastcall NativeRegistration(__int64 a1, __int64 hash, __int64 address) 44 | { 45 | LOG_FILE("Native_Registration", "0x%016llx, 0x%08llx", hash, normalise_base(address, 0)); 46 | 47 | return Detour_NativeRegistration(a1, hash, address); 48 | } 49 | 50 | // Hooking - Functions 51 | 52 | std::uintptr_t Hooking::normalise_base(mem::handle address, const std::uintptr_t& offset) 53 | { 54 | auto module = mem::module::main(); 55 | 56 | if (module.contains(address)) 57 | { 58 | address = address.translate(module.base(), offset); 59 | } 60 | 61 | return address.as(); 62 | }; 63 | 64 | bool Hooking::HookFunctions() 65 | { 66 | if (g_GameVersion == -1) 67 | { 68 | return true 69 | && Detour_NativeRegistration.Hook("48 8B C4 48 89 58 08 48 89 68 18 48 89 70 20 48 89 50 10 57 48 83 EC 20 0F B6 C2"_Scan.as(), &NativeRegistration, "NativeRegistration") 70 | ; 71 | } 72 | else 73 | { 74 | return true 75 | && Detour_System_Wait.Hook(0x4EDE34FBADD967A6_handler, System_Wait, "System_Wait") 76 | ; 77 | } 78 | } 79 | 80 | bool Hooking::UnHookFunctions() 81 | { 82 | if (g_GameVersion == -1) 83 | { 84 | return true 85 | && Detour_NativeRegistration.UnHook() 86 | ; 87 | } 88 | else 89 | { 90 | return true 91 | && Detour_System_Wait.UnHook() 92 | ; 93 | } 94 | } 95 | 96 | -------------------------------------------------------------------------------- /ScriptHookV/Hooking/Hooking.h: -------------------------------------------------------------------------------- 1 | #ifndef __HOOKING_H__ 2 | #define __HOOKING_H__ 3 | 4 | #include "..\ScriptHookV.h" 5 | #include "..\Utility\Pattern.h" 6 | #include 7 | 8 | namespace Hooking 9 | { 10 | template 11 | class DetourHook; 12 | 13 | template 14 | class DetourHook 15 | { 16 | public: 17 | using F = R(*)(T...); 18 | 19 | protected: 20 | F _original; 21 | F _detour; 22 | const char* _name; 23 | DETOUR_TRAMPOLINE* _trampoline; 24 | 25 | public: 26 | DetourHook() 27 | : _original(nullptr) 28 | , _detour(nullptr) 29 | , _trampoline(nullptr) 30 | , _name(nullptr) 31 | { } 32 | 33 | ~DetourHook() 34 | { 35 | if (_trampoline) 36 | { 37 | UnHook(); 38 | 39 | MessageBoxA(NULL, FMT("%s Hook was not removed", _name).c_str(), "Error", MB_OK | MB_TOPMOST); 40 | 41 | } 42 | } 43 | 44 | bool Hook(F original, F detour, const char* name) 45 | { 46 | _original = original; 47 | _detour = detour; 48 | _name = name; 49 | 50 | DetourTransactionBegin(); 51 | DetourUpdateThread(GetCurrentThread()); 52 | 53 | DetourAttachEx(reinterpret_cast(&_original), _detour, &_trampoline, NULL, NULL); 54 | 55 | if (DetourTransactionCommit() != NO_ERROR) 56 | { 57 | LOG_ERROR("Could not hook '%s'", name); 58 | DetourTransactionAbort(); 59 | return nullptr; 60 | } 61 | 62 | LOG_DEBUG("Hooked %s at %llX", name, normalise_base(original)); 63 | 64 | return true; 65 | } 66 | 67 | bool UnHook() 68 | { 69 | DetourTransactionBegin(); 70 | DetourUpdateThread(GetCurrentThread()); 71 | 72 | DetourDetach(reinterpret_cast(&_original), _detour); 73 | 74 | bool success = DetourTransactionCommit() == NO_ERROR; 75 | 76 | if (!success) 77 | { 78 | LOG_ERROR("Could not unhook '%s'", _name); 79 | DetourTransactionAbort(); 80 | } 81 | else 82 | { 83 | LOG_DEBUG("Unhooked %s at %llX", _name, normalise_base(_original)); 84 | } 85 | 86 | _original = nullptr; 87 | _detour = nullptr; 88 | _trampoline = nullptr; 89 | 90 | return success; 91 | } 92 | 93 | R operator()(T&... args) 94 | { 95 | return reinterpret_cast(_trampoline)(std::forward(args)...); 96 | } 97 | }; 98 | 99 | template 100 | class DetourHook : public DetourHook { }; 101 | 102 | template 103 | class DetourHook : public DetourHook { }; 104 | 105 | bool HookFunctions(); 106 | 107 | bool UnHookFunctions(); 108 | 109 | std::uintptr_t normalise_base(mem::handle address, const std::uintptr_t& offset = 0x140000000); 110 | }; 111 | 112 | #endif // __HOOKING_H__ -------------------------------------------------------------------------------- /ScriptHookV/Injector/Injection.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifndef INJECTION_H 4 | #define INJECTION_H 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include "NT Stuff.h" 11 | #include 12 | 13 | enum INJECTION_MODE 14 | { 15 | IM_LoadLibrary, 16 | IM_LdrLoadDll, 17 | IM_ManualMap, 18 | }; 19 | 20 | #define INJ_ERASE_HEADER 1 21 | #define INJ_FAKE_HEADER 2 22 | #define INJ_UNLINK_FROM_PEB 4 23 | #define INJ_FLAGS_ALL (INJ_ERASE_HEADER | INJ_FAKE_HEADER | INJ_UNLINK_FROM_PEB) 24 | 25 | HMODULE GetModuleInProcess(HANDLE hProc, const char* moduleName); 26 | DWORD InjectDLL(const char * szDllFile, HANDLE hProc, INJECTION_MODE Mode, bool HijackThread = false, DWORD Postinjection = 0, DWORD * ErrorCode = nullptr); 27 | 28 | #define InjectionErrors \ 29 | X( INJ_ERR_SUCCESS ) \ 30 | X( INJ_ERR_INVALID_PROC_HANDLE ) \ 31 | X( INJ_ERR_FILE_DOESNT_EXIST ) \ 32 | X( INJ_ERR_OUT_OF_MEMORY ) \ 33 | X( INJ_ERR_INVALID_FILE ) \ 34 | X( INJ_ERR_NO_X64FILE ) \ 35 | X( INJ_ERR_NO_X86FILE ) \ 36 | X( INJ_ERR_IMAGE_CANT_RELOC ) \ 37 | X( INJ_ERR_NTDLL_MISSING ) \ 38 | X( INJ_ERR_LDRLOADDLL_MISSING ) \ 39 | X( INJ_ERR_LDRPLOADDLL_MISSING ) \ 40 | X( INJ_ERR_INVALID_FLAGS ) \ 41 | X( INJ_ERR_CANT_FIND_MOD ) \ 42 | X( INJ_ERR_CANT_FIND_MOD_PEB ) \ 43 | X( INJ_ERR_UNKNOWN ) \ 44 | X( INJ_ERR_CANT_CREATE_THREAD ) \ 45 | X( INJ_ERR_CANT_ALLOC_MEM ) \ 46 | X( INJ_ERR_WPM_FAIL ) \ 47 | X( INJ_ERR_TH32_FAIL ) \ 48 | X( INJ_ERR_CANT_GET_PEB ) \ 49 | X( INJ_ERR_ALREADY_INJ ) 50 | 51 | #define X(x) x, 52 | enum eInjectionErrors { InjectionErrors InjectionErrorCount }; 53 | #undef X 54 | 55 | #define X(x) #x, 56 | constexpr std::array eInjectionErrorNames = { InjectionErrors }; 57 | #undef X 58 | 59 | #define InjectionAdvErrors \ 60 | X( INJ_ERR_ADV_UNKNOWN ) \ 61 | X( INJ_ERR_ADV_INV_PROC ) \ 62 | X( INJ_ERR_ADV_TH32_FAIL ) \ 63 | X( INJ_ERR_ADV_NO_THREADS ) \ 64 | X( INJ_ERR_ADV_CANT_OPEN_THREAD ) \ 65 | X( INJ_ERR_ADV_SUSPEND_FAIL ) \ 66 | X( INJ_ERR_ADV_GET_CONTEXT_FAIL ) \ 67 | X( INJ_ERR_ADV_OUT_OF_MEMORY ) \ 68 | X( INJ_ERR_ADV_WPM_FAIL ) \ 69 | X( INJ_ERR_ADV_SET_CONTEXT_FAIL ) \ 70 | X( INJ_ERR_ADV_RESUME_FAIL ) \ 71 | X( INJ_ERR_ADV_QIP_MISSING ) \ 72 | X( INJ_ERR_ADV_QIP_FAIL ) 73 | 74 | #define X(x) x, 75 | enum eInjectionAdvErrors { InjectionAdvErrors InjectionAdvErrorCount }; 76 | #undef X 77 | 78 | #define X(x) #x, 79 | constexpr std::array eInjectionAdvErrorNames = { InjectionAdvErrors }; 80 | #undef X 81 | 82 | #endif -------------------------------------------------------------------------------- /ScriptHookV/Injector/Injector.rc.k: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Give-Two/ScriptHookV/11b97e8933f5eb219102992910be5a94087354d6/ScriptHookV/Injector/Injector.rc.k -------------------------------------------------------------------------------- /ScriptHookV/Injector/Injector.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Release 6 | x64 7 | 8 | 9 | 10 | {B113859C-0C89-47C5-A09D-DAC2DAE84A12} 11 | Win32Proj 12 | Injector 13 | 10.0.15063.0 14 | 15 | 16 | 17 | Application 18 | false 19 | v141 20 | true 21 | MultiByte 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | $(SolutionDir)Build\$(Configuration)\ 34 | $(SolutionDir)Temp\$(ProjectName)\$(Configuration)\ 35 | false 36 | true 37 | 38 | 39 | 40 | Level4 41 | 42 | 43 | MaxSpeed 44 | true 45 | true 46 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 47 | None 48 | 49 | 50 | Console 51 | true 52 | true 53 | false 54 | AsInvoker 55 | false 56 | true 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /ScriptHookV/Injector/Injector.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 6 | h;hh;hpp;hxx;hm;inl;inc;xsd 7 | 8 | 9 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 10 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 11 | 12 | 13 | 14 | 15 | Source 16 | 17 | 18 | Source 19 | 20 | 21 | Source 22 | 23 | 24 | Source 25 | 26 | 27 | Source 28 | 29 | 30 | 31 | 32 | Headers 33 | 34 | 35 | Headers 36 | 37 | 38 | Headers 39 | 40 | 41 | Headers 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /ScriptHookV/Injector/NT Stuff.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifndef NT_STUFF_H 4 | #define NT_STUFF_H 5 | 6 | #include 7 | 8 | struct UNICODE_STRING 9 | { 10 | WORD Length; 11 | WORD MaxLength; 12 | wchar_t * szBuffer; 13 | }; 14 | 15 | struct LDR_DATA_TABLE_ENTRY 16 | { 17 | LIST_ENTRY InLoadOrder; 18 | LIST_ENTRY InMemoryOrder; 19 | LIST_ENTRY InInitOrder; 20 | void * DllBase; 21 | void * EntryPoint; 22 | ULONG SizeOfImage; 23 | UNICODE_STRING FullDllName; 24 | UNICODE_STRING BaseDllName; 25 | }; 26 | 27 | struct PEB_LDR_DATA 28 | { 29 | ULONG Length; 30 | BYTE Initialized; 31 | HANDLE SsHandle; 32 | LIST_ENTRY InLoadOrderModuleListHead; 33 | LIST_ENTRY InMemoryOrderModuleListHead; 34 | LIST_ENTRY InInitializationOrderModuleListHead; 35 | void * EntryInProgress; 36 | BYTE ShutdownInProgress; 37 | HANDLE ShutdownThreadId; 38 | }; 39 | 40 | struct PEB 41 | { 42 | void * Reserved[3]; 43 | PEB_LDR_DATA * Ldr; 44 | }; 45 | 46 | struct PROCESS_BASIC_INFORMATION 47 | { 48 | NTSTATUS ExitStatus; 49 | PEB * pPEB; 50 | ULONG_PTR AffinityMask; 51 | LONG BasePriority; 52 | HANDLE UniqueProcessId; 53 | HANDLE InheritedFromUniqueProcessId; 54 | }; 55 | 56 | enum _PROCESSINFOCLASS 57 | { 58 | ProcessBasicInformation 59 | }; 60 | typedef _PROCESSINFOCLASS PROCESSINFOCLASS; 61 | 62 | typedef NTSTATUS(__stdcall * f_NtCreateThreadEx)(HANDLE * pHandle, ACCESS_MASK DesiredAccess, void * pAttr, HANDLE hProc, void * pFunc, void * pArg, 63 | ULONG Flags, SIZE_T ZeroBits, SIZE_T StackSize, SIZE_T MaxStackSize, void * pAttrListOut); 64 | 65 | typedef NTSTATUS(__stdcall * f_LdrLoadDll)(wchar_t * szOptPath, ULONG ulFlags, UNICODE_STRING * pModuleFileName, HANDLE * pOut); 66 | 67 | typedef NTSTATUS(__stdcall * f_NtQueryInformationProcess)(HANDLE hProc, PROCESSINFOCLASS PIC, void * pBuffer, ULONG BufferSize, ULONG * SizeOut); 68 | 69 | #endif -------------------------------------------------------------------------------- /ScriptHookV/Injector/Resource.rc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Give-Two/ScriptHookV/11b97e8933f5eb219102992910be5a94087354d6/ScriptHookV/Injector/Resource.rc -------------------------------------------------------------------------------- /ScriptHookV/Injector/icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Give-Two/ScriptHookV/11b97e8933f5eb219102992910be5a94087354d6/ScriptHookV/Injector/icon.ico -------------------------------------------------------------------------------- /ScriptHookV/Injector/main.cpp: -------------------------------------------------------------------------------- 1 | #include "Injection.h" 2 | #include "registry.h" 3 | 4 | #define BREAK_WITH_ERROR( fmt, ...) Utility::GetLog()->LogToFile( Utility::eLogType::LogTypeError, FMT( fmt, ##__VA_ARGS__ ) + FMT( " Code=%d", GetLastError() )) 5 | 6 | int main() 7 | { 8 | /* Configurable Settings */ 9 | 10 | //Target process 11 | const std::string exeName = "GTA5.exe"; 12 | 13 | //DLL to inject 14 | const std::string dllName = "ScriptHookV.dll"; 15 | 16 | //Hijack an existing thread ? false = create one 17 | bool ThreadHijacking = false; 18 | 19 | //DLL Injction methods - IM_LoadLibrary | IM_LdrLoadDll | IM_ManualMap 20 | INJECTION_MODE InjectionMethod = IM_LoadLibrary; 21 | 22 | //DLL Header Options - INJ_ERASE_HEADER | INJ_FAKE_HEADER | INJ_UNLINK_FROM_PEB | INJ_FLAGS_ALL (All of these Options) 23 | DWORD HeaderFlags = NULL; 24 | 25 | // Registry entry 26 | std::string sExecutablePath; 27 | bool isRetailKey = false; 28 | bool isSteamKey = false; 29 | 30 | // first truncated entry 31 | LOG_PRINT("\n"); 32 | 33 | // console window removal; 34 | FreeConsole(); 35 | 36 | Utility::SetOurModuleHandle(GetModuleHandle(NULL)); 37 | 38 | HANDLE hProcess = NULL; 39 | 40 | if (Utility::GetProcess(exeName, hProcess)) goto DO_INJECT; 41 | 42 | if (!hProcess) 43 | { 44 | Registry reg; 45 | 46 | isSteamKey = reg.isSteamKey(); 47 | 48 | isRetailKey = reg.isRetailKey(); 49 | 50 | if (isRetailKey)//RETAIL 51 | { 52 | LOG_PRINT("Detected the retail version of GTAV."); 53 | if (reg.GetValue().empty()) 54 | { 55 | BREAK_WITH_ERROR("Reading GTA V install path."); 56 | } 57 | else 58 | { 59 | sExecutablePath = reg.GetValue() + "\\GTA5.exe"; 60 | if (!Utility::DoesFileExist(sExecutablePath.c_str())) 61 | BREAK_WITH_ERROR("GTA5.exe not found."); 62 | 63 | LOG_DEBUG("Starting %s", "GTAVLauncher.exe"); 64 | Utility::StartProcess((reg.GetValue() + "\\GTAVLauncher.exe").c_str()); 65 | } 66 | } 67 | //STEAM 68 | else if (isSteamKey) 69 | { 70 | LOG_PRINT("Detected the steam version of GTAV."); 71 | if (reg.GetValue(true).empty()) 72 | { 73 | BREAK_WITH_ERROR("Reading GTA V install path."); 74 | } 75 | else 76 | { 77 | sExecutablePath = reg.GetValue() + "\\GTA5.exe"; 78 | if (!Utility::DoesFileExist(sExecutablePath.c_str())) 79 | BREAK_WITH_ERROR("GTA5.exe not found."); 80 | 81 | LOG_DEBUG("Starting GTA V - steam id:271590"); 82 | ShellExecute(NULL, "open", "steam://run/271590", NULL, NULL, SW_SHOWNORMAL); 83 | } 84 | } 85 | 86 | // Wait while target process is unavailable 87 | LOG_DEBUG("Waiting for %s process to become available...", exeName.c_str()); 88 | 89 | while (!Utility::GetProcess(exeName, hProcess)) 90 | { 91 | if (isRetailKey) 92 | { 93 | if (!Utility::GetProcessID("GTAVLauncher.exe")) 94 | { 95 | BREAK_WITH_ERROR("GTAVLauncher.exe Is no longer running, aborting injection."); 96 | } 97 | } 98 | 99 | Sleep(100); 100 | } 101 | } 102 | 103 | DO_INJECT: 104 | 105 | // Ensure we have the process open 106 | if (!hProcess) 107 | BREAK_WITH_ERROR("Opening %s.", exeName.c_str()); 108 | 109 | LOG_DEBUG("Found %s, PID: %lu", exeName.c_str(), GetProcessId(hProcess)); 110 | 111 | // Get full file path 112 | const char* cpDllFile = Utility::GetNamedModuleFolder(dllName, true).c_str(); 113 | if (!cpDllFile) 114 | BREAK_WITH_ERROR("Unable to find %s to inject", dllName.c_str()); 115 | 116 | DWORD Err = 0; 117 | auto Ret = InjectDLL(cpDllFile, hProcess, InjectionMethod, ThreadHijacking, HeaderFlags, &Err); 118 | if (Ret) 119 | { 120 | std::string Msg = "Error code: "; 121 | Msg += eInjectionErrorNames[Ret]; 122 | Msg += "\nAdvanced info: "; 123 | Msg += eInjectionAdvErrorNames[Err]; 124 | MessageBox(0, Msg.c_str(), "Injection failed", MB_ICONERROR); 125 | } 126 | 127 | CloseHandle(hProcess); 128 | 129 | return ERROR_SUCCESS; 130 | } -------------------------------------------------------------------------------- /ScriptHookV/Injector/registry.cpp: -------------------------------------------------------------------------------- 1 | #include "registry.h" 2 | 3 | bool Registry::isRetailKey() 4 | { 5 | hKey = HKEY_LOCAL_MACHINE; 6 | subKey = "SOFTWARE\\Wow6432Node\\Rockstar Games\\Grand Theft Auto V"; 7 | long key = RegOpenKeyExA(hKey, subKey, 0, KEY_READ, &resKey); 8 | if (key == ERROR_SUCCESS) return true; 9 | else return false; 10 | } 11 | 12 | bool Registry::isSteamKey() 13 | { 14 | hKey = HKEY_LOCAL_MACHINE; 15 | subKey = "SOFTWARE\\Wow6432Node\\Rockstar Games\\GTAV"; 16 | long key = RegOpenKeyExA(hKey, subKey, 0, KEY_READ, &resKey); 17 | return (key == ERROR_SUCCESS); 18 | } 19 | 20 | std::string Registry::GetValue(bool steam) 21 | { 22 | DWORD dwType = REG_SZ; 23 | char value[1024]; 24 | DWORD value_length = 1024; 25 | subValue = "InstallFolder"; 26 | if (steam) subValue = "installfoldersteam"; 27 | long key = RegQueryValueExA(resKey, subValue, NULL, &dwType, (LPBYTE)&value, &value_length); 28 | if (key == ERROR_FILE_NOT_FOUND) return std::string(); 29 | else return std::string(value); 30 | } -------------------------------------------------------------------------------- /ScriptHookV/Injector/registry.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "..\ScriptHookV.h" 4 | 5 | class Registry 6 | { 7 | HKEY hKey; 8 | LPCSTR subKey; 9 | LPCSTR subValue; 10 | HKEY resKey; 11 | DWORD dataLen; 12 | public: 13 | bool isRetailKey(); 14 | bool isSteamKey(); 15 | std::string GetValue(bool steam = false); 16 | }; 17 | -------------------------------------------------------------------------------- /ScriptHookV/Injector/resource.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Visual C++ generated include file. 3 | // Used by Resource.rc 4 | 5 | // Next default values for new objects 6 | // 7 | #ifdef APSTUDIO_INVOKED 8 | #ifndef APSTUDIO_READONLY_SYMBOLS 9 | #define _APS_NEXT_RESOURCE_VALUE 101 10 | #define _APS_NEXT_COMMAND_VALUE 40001 11 | #define _APS_NEXT_CONTROL_VALUE 1001 12 | #define _APS_NEXT_SYMED_VALUE 101 13 | #endif 14 | #endif 15 | -------------------------------------------------------------------------------- /ScriptHookV/Input/InputHook.cpp: -------------------------------------------------------------------------------- 1 | #include "InputHook.h" 2 | #include "..\Scripting\ScriptManager.h" 3 | 4 | WNDPROC oWndProc; 5 | HWND hWindow; 6 | 7 | LRESULT APIENTRY InputHook::WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) 8 | { 9 | ScriptManager::WndProc(hwnd, uMsg, wParam, lParam); 10 | return CallWindowProc(oWndProc, hwnd, uMsg, wParam, lParam); 11 | } 12 | 13 | bool InputHook::Initialize() 14 | { 15 | hWindow = FindWindowA("grcWindow", NULL); 16 | 17 | oWndProc = (WNDPROC)SetWindowLongPtr(hWindow, GWLP_WNDPROC, (LONG_PTR)WndProc ); 18 | if (oWndProc == NULL) 19 | { 20 | LOG_ERROR( "Failed to attach input hook" ); 21 | return false; 22 | } 23 | else 24 | { 25 | LOG_DEBUG( "Input hook attached: WndProc 0x%p", oWndProc ); 26 | return true; 27 | } 28 | } 29 | 30 | void InputHook::Remove() 31 | { 32 | SetWindowLongPtr(hWindow, GWLP_WNDPROC, (LONG_PTR)oWndProc); 33 | LOG_DEBUG("Removed input hook"); 34 | } 35 | 36 | -------------------------------------------------------------------------------- /ScriptHookV/Input/InputHook.h: -------------------------------------------------------------------------------- 1 | #ifndef __INPUT_HOOK_H__ 2 | #define __INPUT_HOOK_H__ 3 | 4 | #define KeyStateDown(key)(GetAsyncKeyState(key) & 0x8000) != 0 5 | #define KeyStateToggled(key)GetKeyState(key) & 0x0001) != 0 6 | 7 | #include "..\ScriptHookV.h" 8 | 9 | namespace InputHook 10 | { 11 | bool Initialize(); 12 | 13 | void Remove(); 14 | 15 | static LRESULT APIENTRY WndProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam ); 16 | } 17 | 18 | #endif // __INPUT_HOOK_H__ -------------------------------------------------------------------------------- /ScriptHookV/LICENSE-ntauthority.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014 Bas Timmer/NTAuthority et al. 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. -------------------------------------------------------------------------------- /ScriptHookV/ScriptHookV.cpp: -------------------------------------------------------------------------------- 1 | #include "Scripting\ScriptEngine.h" 2 | #include "Scripting\ScriptManager.h" 3 | #include "Input\InputHook.h" 4 | #include "Hooking\Hooking.h" 5 | #include "DirectX\D3d11Hook.h" 6 | #include "Utility\Versioning.h" 7 | #include "..\SDK\inc\enums.h" 8 | 9 | using namespace Utility; 10 | 11 | std::uint32_t g_ThreadHash = "main_persistent"_joaat; 12 | 13 | BOOL APIENTRY DllMain( HINSTANCE hModule, DWORD dwReason, LPVOID /*lpvReserved*/ ) 14 | { 15 | switch ( dwReason ) 16 | { 17 | case DLL_PROCESS_ATTACH: 18 | { 19 | SetOurModuleHandle(hModule); 20 | 21 | // no launcher check 22 | if (auto p_launcherCheck = "E8 ? ? ? ? 84 C0 75 0C B2 01 B9 2F"_Scan) p_launcherCheck.nop(21); 23 | 24 | // no legals 25 | if (auto p_gameLegals = "72 1F E8 ? ? ? ? 8B 0D"_Scan) p_gameLegals.nop(2); 26 | 27 | // no annoying movie 28 | // this doesn't save any loadup time just plays nothing 29 | //if (auto p_preMovie = "70 6C 61 74 66 6F 72 6D 3A 2F 6D 6F 76"_Scan) p_preMovie.nop(13); 30 | 31 | static auto& versionTool = GTAVersion::GetInstance(); 32 | g_GameVersion = versionTool.GameVersion(); 33 | auto gta5directory = versionTool.GameDirectory(); 34 | auto versionString = versionTool.VersionString(); 35 | 36 | if (g_GameVersion == -1) 37 | { 38 | auto file = GetOurModuleFolder() + "\\Native_Registration.txt"; 39 | if (DoesFileExist(file.c_str())) remove(file.c_str()); 40 | LOG_FILE("Native_Registration", "%s", versionString.c_str()); 41 | CreateElevatedThread([](LPVOID)->DWORD 42 | { 43 | Hooking::HookFunctions(); 44 | while (true) 45 | { 46 | static eGameState* gameState = "83 3D ? ? ? ? ? 8A D9 74 0A"_Scan.add(2).rip(5).as(); 47 | if (*gameState == GameStateMainMenu) 48 | { 49 | Hooking::UnHookFunctions(); 50 | MessageBoxA(NULL, FMT("New Game Version %s", versionTool.VersionString().c_str()).c_str(), "ScriptHookV Incompatible", MB_OK | MB_TOPMOST); 51 | FreeLibraryAndExitThread(Utility::GetOurModuleHandle(), ERROR_SUCCESS); 52 | break; 53 | } 54 | } 55 | return TRUE; 56 | }); 57 | } 58 | else 59 | { 60 | if (g_IsRetail = !DoesFileExist((gta5directory + "\\steam_api64.dll").c_str())) g_GameVersion += 1; 61 | LOG_DEBUG("found GTA5 directory %s", gta5directory.c_str()); 62 | LOG_DEBUG("detected GTA5 %s Version %s (SHV patch %d)", g_IsRetail ? "Retail" : "Steam", versionString.c_str(), g_GameVersion); 63 | 64 | // incompatible with versions prior to 1.0.1493.0 with current hashmap. 65 | if (g_GameVersion < VER_1_0_1493_0_STEAM) 66 | { 67 | MessageBoxA(NULL, "Update to Version 1.0.1493.0", "Game Version Incompatible!", MB_OK | MB_TOPMOST); 68 | FreeLibraryAndExitThread(hModule, 0); 69 | return TRUE; 70 | } 71 | 72 | CreateElevatedThread([](LPVOID)->DWORD 73 | { 74 | if (!ScriptEngine::Initialize()) 75 | { 76 | LOG_ERROR("Failed to initialize ScriptEngine"); 77 | return FALSE; 78 | } return TRUE; 79 | }); 80 | 81 | } 82 | break; 83 | } 84 | case DLL_PROCESS_DETACH: 85 | { 86 | g_HookState = HookStateExiting; 87 | break; 88 | } 89 | } 90 | 91 | return TRUE; 92 | } 93 | -------------------------------------------------------------------------------- /ScriptHookV/ScriptHookV.h: -------------------------------------------------------------------------------- 1 | #ifndef __SCRIPT_HOOK__ 2 | #define __SCRIPT_HOOK__ 3 | 4 | #ifndef NOMINMAX 5 | #define NOMINMAX 6 | #endif //NOMINMAX 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | #pragma comment(lib, "winmm.lib") 31 | #pragma comment(lib, "shlwapi.lib") 32 | 33 | #include "Utility\General.h" 34 | #include "Utility\Log.h" 35 | 36 | #define FMT(fmt, ...) (false ? std::to_string(printf(fmt, ##__VA_ARGS__)) : string_format(fmt, ##__VA_ARGS__ )) 37 | template T process_arg(T value) noexcept { return value; } 38 | template T const * process_arg(std::basic_string const & value) noexcept { return value.c_str(); } 39 | template std::string string_format(const std::string& format, Args const & ... args) { 40 | 41 | const auto fmt = format.c_str(); 42 | const auto size = std::snprintf(nullptr, 0, fmt, process_arg(args) ...) + 1; 43 | auto buf = std::make_unique(size); 44 | std::snprintf(buf.get(), size, fmt, process_arg(args) ...); 45 | return std::string(buf.get(), buf.get() + size - 1); 46 | } 47 | 48 | template 49 | InputType RCast(InputType Input, ReturnType Ret) 50 | { 51 | return reinterpret_cast(Ret); 52 | } 53 | 54 | extern std::uint32_t g_ThreadHash; 55 | extern int g_GameVersion; 56 | extern bool g_IsRetail; 57 | 58 | #endif // __SCRIPT_HOOK__ -------------------------------------------------------------------------------- /ScriptHookV/ScriptHookV.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | Release 7 | x64 8 | 9 | 10 | 11 | 15.0 12 | {B77FAE3F-A179-425D-B361-64F125CC3168} 13 | Win32Proj 14 | ScriptHookV 15 | 10.0.16299.0 16 | 17 | 18 | 19 | DynamicLibrary 20 | false 21 | v141 22 | true 23 | MultiByte 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | false 34 | $(ProjectDir)..\Build\$(Configuration)\ 35 | $(ProjectDir)..\Temp\$(ProjectName)\$(Configuration)\ 36 | 37 | 38 | 39 | Level4 40 | Full 41 | true 42 | true 43 | true 44 | _MBCS;_CRT_SECURE_NO_WARNINGS;NOMINMAX;%(PreprocessorDefinitions) 45 | $(ProjectDir)detours\include;$(ProjectDir)StackWalker\include;$(ProjectDir)DirectX\DirectXTK\inc;%(AdditionalIncludeDirectories) 46 | stdcpplatest 47 | true 48 | 49 | 50 | Windows 51 | true 52 | true 53 | $(ProjectDir)detours\lib.X64;$(ProjectDir)StackWalker\lib\Release;$(ProjectDir)DirectX\DirectXTK\lib;%(AdditionalLibraryDirectories) 54 | detours.lib;d3d11.lib;d3dcompiler.lib;dxgi.lib;%(AdditionalDependencies) 55 | 56 | 57 | xcopy "$(OutDir)$(TargetName).lib" "$(ProjectDir)..\SDK\lib\" /Y 58 | 59 | 60 | if not exist "$(OutDir)Asi" mkdir "$(OutDir)Asi" 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. 114 | 115 | 116 | 117 | 118 | -------------------------------------------------------------------------------- /ScriptHookV/Scripting/NativeInvoker.cpp: -------------------------------------------------------------------------------- 1 | #include "NativeInvoker.h" 2 | #include "ScriptEngine.h" 3 | #include "..\Hooking\Hooking.h" 4 | #include 5 | 6 | uint64_t NativeInvoker::Helper::g_hash; 7 | NativeArgStack NativeInvoker::Helper::g_Args; 8 | NativeReturnStack NativeInvoker::Helper::g_Returns; 9 | scrNativeCallContext NativeInvoker::Helper::g_context(&NativeInvoker::Helper::g_Returns, &NativeInvoker::Helper::g_Args); 10 | 11 | void(*scrNativeCallContext::SetVectorResults)(scrNativeCallContext*) = "83 79 18 00 48 8B D1 74 4A FF 4A 18"_Scan.as(); 12 | void* NativeRegistrationTable = "48 8D 0D ? ? ? ? 48 8B 14 FA E8 ? ? ? ?"_Scan.add(3).rip(4).as(); 13 | NativeHandler(*pGetNativeHandler)(void*, uint64_t hash) = "48 8D 0D ? ? ? ? 48 8B 14 FA E8 ? ? ? ?"_Scan.add(12).rip(4).as(); 14 | 15 | const std::unordered_map mHashMapTuple 16 | { 17 | #define X(OldHash, NewHash, Offset, Name, Version) { OldHash, std::make_tuple( NewHash, Offset, #Name, Version ) }, 18 | #include "HashMapData.h" 19 | #undef X 20 | }; 21 | 22 | HashMapTuple NativeInvoker::GetNativeTuple(uint64_t hash) 23 | { 24 | HashMapTuple tuple; 25 | return Utility::GetMapValue(mHashMapTuple, hash, tuple) ? tuple : HashMapTuple(); 26 | } 27 | 28 | NativeHandler NativeInvoker::GetNativeHandler(uint64_t hash) 29 | { 30 | HashMapTuple tuple = NativeInvoker::GetNativeTuple(hash); 31 | 32 | if (g_IsRetail) 33 | { 34 | // Direct to handler without accessing the NativeRegistrationTable 35 | if (auto offSet = std::get(tuple)) 36 | { 37 | return mem::module::main().base().add(offSet).as(); 38 | } 39 | } 40 | 41 | if (auto newHash = std::get(tuple)) 42 | { 43 | return pGetNativeHandler(NativeRegistrationTable, newHash); 44 | } 45 | 46 | return nullptr; 47 | } 48 | 49 | void NativeInvoker::DumpNativeList() 50 | { 51 | for (const auto& map : mHashMapTuple) 52 | { 53 | HashMapTuple tuple = NativeInvoker::GetNativeTuple(map.first); 54 | 55 | // auto pair = map.second; 56 | // auto hashOld = map.first; 57 | // auto hashNew = std::get(tuple); 58 | auto name = std::get(tuple); 59 | auto offset = std::get(tuple); 60 | // auto offset = Hooking::normalise_base((void*)pGetNativeHandler(NativeRegistrationTable, hashNew), 0); 61 | // auto vers = pair.second; 62 | // LOG_FILE("Natives", "X(0x%016llX, 0x%016llX, 0x%08llX, %s, %d)", hashOld, hashNew, offset, name, vers); 63 | LOG_FILE("IDA-python", "['%s', 0x%x],", name, offset); 64 | } 65 | } 66 | 67 | DECLSPEC_NOINLINE void NativeInvoker::Helper::CallNative(scrNativeCallContext *cxt, uint64_t hash) 68 | { 69 | if (auto handler = GetNativeHandler(hash)) 70 | { 71 | handler(cxt); 72 | 73 | cxt->FixVectors(); 74 | } 75 | else 76 | { 77 | static std::vector failed; 78 | if (!Utility::DoesVectorContain(failed, hash)) 79 | { 80 | LOG_ERROR("Failed to find native handler for 0x%016llX", hash); 81 | failed.push_back(hash); 82 | } 83 | } 84 | } -------------------------------------------------------------------------------- /ScriptHookV/Scripting/NativeInvoker.h: -------------------------------------------------------------------------------- 1 | #ifndef __NATIVE_INVOKER_H__ 2 | #define __NATIVE_INVOKER_H__ 3 | 4 | #include "..\ScriptHookV.h" 5 | #include "..\Utility\Pattern.h" 6 | #include "..\..\SDK\inc\types.h" 7 | 8 | enum HashMapIndice : std::size_t { HMT_NEW, HMT_OFF, HMT_NME, HMT_VER }; 9 | using HashMapTuple = std::tuple; 10 | 11 | template class NativeStack 12 | { 13 | public: 14 | 15 | static constexpr uint32_t size = stackSize; 16 | 17 | protected: 18 | 19 | uint64_t stack[stackSize]; 20 | 21 | template T getAt(uint32_t index)const 22 | { 23 | return reinterpret_cast(stack[index]); 24 | } 25 | 26 | template <> bool getAt(uint32_t index)const 27 | { 28 | return reinterpret_cast(stack[index]) != 0; 29 | } 30 | 31 | template void setAt(uint32_t index, const T& value) 32 | { 33 | reinterpret_cast(stack[index]) = value; 34 | } 35 | 36 | template <> void setAt(uint32_t index, const bool& value) 37 | { 38 | reinterpret_cast(stack[index]) = value != 0; 39 | } 40 | 41 | public: 42 | 43 | decltype(stack)& getRawPtr() { return stack; }; 44 | const decltype(stack)& getRawPtr()const { return stack; } 45 | }; 46 | 47 | struct NativeArgStack : NativeStack<32u> 48 | { 49 | template NativeArgStack *setArg(const T &value, uint32_t index) 50 | { 51 | if (index < size) setAt(index, value); return this; 52 | } 53 | 54 | template NativeArgStack *setArg(const T &value) 55 | { 56 | setAt(index, value); return this; 57 | } 58 | 59 | template T getArg(uint32_t index)const 60 | { 61 | return (index < size) ? getAt(index) : T(); 62 | } 63 | 64 | template NativeArgStack *getArg()const 65 | { 66 | return getAt(index); 67 | } 68 | }; 69 | 70 | struct NativeReturnStack : NativeStack<3u> 71 | { 72 | template T Get() const 73 | { 74 | return getAt(0); 75 | } 76 | 77 | template NativeReturnStack *Set(const T &value) 78 | { 79 | setAt(0, value); return this; 80 | } 81 | }; 82 | 83 | class scrNativeCallContext 84 | { 85 | public: 86 | static constexpr uint32_t maxNativeArgCount = NativeArgStack::size; 87 | static constexpr uint32_t maxNativeReturnCount = NativeReturnStack::size; 88 | static void(*SetVectorResults)(scrNativeCallContext*); 89 | private: 90 | NativeReturnStack* const m_pReturns; 91 | uint32_t m_nArgCount; 92 | NativeArgStack* const m_pArgs; 93 | uint32_t m_nDataCount; 94 | uint64_t reservedSpace[24] = {}; 95 | public: 96 | scrNativeCallContext(NativeReturnStack *returnStack, NativeArgStack *argStack) 97 | : m_pReturns(returnStack) 98 | , m_nArgCount(0) 99 | , m_pArgs(argStack) 100 | , m_nDataCount(0) {} 101 | 102 | void Reset() 103 | { 104 | SetArgCount<0>(); 105 | SetDataCount<0>(); 106 | } 107 | 108 | void FixVectors() { SetVectorResults(this); } 109 | 110 | template scrNativeCallContext *Push(const T &value) 111 | { 112 | m_pArgs->setArg(value, m_nArgCount++); return this; 113 | } 114 | 115 | template scrNativeCallContext *Push(const T &value) 116 | { 117 | m_pArgs->setArg(value); return *this; 118 | } 119 | 120 | template void SetArgCount() 121 | { 122 | m_nArgCount = ArgCount; 123 | } 124 | 125 | template void SetDataCount() 126 | { 127 | m_nDataCount = DataCount; 128 | } 129 | 130 | template T GetResult() const 131 | { 132 | return m_pReturns->Get(); 133 | } 134 | 135 | template scrNativeCallContext *SetResult(const T &value) 136 | { 137 | m_pReturns->Set(value); return this; 138 | } 139 | 140 | template T GetArg(uint32_t index) const 141 | { 142 | return m_pArgs->getArg(index); 143 | } 144 | 145 | template scrNativeCallContext *SetArg(uint32_t index, const T &value) 146 | { 147 | m_pArgs->setArg(index, value); return this; 148 | } 149 | 150 | uint32_t getArgCount() const { return m_nArgCount; } 151 | 152 | NativeArgStack &getArgStack() const { return *m_pArgs; } 153 | NativeReturnStack &getReturnStack() const { return *m_pReturns; } 154 | }; 155 | 156 | using NativeHandler = void(*)(scrNativeCallContext *); 157 | 158 | namespace NativeInvoker 159 | { 160 | namespace Helper 161 | { 162 | extern uint64_t g_hash; 163 | extern scrNativeCallContext g_context; 164 | extern NativeArgStack g_Args; 165 | extern NativeReturnStack g_Returns; 166 | extern DECLSPEC_NOINLINE void CallNative(scrNativeCallContext *cxt, std::uint64_t hash); 167 | } 168 | 169 | NativeHandler GetNativeHandler(uint64_t hash); 170 | 171 | HashMapTuple GetNativeTuple(uint64_t hash); 172 | 173 | void DumpNativeList(); 174 | 175 | // 176 | template struct NativeArgument 177 | { 178 | static constexpr uint32_t paramCount = NativeArgument::paramCount + NativeArgument::paramCount; 179 | template 180 | inline static void Push(NativeArgStack& argStack, T value, TArgs... args) 181 | { 182 | NativeArgument::Push(argStack, value); 183 | NativeArgument::Push::paramCount>(argStack, args...); 184 | } 185 | }; 186 | 187 | template <> struct NativeArgument // overload the template for NativeVector3 because they push 3 items 188 | { 189 | static constexpr uint32_t paramCount = 3u; 190 | template 191 | inline static void Push(NativeArgStack& argStack, const Vector3 &value) 192 | { 193 | argStack.setArg(value.x); 194 | argStack.setArg(value.y); 195 | argStack.setArg(value.z); 196 | } 197 | }; 198 | 199 | template struct NativeArgument 200 | { 201 | static constexpr uint32_t paramCount = 1; 202 | template 203 | inline static void Push(NativeArgStack& argStack, T value) 204 | { 205 | argStack.setArg(value); 206 | } 207 | }; 208 | 209 | template 210 | FORCEINLINE void PushArgs(scrNativeCallContext &cxt, TArgs... args) 211 | { 212 | cxt.SetDataCount<0>(); 213 | NativeArgument::Push<0>(cxt.getArgStack(), args...); 214 | cxt.SetArgCount::paramCount>(); 215 | } 216 | FORCEINLINE void PushArgs(scrNativeCallContext &cxt) { cxt.Reset(); }; 217 | 218 | template 219 | FORCEINLINE void PushArgs(TArgs... args) 220 | { 221 | Helper::g_context.SetDataCount<0>(); 222 | NativeArgument::Push<0>(Helper::g_Args, args...); 223 | Helper::g_context.SetArgCount::paramCount>(); 224 | } 225 | 226 | FORCEINLINE void PushArgs() { Helper::g_context.Reset(); }; //zero args 227 | 228 | template 229 | FORCEINLINE R invoke(std::uint64_t hash, TArgs... args) 230 | { 231 | Helper::g_context.Reset(); 232 | PushArgs(args...); 233 | Helper::CallNative(&Helper::g_context, hash); 234 | return Helper::g_Returns.Get(); 235 | }; 236 | // <\Local Invoker end> 237 | }; 238 | 239 | inline NativeHandler operator""_handler(uint64_t hash) 240 | { 241 | return NativeInvoker::GetNativeHandler(hash); 242 | } 243 | 244 | inline HashMapTuple operator""_info(uint64_t hash) 245 | { 246 | return NativeInvoker::GetNativeTuple(hash); 247 | } 248 | 249 | namespace rage 250 | { 251 | static int64_t*(*GetLocalPlayerInfo)() = "48 8B 05 ? ? ? ? 48 8B 48 08 33 C0 48 85 C9 74 07"_Scan.as(); 252 | static int64_t(*GetEntityAddress)(int) = "83 f9 ff 74 31 4c 8b 0d ? ? ? ? 44 8b c1 49 8b 41 08"_Scan.as(); 253 | static Entity(*AddressToEntity)(int64_t) = "48 89 5c 24 ? 48 89 74 24 ? 57 48 83 ec 20 8b 15 ? ? ? ? 48 8b f9 48 83 c1 10 33 db"_Scan.as(); 254 | static uint32_t*(*FileRegister)(int*, const char*, bool, const char*, bool) = "48 89 5C 24 ? 48 89 6C 24 ? 48 89 7C 24 ? 41 54 41 56 41 57 48 83 EC 50 48 8B EA 4C 8B FA 48 8B D9 4D 85 C9"_Scan.as(); 255 | static int64_t(*GetGtaSwapChain)() = "48 8B 05 ? ? ? ? C3 48 8B C1 8D 4A 0E"_Scan.as(); 256 | 257 | FORCEINLINE void GET_SCREEN_RESOLUTION(int* x, int* y) { NativeInvoker::invoke(0x888D57E407E63624, x, y); } 258 | FORCEINLINE void SET_TEXT_OUTLINE() { NativeInvoker::invoke(0x2513DFB0FB8400FE); } 259 | FORCEINLINE void SET_TEXT_WRAP(float start, float end) { NativeInvoker::invoke(0x63145D9C883A1A70, start, end); } 260 | FORCEINLINE void SET_TEXT_SCALE(float p0, float size) { NativeInvoker::invoke(0x07C837F9A01C34C9, p0, size); } 261 | FORCEINLINE void SET_TEXT_FONT(int fontType) { NativeInvoker::invoke(0x66E0276CC5F6B9DA, fontType); } 262 | FORCEINLINE void SET_TEXT_COLOUR(int red, int green, int blue, int alpha) { NativeInvoker::invoke(0xBE6B23FFA53FB442, red, green, blue, alpha); } 263 | FORCEINLINE void SET_TEXT_JUSTIFICATION(int justifyType) { NativeInvoker::invoke(0x4E096588B13FFECA, justifyType); } 264 | FORCEINLINE void SET_TEXT_CENTRE(bool align) { NativeInvoker::invoke(0xC02F4DBFB51D988B, align); } 265 | FORCEINLINE void ADD_TEXT_COMPONENT_SUBSTRING_PLAYER_NAME(const char* text) { NativeInvoker::invoke(0x6C188BE134E074AA, text); } 266 | FORCEINLINE void BEGIN_TEXT_COMMAND_DISPLAY_TEXT(const char* text) { NativeInvoker::invoke(0x25FBB336DF1804CB, text); } 267 | FORCEINLINE void END_TEXT_COMMAND_DISPLAY_TEXT(float x, float y, Any p2) { NativeInvoker::invoke(0xCD015E5BB0D96A57, x, y, p2); } 268 | 269 | FORCEINLINE bool DOES_TEXT_LABEL_EXIST(const char* gxt) { return NativeInvoker::invoke(0xAC09CA973C564252, gxt); } 270 | FORCEINLINE void _SET_NOTIFICATION_TEXT_ENTRY(const char* type) { NativeInvoker::invoke(0x202709F4C58A0424, type); } 271 | FORCEINLINE int _DRAW_NOTIFICATION(bool blink, bool p1) { return NativeInvoker::invoke(0x2ED7843F8F801023, blink, p1); } 272 | } 273 | 274 | #endif // __NATIVE_INVOKER_H__ -------------------------------------------------------------------------------- /ScriptHookV/Scripting/Pools.cpp: -------------------------------------------------------------------------------- 1 | #include "Pools.h" 2 | #include "NativeInvoker.h" 3 | 4 | namespace rage 5 | { 6 | class EntityPool 7 | { 8 | public: 9 | int _padding0[4]; 10 | int maxCount; // num1 11 | int itemSize; // seems to be valid 12 | int firstEmptySlot; // these two increment and loop when hitting maxCount 13 | int emptySlots; // not sure exactly why 14 | int itemCount; // num2 15 | 16 | inline bool Full() const 17 | { 18 | return free() < 256; 19 | } 20 | 21 | int free() const 22 | { 23 | return maxCount - (itemCount & 0x3FFFFFFF); 24 | } 25 | 26 | }; 27 | 28 | class GenericPool 29 | { 30 | public: 31 | uint64_t poolStartAddress; 32 | uint8_t* byteArray; 33 | int size; 34 | int itemSize; 35 | 36 | inline bool isValid(int i) 37 | { 38 | assert(i >= 0); 39 | return mask(i) != 0; 40 | } 41 | 42 | inline uint64_t getAddress(int i) 43 | { 44 | assert(i >= 0); 45 | return mask(i) & (poolStartAddress + i * itemSize); 46 | } 47 | private: 48 | inline long long mask(int i) 49 | { 50 | assert(i >= 0); 51 | long long num1 = byteArray[i] & 0x80; // check for high bit. 52 | return ~((num1 | -num1) >> 63); 53 | } 54 | }; 55 | 56 | class VehiclePool 57 | { 58 | public: 59 | uint64_t * listAddress; 60 | int size; 61 | char _padding2[36]; 62 | uint32_t* bitArray; 63 | char _padding3[40]; 64 | int itemCount; 65 | 66 | inline bool isValid(int i) 67 | { 68 | assert(i >= 0); 69 | return (bitArray[i >> 5] >> (i & 0x1F)) & 1; 70 | } 71 | 72 | inline uint64_t getAddress(int i) 73 | { 74 | return listAddress[i]; 75 | } 76 | }; 77 | 78 | struct EntityPoolTask 79 | { 80 | inline bool TypeHasFlag(uint16_t flag) 81 | { 82 | assert(!(_type & ~31)); 83 | assert(!(flag & ~31)); 84 | return (_type & flag) != 0; 85 | } 86 | 87 | EntityPoolTask(uint16_t type) : _type(type) {} 88 | 89 | void Run(std::vector& _pointers) 90 | { 91 | if (TypeHasFlag(PoolTypePed)) 92 | { 93 | static GenericPool* &pedPool = "48 8B 05 ? ? ? ? 41 0F BF C8 0F BF 40 10"_Scan.add(3).rip(4).as(); 94 | 95 | for (int i = 0; i < pedPool->size; i++) 96 | { 97 | if (uintptr_t address = pedPool->getAddress(i)) 98 | { 99 | _pointers.push_back(address); 100 | } 101 | } 102 | } 103 | 104 | if (TypeHasFlag(PoolTypeVehicle)) 105 | { 106 | static VehiclePool* &vehiclePool = *(VehiclePool **)(*(uintptr_t *)"48 8B 05 ? ? ? ? F3 0F 59 F6 48 8B 08"_Scan.add(3).rip(4).as()); 107 | 108 | for (int i = 0; i < vehiclePool->size; i++) 109 | { 110 | if (vehiclePool->isValid(i)) 111 | { 112 | if (uintptr_t address = vehiclePool->getAddress(i)) 113 | { 114 | _pointers.push_back(address); 115 | } 116 | } 117 | } 118 | } 119 | 120 | if (TypeHasFlag(PoolTypeObject)) 121 | { 122 | static GenericPool* &propPool = "48 8B 05 ? ? ? ? 8B 78 10 85 FF"_Scan.add(3).rip(4).as(); 123 | 124 | for (int i = 0; i < propPool->size; i++) 125 | { 126 | if (uintptr_t address = propPool->getAddress(i)) 127 | { 128 | _pointers.push_back(address); 129 | } 130 | } 131 | } 132 | 133 | if (TypeHasFlag(PoolTypePickup)) 134 | { 135 | static GenericPool* &pickupPool = "4C 8B 05 ? ? ? ? 40 8A F2 8B E9"_Scan.add(3).rip(4).as(); 136 | 137 | for (int i = 0; i < pickupPool->size; i++) 138 | { 139 | if (uintptr_t address = pickupPool->getAddress(i)) 140 | { 141 | _pointers.push_back(address); 142 | } 143 | } 144 | } 145 | 146 | if (TypeHasFlag(PoolTypeCamera)) 147 | { 148 | static GenericPool* &cameraPool = "48 8B C8 EB 02 33 C9 48 85 C9 74 26"_Scan.add(-9).rip(4).as(); 149 | 150 | for (int i = 0; i < cameraPool->size; i++) 151 | { 152 | if (uintptr_t address = cameraPool->getAddress(i)) 153 | { 154 | _pointers.push_back(address); 155 | } 156 | } 157 | } 158 | } 159 | private: 160 | uint16_t _type; 161 | }; 162 | 163 | std::string GetEntityPoolStats() 164 | { 165 | static EntityPool* &entityPool = "4C 8B 0D ? ? ? ? 44 8B C1 49 8B 41 08"_Scan.add(3).rip(4).as(); 166 | 167 | return FMT("maxCount: %i itemSize: %i firstEmptySlot: %i emptySlots: %i free: %i", 168 | entityPool->maxCount, // num1 169 | entityPool->itemSize, // 16 bytes 170 | entityPool->firstEmptySlot, // not sure if these are valid for EntityPools -- sfink 171 | entityPool->emptySlots, // not sure if these are valid for EntityPools -- sfink 172 | entityPool->maxCount - (entityPool->itemCount & 0x3FFFFFFF) 173 | ); 174 | } 175 | 176 | void GetEntityPointers(EntityPoolType type, std::vector& result) 177 | { 178 | EntityPoolTask(type).Run(result); 179 | } 180 | 181 | std::vector GetAllWorld(EntityPoolType type, int max) 182 | { 183 | int count = 0; 184 | std::vector entities; 185 | std::vector pointers; 186 | GetEntityPointers(type, pointers); 187 | 188 | for (const auto& cEntity : pointers) 189 | { 190 | if (count == max) break; 191 | auto entity = rage::AddressToEntity(cEntity); 192 | if (entity) 193 | { 194 | entities.push_back(entity); 195 | count++; 196 | } 197 | } 198 | 199 | return entities; 200 | } 201 | 202 | int GetAllWorld(EntityPoolType type, int max, int *arr) 203 | { 204 | auto entities = GetAllWorld(type, max); 205 | 206 | for (int i = 0; i < entities.size(); ++i) 207 | { 208 | arr[i] = entities[i]; 209 | } 210 | 211 | return (int) entities.size(); 212 | } 213 | } -------------------------------------------------------------------------------- /ScriptHookV/Scripting/Pools.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "..\..\SDK\inc\types.h" 3 | #include "..\ScriptHookV.h" 4 | 5 | enum EntityPoolType : uint16_t 6 | { 7 | PoolTypeVehicle = 1, 8 | PoolTypePed = 2, 9 | PoolTypeObject = 4, 10 | PoolTypePickup = 8, 11 | PoolTypeCamera = 16 12 | }; 13 | 14 | namespace rage 15 | { 16 | std::string GetEntityPoolStats(); 17 | 18 | int GetAllWorld(EntityPoolType type, int max, int *arr); 19 | 20 | std::vector GetAllWorld(EntityPoolType type, int max); 21 | }; 22 | -------------------------------------------------------------------------------- /ScriptHookV/Scripting/ScriptEngine.cpp: -------------------------------------------------------------------------------- 1 | #include "ScriptEngine.h" 2 | #include "ScriptManager.h" 3 | #include "NativeInvoker.h" 4 | #include "Pools.h" 5 | 6 | #include "..\ASI Loader\ASILoader.h" 7 | #include "..\Input\InputHook.h" 8 | #include "..\DirectX\D3d11Hook.h" 9 | #include "..\Hooking\Hooking.h" 10 | 11 | #include "..\..\SDK\inc\enums.h" 12 | 13 | struct GlobalTable 14 | { 15 | PINT64* GlobalBasePtr; 16 | PINT64 AddressOf(int index) const { return &GlobalBasePtr[index >> 18 & 0x3F][index & 0x3FFFF]; } 17 | bool IsInitialised()const { return *GlobalBasePtr; } 18 | }; 19 | 20 | GlobalTable globalTable; 21 | eGameState * gameState; 22 | eHookState g_HookState; 23 | int g_GameVersion; 24 | bool g_IsRetail; 25 | 26 | bool ScriptEngine::Initialize() 27 | { 28 | LOG_PRINT("Initializing..."); 29 | 30 | // init Direct3d hook 31 | if (!g_D3DHook.InitializeHooks()) 32 | { 33 | LOG_ERROR("Failed to Initialize Direct3d Hooks"); 34 | return false; 35 | } 36 | 37 | // kill this data snoop ( must be done after D3D ) 38 | if (Utility::GetProcessID("GTAVLauncher.exe")) 39 | { 40 | Utility::killProcessByName("GTAVLauncher.exe"); 41 | LOG_DEBUG("Killed %s", "GTAVLauncher.exe"); 42 | } 43 | 44 | // init Winproc hook 45 | if (!InputHook::Initialize()) 46 | { 47 | LOG_ERROR("Failed to Initialize InputHook"); 48 | return false; 49 | } 50 | 51 | // Get game state 52 | if (auto gameStatePattern = "83 3D ? ? ? ? ? 8A D9 74 0A"_Scan) 53 | { 54 | gameState = gameStatePattern.add(2).rip(5).as(); 55 | LOG_ADDRESS("gameState", gameState); 56 | } 57 | else 58 | { 59 | LOG_ERROR("Unable to find gameState"); 60 | return false; 61 | } 62 | 63 | // Get global table 64 | if (auto globalTablePattern = "4C 8D 05 ? ? ? ? 4D 8B 08 4D 85 C9 74 11"_Scan) 65 | { 66 | globalTable.GlobalBasePtr = globalTablePattern.add(3).rip(4).as(); 67 | while (!globalTable.IsInitialised()) Sleep(100); 68 | LOG_ADDRESS("globalTable", globalTable.GlobalBasePtr); 69 | } 70 | else 71 | { 72 | LOG_ERROR("Unable to find globalTable"); 73 | return false; 74 | } 75 | 76 | while (GetGameState() != GameStatePlaying) Sleep(100); 77 | 78 | LOG_PRINT("Performing function hooking..."); 79 | 80 | if (Hooking::HookFunctions()) 81 | { 82 | ASILoader::Initialize(); 83 | 84 | LOG_PRINT("Initialization finished"); 85 | 86 | g_HookState = HookStateRunning; 87 | 88 | return true; 89 | } 90 | 91 | g_HookState = HookStateExiting; 92 | 93 | return false; 94 | } 95 | 96 | eGameState ScriptEngine::GetGameState() 97 | { 98 | return *gameState; 99 | } 100 | 101 | PUINT64 ScriptEngine::getGlobal(int globalId) 102 | { 103 | return reinterpret_cast(globalTable.AddressOf(globalId)); 104 | } 105 | 106 | int ScriptEngine::RegisterFile(const std::string& fullPath, const std::string& fileName) 107 | { 108 | int textureID = -1; 109 | if (rage::FileRegister(&textureID, fullPath.c_str(), true, fileName.c_str(), false)) 110 | { 111 | LOG_DEBUG("Registered File %s with ID:%i", fullPath.c_str(), textureID); 112 | return textureID; 113 | } 114 | 115 | LOG_ERROR("Failed to register %s", fullPath.c_str()); 116 | return 0; 117 | } 118 | -------------------------------------------------------------------------------- /ScriptHookV/Scripting/ScriptEngine.h: -------------------------------------------------------------------------------- 1 | #ifndef __SCRIPT_ENGINE_H__ 2 | #define __SCRIPT_ENGINE_H__ 3 | 4 | #include "..\ScriptHookV.h" 5 | 6 | #include "NativeInvoker.h" 7 | 8 | enum eGameState 9 | { 10 | GameStatePlaying, 11 | GameStateIntro, 12 | GameStateLicenseShit = 3, 13 | GameStateMainMenu = 5, 14 | GameStateLoadingSP_MP = 6 15 | }; 16 | 17 | enum eHookState 18 | { 19 | HookStateRunning, 20 | HookStateExiting, 21 | HookStateUnknown = -1 22 | }; extern eHookState g_HookState; 23 | 24 | class ScriptEngine 25 | { 26 | public: 27 | 28 | static bool Initialize(); 29 | 30 | static PUINT64 getGlobal(int globalId); 31 | 32 | static eGameState GetGameState(); 33 | 34 | static int RegisterFile(const std::string& fullPath, const std::string& fileName); 35 | }; 36 | 37 | #endif // __SCRIPT_ENGINE_H__ -------------------------------------------------------------------------------- /ScriptHookV/Scripting/ScriptManager.cpp: -------------------------------------------------------------------------------- 1 | #include "ScriptManager.h" 2 | #include "ScriptEngine.h" 3 | #include "ScriptThread.h" 4 | #include "NativeInvoker.h" 5 | #include "Pools.h" 6 | 7 | #include "..\ASI Loader\ASILoader.h" 8 | #include "..\Input\InputHook.h" 9 | #include "..\DirectX\D3d11Hook.h" 10 | #include "..\Hooking\Hooking.h" 11 | #include "..\..\SDK\inc\types.h" 12 | #include "..\..\SDK\inc\enums.h" 13 | 14 | #include 15 | #pragma comment(lib, "StackWalker.lib") 16 | // Specialized stackwalker-output classes 17 | // Console (printf): 18 | class StackWalkerToConsole : public StackWalker 19 | { 20 | protected: 21 | virtual void OnOutput(LPCSTR szText) 22 | { 23 | std::ofstream LOG; 24 | 25 | std::string fileName = Utility::GetOurModuleFolder() + "\\" + "StackTrace" + ".txt"; 26 | 27 | LOG.open(fileName, std::ofstream::out | std::ofstream::app); 28 | 29 | LOG << szText << std::endl; 30 | 31 | LOG.close(); 32 | } 33 | }; 34 | 35 | LONG WINAPI ExpFilter(EXCEPTION_POINTERS* pExp, DWORD /*dwExpCode*/) 36 | { 37 | //StackWalker sw; // output to default (Debug-Window) 38 | StackWalkerToConsole sw; // output to the console 39 | sw.ShowCallstack(GetCurrentThread(), pExp->ContextRecord); 40 | return EXCEPTION_EXECUTE_HANDLER; 41 | } 42 | 43 | #define DLL_EXPORT __declspec( dllexport ) 44 | 45 | using namespace NativeInvoker::Helper; 46 | 47 | ScriptThread g_ScriptThread; 48 | ScriptThread g_AdditionalThread; 49 | HANDLE g_MainFiber; 50 | Script* g_CurrentScript; 51 | 52 | /* ####################### SCRIPT #######################*/ 53 | 54 | void Script::Tick() 55 | { 56 | if (timeGetTime() < wakeAt) 57 | { 58 | if (GetCurrentFiber() != g_MainFiber) SwitchToFiber(g_MainFiber); return; 59 | } 60 | 61 | else if (scriptFiber) 62 | { 63 | g_CurrentScript = this; 64 | SwitchToFiber(scriptFiber); 65 | g_CurrentScript = nullptr; 66 | } 67 | 68 | else 69 | { 70 | scriptFiber = CreateFiber(NULL, [](LPVOID handler) {reinterpret_cast(handler)->Run(); }, this); 71 | } 72 | 73 | SwitchToFiber(g_MainFiber); 74 | } 75 | 76 | void Script::Run() 77 | { 78 | __try 79 | { 80 | callbackFunction(); 81 | } 82 | __except (ExpFilter(GetExceptionInformation(), GetExceptionCode())) 83 | { 84 | g_AdditionalThread.RemoveScript(this->GetCallbackFunction()); 85 | g_ScriptThread.RemoveScript(this->GetCallbackFunction()); 86 | } 87 | } 88 | 89 | void Script::Wait( uint32_t time ) 90 | { 91 | if (g_MainFiber && GetCurrentFiber() != g_MainFiber) 92 | SwitchToFiber(g_MainFiber); 93 | wakeAt = timeGetTime() + time; 94 | } 95 | 96 | void ScriptThread::DoRun() 97 | { 98 | for (auto & pair : m_scripts) 99 | { 100 | pair.second->Tick(); 101 | } 102 | } 103 | 104 | void ScriptThread::AddScript( HMODULE module, void(*fn)()) 105 | { 106 | const std::string moduleName = Utility::GetModuleNameWithoutExtension( module); 107 | 108 | if (m_scripts.find(module) != m_scripts.end()) 109 | { 110 | LOG_ERROR("Script '%s' is already registered", moduleName.c_str()); return; 111 | } 112 | else 113 | { 114 | ScriptManager::Notification(FMT("Loaded '%s'", moduleName.c_str())); 115 | LOG_PRINT("Registering script '%s' (0x%p)", moduleName.c_str(), fn); 116 | m_scripts[module] = std::make_shared