├── .gitattributes ├── .gitignore ├── .gitmodules ├── LICENSE ├── README.md ├── nSkinz.sln ├── nSkinz.vcxproj ├── nSkinz.vcxproj.filters └── src ├── Hooks ├── FireGameEvent.cpp ├── Hooks.hpp ├── PostDataUpdate.cpp └── Sequence.cpp ├── Imgui_impl_dx9 └── imgui_impl_dx9.cpp ├── SDK.hpp ├── SDK ├── CBaseClientState.hpp ├── CBaseEntity.hpp ├── ClientClass.hpp ├── DataTable.hpp ├── IAppSystem.hpp ├── IBaseClientDLL.hpp ├── IClientEntity.hpp ├── IClientEntityList.hpp ├── IGameEvent.hpp ├── IGameEventManager2.hpp ├── IInputSystem.hpp ├── ILocalize.hpp ├── IVEngineClient.hpp ├── IVModelInfoClient.hpp ├── declarations.hpp └── interfaces.hpp ├── Utilities ├── Platform.cpp ├── Platform.hpp ├── fnv_hash.hpp ├── netvar_manager.cpp ├── netvar_manager.hpp └── vmt_smart_hook.hpp ├── config.cpp ├── config.hpp ├── dllmain.cpp ├── gui.cpp ├── item_definitions.cpp ├── item_definitions.hpp ├── kit_parser.cpp ├── kit_parser.hpp ├── nSkinz.cpp ├── nSkinz.hpp ├── recv_proxy_hook.hpp ├── render.cpp ├── render.hpp ├── sticker_changer.cpp ├── sticker_changer.hpp ├── update_check.cpp └── update_check.hpp /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.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 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | [Xx]64/ 19 | [Xx]86/ 20 | [Bb]uild/ 21 | bld/ 22 | [Bb]in/ 23 | [Oo]bj/ 24 | 25 | # Visual Studio 2015 cache/options directory 26 | .vs/ 27 | # Uncomment if you have tasks that create the project's static files in wwwroot 28 | #wwwroot/ 29 | 30 | # MSTest test Results 31 | [Tt]est[Rr]esult*/ 32 | [Bb]uild[Ll]og.* 33 | 34 | # NUNIT 35 | *.VisualState.xml 36 | TestResult.xml 37 | 38 | # Build Results of an ATL Project 39 | [Dd]ebugPS/ 40 | [Rr]eleasePS/ 41 | dlldata.c 42 | 43 | # DNX 44 | project.lock.json 45 | artifacts/ 46 | 47 | *_i.c 48 | *_p.c 49 | *_i.h 50 | *.ilk 51 | *.meta 52 | *.obj 53 | *.pch 54 | *.pdb 55 | *.pgc 56 | *.pgd 57 | *.rsp 58 | *.sbr 59 | *.tlb 60 | *.tli 61 | *.tlh 62 | *.tmp 63 | *.tmp_proj 64 | *.log 65 | *.vspscc 66 | *.vssscc 67 | .builds 68 | *.pidb 69 | *.svclog 70 | *.scc 71 | 72 | # Chutzpah Test files 73 | _Chutzpah* 74 | 75 | # Visual C++ cache files 76 | ipch/ 77 | *.aps 78 | *.ncb 79 | *.opendb 80 | *.opensdf 81 | *.sdf 82 | *.cachefile 83 | *.VC.db 84 | 85 | # Visual Studio profiler 86 | *.psess 87 | *.vsp 88 | *.vspx 89 | *.sap 90 | 91 | # TFS 2012 Local Workspace 92 | $tf/ 93 | 94 | # Guidance Automation Toolkit 95 | *.gpState 96 | 97 | # ReSharper is a .NET coding add-in 98 | _ReSharper*/ 99 | *.[Rr]e[Ss]harper 100 | *.DotSettings.user 101 | 102 | # JustCode is a .NET coding add-in 103 | .JustCode 104 | 105 | # TeamCity is a build add-in 106 | _TeamCity* 107 | 108 | # DotCover is a Code Coverage Tool 109 | *.dotCover 110 | 111 | # NCrunch 112 | _NCrunch_* 113 | .*crunch*.local.xml 114 | nCrunchTemp_* 115 | 116 | # MightyMoose 117 | *.mm.* 118 | AutoTest.Net/ 119 | 120 | # Web workbench (sass) 121 | .sass-cache/ 122 | 123 | # Installshield output folder 124 | [Ee]xpress/ 125 | 126 | # DocProject is a documentation generator add-in 127 | DocProject/buildhelp/ 128 | DocProject/Help/*.HxT 129 | DocProject/Help/*.HxC 130 | DocProject/Help/*.hhc 131 | DocProject/Help/*.hhk 132 | DocProject/Help/*.hhp 133 | DocProject/Help/Html2 134 | DocProject/Help/html 135 | 136 | # Click-Once directory 137 | publish/ 138 | 139 | # Publish Web Output 140 | *.[Pp]ublish.xml 141 | *.azurePubxml 142 | 143 | # TODO: Un-comment the next line if you do not want to checkin 144 | # your web deploy settings because they may include unencrypted 145 | # passwords 146 | #*.pubxml 147 | *.publishproj 148 | 149 | # NuGet Packages 150 | *.nupkg 151 | # The packages folder can be ignored because of Package Restore 152 | **/packages/* 153 | # except build/, which is used as an MSBuild target. 154 | !**/packages/build/ 155 | # Uncomment if necessary however generally it will be regenerated when needed 156 | #!**/packages/repositories.config 157 | # NuGet v3's project.json files produces more ignoreable files 158 | *.nuget.props 159 | *.nuget.targets 160 | 161 | # Microsoft Azure Build Output 162 | csx/ 163 | *.build.csdef 164 | 165 | # Microsoft Azure Emulator 166 | ecf/ 167 | rcf/ 168 | 169 | # Windows Store app package directory 170 | AppPackages/ 171 | BundleArtifacts/ 172 | 173 | # Visual Studio cache files 174 | # files ending in .cache can be ignored 175 | *.[Cc]ache 176 | # but keep track of directories ending in .cache 177 | !*.[Cc]ache/ 178 | 179 | # Others 180 | ClientBin/ 181 | [Ss]tyle[Cc]op.* 182 | ~$* 183 | *~ 184 | *.dbmdl 185 | *.dbproj.schemaview 186 | *.pfx 187 | *.publishsettings 188 | node_modules/ 189 | orleans.codegen.cs 190 | 191 | # RIA/Silverlight projects 192 | Generated_Code/ 193 | 194 | # Backup & report files from converting an old project file 195 | # to a newer Visual Studio version. Backup files are not needed, 196 | # because we have git ;-) 197 | _UpgradeReport_Files/ 198 | Backup*/ 199 | UpgradeLog*.XML 200 | UpgradeLog*.htm 201 | 202 | # SQL Server files 203 | *.mdf 204 | *.ldf 205 | 206 | # Business Intelligence projects 207 | *.rdl.data 208 | *.bim.layout 209 | *.bim_*.settings 210 | 211 | # Microsoft Fakes 212 | FakesAssemblies/ 213 | 214 | # GhostDoc plugin setting file 215 | *.GhostDoc.xml 216 | 217 | # Node.js Tools for Visual Studio 218 | .ntvs_analysis.dat 219 | 220 | # Visual Studio 6 build log 221 | *.plg 222 | 223 | # Visual Studio 6 workspace options file 224 | *.opt 225 | 226 | # Visual Studio LightSwitch build output 227 | **/*.HTMLClient/GeneratedArtifacts 228 | **/*.DesktopClient/GeneratedArtifacts 229 | **/*.DesktopClient/ModelManifest.xml 230 | **/*.Server/GeneratedArtifacts 231 | **/*.Server/ModelManifest.xml 232 | _Pvt_Extensions 233 | 234 | # LightSwitch generated files 235 | GeneratedArtifacts/ 236 | ModelManifest.xml 237 | 238 | # Paket dependency manager 239 | .paket/paket.exe 240 | 241 | # FAKE - F# Make 242 | .fake/ 243 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "deps/imgui"] 2 | path = deps/imgui 3 | url = https://github.com/ocornut/imgui.git 4 | [submodule "deps/json"] 5 | path = deps/json 6 | url = https://github.com/nlohmann/json.git 7 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) namazso 2018 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # This project is **discontinued**. Please visit [advancedfx's fork](https://github.com/advancedfx/nSkinz) for a more up-to-date version 2 | -------------------------------------------------------------------------------- /nSkinz.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.26730.16 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nSkinz", "nSkinz.vcxproj", "{D93A638A-0449-48D2-90EB-77571D2C8304}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x86 = Debug|x86 11 | Release|x86 = Release|x86 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {D93A638A-0449-48D2-90EB-77571D2C8304}.Debug|x86.ActiveCfg = Debug|Win32 15 | {D93A638A-0449-48D2-90EB-77571D2C8304}.Debug|x86.Build.0 = Debug|Win32 16 | {D93A638A-0449-48D2-90EB-77571D2C8304}.Release|x86.ActiveCfg = Release|Win32 17 | {D93A638A-0449-48D2-90EB-77571D2C8304}.Release|x86.Build.0 = Release|Win32 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {20E550A6-6362-47AB-94C3-670B977ACD50} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /nSkinz.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | {D93A638A-0449-48D2-90EB-77571D2C8304} 66 | Win32Proj 67 | nSkinz 68 | 10.0 69 | 70 | 71 | 72 | DynamicLibrary 73 | true 74 | v142 75 | Unicode 76 | 77 | 78 | DynamicLibrary 79 | false 80 | v142 81 | true 82 | Unicode 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | true 98 | $(ProjectDir)deps\json\include;$(ProjectDir)deps\imgui;$(ProjectDir)deps\imgui\examples\directx9_example;$(IncludePath) 99 | 100 | 101 | false 102 | $(ProjectDir)deps\json\include;$(ProjectDir)deps\imgui;$(ProjectDir)deps\imgui\examples\directx9_example;$(IncludePath) 103 | 104 | 105 | 106 | 107 | 108 | Level4 109 | Disabled 110 | WIN32;_DEBUG;_WINDOWS;_USRDLL;NSKINZ_EXPORTS;%(PreprocessorDefinitions) 111 | true 112 | true 113 | true 114 | stdcpp17 115 | /Zc:threadSafeInit- %(AdditionalOptions) 116 | 117 | 118 | Windows 119 | true 120 | 121 | 122 | 123 | 124 | Level3 125 | 126 | 127 | Full 128 | true 129 | true 130 | WIN32;NDEBUG;_WINDOWS;_USRDLL;NSKINZ_EXPORTS;%(PreprocessorDefinitions) 131 | true 132 | true 133 | Speed 134 | false 135 | Default 136 | stdcpp17 137 | true 138 | ProgramDatabase 139 | false 140 | false 141 | true 142 | Fast 143 | /Zc:threadSafeInit- %(AdditionalOptions) 144 | 145 | 146 | Windows 147 | true 148 | true 149 | true 150 | 151 | 152 | 153 | 154 | 155 | -------------------------------------------------------------------------------- /nSkinz.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Hooks 6 | 7 | 8 | 9 | Dependency 10 | 11 | 12 | Dependency 13 | 14 | 15 | Utilities 16 | 17 | 18 | Utilities 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | Hooks 30 | 31 | 32 | Hooks 33 | 34 | 35 | Dependency 36 | 37 | 38 | 39 | 40 | SDK\Class 41 | 42 | 43 | SDK\Class 44 | 45 | 46 | SDK\Class 47 | 48 | 49 | SDK\Class 50 | 51 | 52 | SDK\Class 53 | 54 | 55 | SDK\Class 56 | 57 | 58 | SDK\Interface 59 | 60 | 61 | SDK\Interface 62 | 63 | 64 | SDK\Interface 65 | 66 | 67 | SDK\Interface 68 | 69 | 70 | SDK\Interface 71 | 72 | 73 | SDK\Interface 74 | 75 | 76 | SDK\Interface 77 | 78 | 79 | SDK 80 | 81 | 82 | 83 | Utilities 84 | 85 | 86 | Utilities 87 | 88 | 89 | SDK 90 | 91 | 92 | Utilities 93 | 94 | 95 | SDK 96 | 97 | 98 | Utilities 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | Hooks 109 | 110 | 111 | 112 | 113 | 114 | {65eccfc5-d06e-4ad9-9c4d-d85d8442d680} 115 | 116 | 117 | {51010c84-be5b-452b-a3a4-2e1d7be8f8b3} 118 | 119 | 120 | {ea773f6e-6f49-4132-8b2f-e1cd313697d0} 121 | 122 | 123 | {4edde6e6-abf1-4097-8ca9-8ac78f0312a6} 124 | 125 | 126 | {dcbb33bc-5f9f-45d0-9c1c-4cca665c10d4} 127 | 128 | 129 | {220d34fa-499b-4bce-9e4f-493421f1b61d} 130 | 131 | 132 | -------------------------------------------------------------------------------- /src/Hooks/FireGameEvent.cpp: -------------------------------------------------------------------------------- 1 | /* This file is part of nSkinz by namazso, licensed under the MIT license: 2 | * 3 | * MIT License 4 | * 5 | * Copyright (c) namazso 2018 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | #include "hooks.hpp" 26 | #include "../config.hpp" 27 | #include "../nSkinz.hpp" 28 | 29 | auto __fastcall hooks::SFHudDeathNoticeAndBotStatus_FireGameEvent::hooked(void* thisptr, void*, sdk::IGameEvent* event) -> void 30 | { 31 | // Filter to only the events we're interested in. 32 | if(fnv::hash_runtime(event->GetName()) == FNV("player_death") 33 | && g_engine->GetPlayerForUserID(event->GetInt("attacker")) == g_engine->GetLocalPlayer()) 34 | if(const auto icon_override = g_config.get_icon_override(event->GetString("weapon"))) 35 | event->SetString("weapon", icon_override); 36 | 37 | m_original(thisptr, nullptr, event); 38 | } 39 | 40 | hooks::SFHudDeathNoticeAndBotStatus_FireGameEvent::Fn* hooks::SFHudDeathNoticeAndBotStatus_FireGameEvent::m_original; -------------------------------------------------------------------------------- /src/Hooks/Hooks.hpp: -------------------------------------------------------------------------------- 1 | /* This file is part of nSkinz by namazso, licensed under the MIT license: 2 | * 3 | * MIT License 4 | * 5 | * Copyright (c) namazso 2018 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | #pragma once 26 | #include "../SDK.hpp" 27 | 28 | namespace hooks 29 | { 30 | struct CCSPlayer_PostDataUpdate 31 | { 32 | using Fn = void __fastcall(sdk::IClientNetworkable* thisptr, void*, int update_type); 33 | static Fn hooked; 34 | static Fn* m_original; 35 | }; 36 | 37 | struct SFHudDeathNoticeAndBotStatus_FireGameEvent 38 | { 39 | using Fn = void __fastcall(void* thisptr, void*, sdk::IGameEvent* event); 40 | static Fn hooked; 41 | static Fn* m_original; 42 | }; 43 | 44 | // NetVar Proxies 45 | 46 | extern auto __cdecl sequence_proxy_fn(const sdk::CRecvProxyData* proxy_data_const, void* entity, void* output) -> void; 47 | } 48 | -------------------------------------------------------------------------------- /src/Hooks/PostDataUpdate.cpp: -------------------------------------------------------------------------------- 1 | /* This file is part of nSkinz by namazso, licensed under the MIT license: 2 | * 3 | * MIT License 4 | * 5 | * Copyright (c) namazso 2018 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | #include "hooks.hpp" 26 | #include "../item_definitions.hpp" 27 | #include "../nSkinz.hpp" 28 | #include "../config.hpp" 29 | #include "../sticker_changer.hpp" 30 | 31 | static auto erase_override_if_exists_by_index(const int definition_index) -> void 32 | { 33 | // We have info about the item not needed to be overridden 34 | if(const auto original_item = game_data::get_weapon_info(definition_index)) 35 | { 36 | auto& icon_override_map = g_config.get_icon_override_map(); 37 | 38 | if (!original_item->icon) 39 | return; 40 | 41 | const auto override_entry = icon_override_map.find(original_item->icon); 42 | 43 | // We are overriding its icon when not needed 44 | if(override_entry != end(icon_override_map)) 45 | icon_override_map.erase(override_entry); // Remove the leftover override 46 | } 47 | } 48 | 49 | static auto apply_config_on_attributable_item(sdk::C_BaseAttributableItem* item, const item_setting* config, 50 | const unsigned xuid_low) -> void 51 | { 52 | // Force fallback values to be used. 53 | item->GetItemIDHigh() = -1; 54 | 55 | // Set the owner of the weapon to our lower XUID. (fixes StatTrak) 56 | item->GetAccountID() = xuid_low; 57 | 58 | if(config->entity_quality_index) 59 | item->GetEntityQuality() = config->entity_quality_index; 60 | 61 | if(config->custom_name[0]) 62 | strcpy_s(item->GetCustomName(), config->custom_name); 63 | 64 | if(config->paint_kit_index) 65 | item->GetFallbackPaintKit() = config->paint_kit_index; 66 | 67 | if(config->seed) 68 | item->GetFallbackSeed() = config->seed; 69 | 70 | if(config->stat_trak) 71 | item->GetFallbackStatTrak() = config->stat_trak; 72 | 73 | item->GetFallbackWear() = config->wear; 74 | 75 | auto& definition_index = item->GetItemDefinitionIndex(); 76 | 77 | auto& icon_override_map = g_config.get_icon_override_map(); 78 | 79 | if(config->definition_override_index // We need to override defindex 80 | && config->definition_override_index != definition_index) // It is not yet overridden 81 | { 82 | // We have info about what we gonna override it to 83 | if(const auto replacement_item = game_data::get_weapon_info(config->definition_override_index)) 84 | { 85 | const auto old_definition_index = definition_index; 86 | 87 | definition_index = short(config->definition_override_index); 88 | 89 | // Set the weapon model index -- required for paint kits to work on replacement items after the 29/11/2016 update. 90 | //item->GetModelIndex() = g_model_info->GetModelIndex(k_weapon_info.at(config->definition_override_index).model); 91 | item->SetModelIndex(g_model_info->GetModelIndex(replacement_item->model)); 92 | item->GetClientNetworkable()->PreDataUpdate(0); 93 | 94 | // We didn't override 0, but some actual weapon, that we have data for 95 | if(old_definition_index) 96 | { 97 | if(const auto original_item = game_data::get_weapon_info(old_definition_index)) 98 | { 99 | if(original_item->icon && replacement_item->icon) 100 | icon_override_map[original_item->icon] = replacement_item->icon; 101 | } 102 | } 103 | } 104 | } 105 | else 106 | { 107 | erase_override_if_exists_by_index(definition_index); 108 | } 109 | 110 | apply_sticker_changer(item); 111 | } 112 | 113 | static auto get_wearable_create_fn() -> sdk::CreateClientClassFn 114 | { 115 | auto clazz = g_client->GetAllClasses(); 116 | 117 | // Please, if you gonna paste it into a cheat use classids here. I use names because they 118 | // won't change in the foreseeable future and i dont need high speed, but chances are 119 | // you already have classids, so use them instead, they are faster. 120 | while(fnv::hash_runtime(clazz->m_pNetworkName) != FNV("CEconWearable")) 121 | clazz = clazz->m_pNext; 122 | 123 | return clazz->m_pCreateFn; 124 | } 125 | 126 | static auto make_glove(int entry, int serial) -> sdk::C_BaseAttributableItem* 127 | { 128 | static auto create_wearable_fn = get_wearable_create_fn(); 129 | 130 | create_wearable_fn(entry, serial); 131 | 132 | const auto glove = static_cast(g_entity_list->GetClientEntity(entry)); 133 | assert(glove); 134 | 135 | // He he 136 | { 137 | static auto set_abs_origin_addr = platform::find_pattern(get_client_name(), "\x55\x8B\xEC\x83\xE4\xF8\x51\x53\x56\x57\x8B\xF1", "xxxxxxxxxxxx"); 138 | 139 | const auto set_abs_origin_fn = reinterpret_cast(set_abs_origin_addr); 140 | 141 | static constexpr sdk::Vector new_pos = { 10000.f, 10000.f, 10000.f }; 142 | 143 | set_abs_origin_fn(glove, new_pos); 144 | } 145 | 146 | return glove; 147 | } 148 | 149 | static auto post_data_update_start(sdk::C_BasePlayer* local) -> void 150 | { 151 | const auto local_index = local->GetIndex(); 152 | 153 | /*if(auto player_resource = *g_player_resource) 154 | { 155 | player_resource->GetCoins()[local_index] = 890; 156 | player_resource->GetMusicKits()[local_index] = 3; 157 | player_resource->GetRanks()[local_index] = 1; 158 | player_resource->GetWins()[local_index] = 1337; 159 | }*/ 160 | 161 | sdk::player_info_t player_info; 162 | if(!g_engine->GetPlayerInfo(local_index, &player_info)) 163 | return; 164 | 165 | // Handle glove config 166 | { 167 | const auto wearables = local->GetWearables(); 168 | 169 | const auto glove_config = g_config.get_by_definition_index(GLOVE_T_SIDE); 170 | 171 | static auto glove_handle = sdk::CBaseHandle(0); 172 | 173 | auto glove = get_entity_from_handle(wearables[0]); 174 | 175 | if(!glove) // There is no glove 176 | { 177 | // Try to get our last created glove 178 | const auto our_glove = get_entity_from_handle(glove_handle); 179 | 180 | if(our_glove) // Our glove still exists 181 | { 182 | wearables[0] = glove_handle; 183 | glove = our_glove; 184 | } 185 | } 186 | 187 | if(local->GetLifeState() != sdk::LifeState::ALIVE) 188 | { 189 | // We are dead but we have a glove, destroy it 190 | if(glove) 191 | { 192 | glove->GetClientNetworkable()->SetDestroyedOnRecreateEntities(); 193 | glove->GetClientNetworkable()->Release(); 194 | } 195 | 196 | return; 197 | } 198 | 199 | if(glove_config && glove_config->definition_override_index) 200 | { 201 | // We don't have a glove, but we should 202 | if(!glove) 203 | { 204 | const auto entry = g_entity_list->GetHighestEntityIndex() + 1; 205 | const auto serial = rand() % 0x1000; 206 | 207 | glove = make_glove(entry, serial); 208 | 209 | wearables[0] = entry | serial << 16; 210 | 211 | // Let's store it in case we somehow lose it. 212 | glove_handle = wearables[0]; 213 | } 214 | 215 | // Thanks, Beakers 216 | glove->GetIndex() = -1; 217 | 218 | apply_config_on_attributable_item(glove, glove_config, player_info.xuid_low); 219 | } 220 | } 221 | 222 | // Handle weapon configs 223 | { 224 | auto& weapons = local->GetWeapons(); 225 | 226 | for(auto weapon_handle : weapons) 227 | { 228 | if(weapon_handle == sdk::INVALID_EHANDLE_INDEX) 229 | break; 230 | 231 | auto weapon = get_entity_from_handle(weapon_handle); 232 | 233 | if(!weapon) 234 | continue; 235 | 236 | auto& definition_index = weapon->GetItemDefinitionIndex(); 237 | 238 | // All knives are terrorist knives. 239 | if(const auto active_conf = g_config.get_by_definition_index(is_knife(definition_index) ? WEAPON_KNIFE : definition_index)) 240 | apply_config_on_attributable_item(weapon, active_conf, player_info.xuid_low); 241 | else 242 | erase_override_if_exists_by_index(definition_index); 243 | } 244 | } 245 | 246 | const auto view_model = get_entity_from_handle(local->GetViewModel()); 247 | 248 | if(!view_model) 249 | return; 250 | 251 | const auto view_model_weapon = get_entity_from_handle(view_model->GetWeapon()); 252 | 253 | if(!view_model_weapon) 254 | return; 255 | 256 | const auto override_info = game_data::get_weapon_info(view_model_weapon->GetItemDefinitionIndex()); 257 | 258 | if(!override_info) 259 | return; 260 | 261 | const auto override_model_index = g_model_info->GetModelIndex(override_info->model); 262 | view_model->GetModelIndex() = override_model_index; 263 | 264 | const auto world_model = get_entity_from_handle(view_model_weapon->GetWeaponWorldModel()); 265 | 266 | if(!world_model) 267 | return; 268 | 269 | world_model->GetModelIndex() = override_model_index + 1; 270 | } 271 | 272 | auto __fastcall hooks::CCSPlayer_PostDataUpdate::hooked(sdk::IClientNetworkable* thisptr, void*, int update_type) -> void 273 | { 274 | post_data_update_start(static_cast(thisptr)); 275 | 276 | return m_original(thisptr, nullptr, update_type); 277 | } 278 | 279 | hooks::CCSPlayer_PostDataUpdate::Fn* hooks::CCSPlayer_PostDataUpdate::m_original; -------------------------------------------------------------------------------- /src/Hooks/Sequence.cpp: -------------------------------------------------------------------------------- 1 | /* This file is part of nSkinz by namazso, licensed under the MIT license: 2 | * 3 | * MIT License 4 | * 5 | * Copyright (c) namazso 2018 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | #include "hooks.hpp" 26 | #include "../nSkinz.hpp" 27 | #include "../config.hpp" 28 | 29 | static auto random_sequence(const int low, const int high) -> int 30 | { 31 | return rand() % (high - low + 1) + low; 32 | } 33 | 34 | // This only fixes if the original knife was a default knife. 35 | // The best would be having a function that converts original knife's sequence 36 | // into some generic enum, then another function that generates a sequence 37 | // from the sequences of the new knife. I won't write that. 38 | static auto get_new_animation(const fnv::hash model, const int sequence) -> int 39 | { 40 | enum ESequence 41 | { 42 | SEQUENCE_DEFAULT_DRAW = 0, 43 | SEQUENCE_DEFAULT_IDLE1 = 1, 44 | SEQUENCE_DEFAULT_IDLE2 = 2, 45 | SEQUENCE_DEFAULT_LIGHT_MISS1 = 3, 46 | SEQUENCE_DEFAULT_LIGHT_MISS2 = 4, 47 | SEQUENCE_DEFAULT_HEAVY_MISS1 = 9, 48 | SEQUENCE_DEFAULT_HEAVY_HIT1 = 10, 49 | SEQUENCE_DEFAULT_HEAVY_BACKSTAB = 11, 50 | SEQUENCE_DEFAULT_LOOKAT01 = 12, 51 | 52 | SEQUENCE_BUTTERFLY_DRAW = 0, 53 | SEQUENCE_BUTTERFLY_DRAW2 = 1, 54 | SEQUENCE_BUTTERFLY_LOOKAT01 = 13, 55 | SEQUENCE_BUTTERFLY_LOOKAT03 = 15, 56 | 57 | SEQUENCE_FALCHION_IDLE1 = 1, 58 | SEQUENCE_FALCHION_HEAVY_MISS1 = 8, 59 | SEQUENCE_FALCHION_HEAVY_MISS1_NOFLIP = 9, 60 | SEQUENCE_FALCHION_LOOKAT01 = 12, 61 | SEQUENCE_FALCHION_LOOKAT02 = 13, 62 | 63 | SEQUENCE_CSS_LOOKAT01 = 14, 64 | SEQUENCE_CSS_LOOKAT02 = 15, 65 | 66 | SEQUENCE_DAGGERS_IDLE1 = 1, 67 | SEQUENCE_DAGGERS_LIGHT_MISS1 = 2, 68 | SEQUENCE_DAGGERS_LIGHT_MISS5 = 6, 69 | SEQUENCE_DAGGERS_HEAVY_MISS2 = 11, 70 | SEQUENCE_DAGGERS_HEAVY_MISS1 = 12, 71 | 72 | SEQUENCE_BOWIE_IDLE1 = 1, 73 | }; 74 | 75 | // Hashes for best performance. 76 | switch(model) 77 | { 78 | case FNV("models/weapons/v_knife_butterfly.mdl"): 79 | { 80 | switch(sequence) 81 | { 82 | case SEQUENCE_DEFAULT_DRAW: 83 | return random_sequence(SEQUENCE_BUTTERFLY_DRAW, SEQUENCE_BUTTERFLY_DRAW2); 84 | case SEQUENCE_DEFAULT_LOOKAT01: 85 | return random_sequence(SEQUENCE_BUTTERFLY_LOOKAT01, SEQUENCE_BUTTERFLY_LOOKAT03); 86 | default: 87 | return sequence + 1; 88 | } 89 | } 90 | case FNV("models/weapons/v_knife_falchion_advanced.mdl"): 91 | { 92 | switch(sequence) 93 | { 94 | case SEQUENCE_DEFAULT_IDLE2: 95 | return SEQUENCE_FALCHION_IDLE1; 96 | case SEQUENCE_DEFAULT_HEAVY_MISS1: 97 | return random_sequence(SEQUENCE_FALCHION_HEAVY_MISS1, SEQUENCE_FALCHION_HEAVY_MISS1_NOFLIP); 98 | case SEQUENCE_DEFAULT_LOOKAT01: 99 | return random_sequence(SEQUENCE_FALCHION_LOOKAT01, SEQUENCE_FALCHION_LOOKAT02); 100 | case SEQUENCE_DEFAULT_DRAW: 101 | case SEQUENCE_DEFAULT_IDLE1: 102 | return sequence; 103 | default: 104 | return sequence - 1; 105 | } 106 | } 107 | case FNV("models/weapons/v_knife_css.mdl"): 108 | { 109 | switch (sequence) 110 | { 111 | case SEQUENCE_DEFAULT_LOOKAT01: 112 | return random_sequence(SEQUENCE_CSS_LOOKAT01, SEQUENCE_CSS_LOOKAT02); 113 | default: 114 | return sequence; 115 | } 116 | } 117 | case FNV("models/weapons/v_knife_push.mdl"): 118 | { 119 | switch(sequence) 120 | { 121 | case SEQUENCE_DEFAULT_IDLE2: 122 | return SEQUENCE_DAGGERS_IDLE1; 123 | case SEQUENCE_DEFAULT_LIGHT_MISS1: 124 | case SEQUENCE_DEFAULT_LIGHT_MISS2: 125 | return random_sequence(SEQUENCE_DAGGERS_LIGHT_MISS1, SEQUENCE_DAGGERS_LIGHT_MISS5); 126 | case SEQUENCE_DEFAULT_HEAVY_MISS1: 127 | return random_sequence(SEQUENCE_DAGGERS_HEAVY_MISS2, SEQUENCE_DAGGERS_HEAVY_MISS1); 128 | case SEQUENCE_DEFAULT_HEAVY_HIT1: 129 | case SEQUENCE_DEFAULT_HEAVY_BACKSTAB: 130 | case SEQUENCE_DEFAULT_LOOKAT01: 131 | return sequence + 3; 132 | case SEQUENCE_DEFAULT_DRAW: 133 | case SEQUENCE_DEFAULT_IDLE1: 134 | return sequence; 135 | default: 136 | return sequence + 2; 137 | } 138 | } 139 | case FNV("models/weapons/v_knife_survival_bowie.mdl"): 140 | { 141 | switch(sequence) 142 | { 143 | case SEQUENCE_DEFAULT_DRAW: 144 | case SEQUENCE_DEFAULT_IDLE1: 145 | return sequence; 146 | case SEQUENCE_DEFAULT_IDLE2: 147 | return SEQUENCE_BOWIE_IDLE1; 148 | default: 149 | return sequence - 1; 150 | } 151 | } 152 | case FNV("models/weapons/v_knife_ursus.mdl"): 153 | case FNV("models/weapons/v_knife_cord.mdl"): 154 | case FNV("models/weapons/v_knife_canis.mdl"): 155 | case FNV("models/weapons/v_knife_outdoor.mdl"): 156 | case FNV("models/weapons/v_knife_skeleton.mdl"): 157 | { 158 | switch (sequence) 159 | { 160 | case SEQUENCE_DEFAULT_DRAW: 161 | return random_sequence(SEQUENCE_BUTTERFLY_DRAW, SEQUENCE_BUTTERFLY_DRAW2); 162 | case SEQUENCE_DEFAULT_LOOKAT01: 163 | return random_sequence(SEQUENCE_BUTTERFLY_LOOKAT01, 14); 164 | default: 165 | return sequence + 1; 166 | } 167 | } 168 | case FNV("models/weapons/v_knife_stiletto.mdl"): 169 | { 170 | switch (sequence) 171 | { 172 | case SEQUENCE_DEFAULT_LOOKAT01: 173 | return random_sequence(12, 13); 174 | default: 175 | return sequence; 176 | } 177 | } 178 | case FNV("models/weapons/v_knife_widowmaker.mdl"): 179 | { 180 | switch (sequence) 181 | { 182 | case SEQUENCE_DEFAULT_LOOKAT01: 183 | return random_sequence(14, 15); 184 | default: 185 | return sequence; 186 | } 187 | } 188 | default: 189 | return sequence; 190 | } 191 | } 192 | 193 | static auto do_sequence_remapping(sdk::CRecvProxyData* data, sdk::C_BaseViewModel* entity) -> void 194 | { 195 | const auto local = static_cast(g_entity_list->GetClientEntity(g_engine->GetLocalPlayer())); 196 | 197 | if(!local) 198 | return; 199 | 200 | if(local->GetLifeState() != sdk::LifeState::ALIVE) 201 | return; 202 | 203 | const auto owner = get_entity_from_handle(entity->GetOwner()); 204 | 205 | if(owner != local) 206 | return; 207 | 208 | const auto view_model_weapon = get_entity_from_handle(entity->GetWeapon()); 209 | 210 | if(!view_model_weapon) 211 | return; 212 | 213 | const auto weapon_info = game_data::get_weapon_info(view_model_weapon->GetItemDefinitionIndex()); 214 | 215 | if(!weapon_info) 216 | return; 217 | 218 | const auto override_model = weapon_info->model; 219 | 220 | auto& sequence = data->m_Value.m_Int; 221 | sequence = get_new_animation(fnv::hash_runtime(override_model), sequence); 222 | } 223 | 224 | // Replacement function that will be called when the view model animation sequence changes. 225 | auto __cdecl hooks::sequence_proxy_fn(const sdk::CRecvProxyData* proxy_data_const, void* entity, void* output) -> void 226 | { 227 | // Ensure our other dynamic object hooks are in place. 228 | // Must do this from a game thread. 229 | ensure_dynamic_hooks(); 230 | 231 | static auto original_fn = g_sequence_hook->get_original_function(); 232 | 233 | // Remove the constness from the proxy data allowing us to make changes. 234 | const auto proxy_data = const_cast(proxy_data_const); 235 | 236 | const auto view_model = static_cast(entity); 237 | 238 | do_sequence_remapping(proxy_data, view_model); 239 | 240 | // Call the original function with our edited data. 241 | original_fn(proxy_data_const, entity, output); 242 | } 243 | -------------------------------------------------------------------------------- /src/Imgui_impl_dx9/imgui_impl_dx9.cpp: -------------------------------------------------------------------------------- 1 | // ImGui Win32 + DirectX9 binding 2 | // In this binding, ImTextureID is used to store a 'LPDIRECT3DTEXTURE9' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. 3 | 4 | // You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. 5 | // If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown(). 6 | // If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp. 7 | // https://github.com/ocornut/imgui 8 | 9 | #include 10 | #include "imgui_impl_dx9.h" 11 | 12 | // DirectX 13 | #include 14 | #define DIRECTINPUT_VERSION 0x0800 15 | #include 16 | 17 | // Data 18 | static HWND g_hWnd = 0; 19 | static INT64 g_Time = 0; 20 | static INT64 g_TicksPerSecond = 0; 21 | static LPDIRECT3DDEVICE9 g_pd3dDevice = NULL; 22 | static LPDIRECT3DVERTEXBUFFER9 g_pVB = NULL; 23 | static LPDIRECT3DINDEXBUFFER9 g_pIB = NULL; 24 | static LPDIRECT3DTEXTURE9 g_FontTexture = NULL; 25 | static int g_VertexBufferSize = 5000, g_IndexBufferSize = 10000; 26 | 27 | struct CUSTOMVERTEX 28 | { 29 | float pos[3]; 30 | D3DCOLOR col; 31 | float uv[2]; 32 | }; 33 | #define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1) 34 | 35 | // This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) 36 | // If text or lines are blurry when integrating ImGui in your engine: 37 | // - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) 38 | void ImGui_ImplDX9_RenderDrawLists(ImDrawData* draw_data) 39 | { 40 | // Avoid rendering when minimized 41 | ImGuiIO& io = ImGui::GetIO(); 42 | if (io.DisplaySize.x <= 0.0f || io.DisplaySize.y <= 0.0f) 43 | return; 44 | 45 | // Create and grow buffers if needed 46 | if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) 47 | { 48 | if (g_pVB) { g_pVB->Release(); g_pVB = NULL; } 49 | g_VertexBufferSize = draw_data->TotalVtxCount + 5000; 50 | if (g_pd3dDevice->CreateVertexBuffer(g_VertexBufferSize * sizeof(CUSTOMVERTEX), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &g_pVB, NULL) < 0) 51 | return; 52 | } 53 | if (!g_pIB || g_IndexBufferSize < draw_data->TotalIdxCount) 54 | { 55 | if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } 56 | g_IndexBufferSize = draw_data->TotalIdxCount + 10000; 57 | if (g_pd3dDevice->CreateIndexBuffer(g_IndexBufferSize * sizeof(ImDrawIdx), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, sizeof(ImDrawIdx) == 2 ? D3DFMT_INDEX16 : D3DFMT_INDEX32, D3DPOOL_DEFAULT, &g_pIB, NULL) < 0) 58 | return; 59 | } 60 | 61 | // Backup the DX9 state 62 | IDirect3DStateBlock9* d3d9_state_block = NULL; 63 | if (g_pd3dDevice->CreateStateBlock(D3DSBT_PIXELSTATE, &d3d9_state_block) < 0) 64 | return; 65 | 66 | // Copy and convert all vertices into a single contiguous buffer 67 | CUSTOMVERTEX* vtx_dst; 68 | ImDrawIdx* idx_dst; 69 | if (g_pVB->Lock(0, (UINT)(draw_data->TotalVtxCount * sizeof(CUSTOMVERTEX)), (void**)&vtx_dst, D3DLOCK_DISCARD) < 0) 70 | return; 71 | if (g_pIB->Lock(0, (UINT)(draw_data->TotalIdxCount * sizeof(ImDrawIdx)), (void**)&idx_dst, D3DLOCK_DISCARD) < 0) 72 | return; 73 | for (int n = 0; n < draw_data->CmdListsCount; n++) 74 | { 75 | const ImDrawList* cmd_list = draw_data->CmdLists[n]; 76 | const ImDrawVert* vtx_src = cmd_list->VtxBuffer.Data; 77 | for (int i = 0; i < cmd_list->VtxBuffer.Size; i++) 78 | { 79 | vtx_dst->pos[0] = vtx_src->pos.x; 80 | vtx_dst->pos[1] = vtx_src->pos.y; 81 | vtx_dst->pos[2] = 0.0f; 82 | vtx_dst->col = (vtx_src->col & 0xFF00FF00) | ((vtx_src->col & 0xFF0000)>>16) | ((vtx_src->col & 0xFF) << 16); // RGBA --> ARGB for DirectX9 83 | vtx_dst->uv[0] = vtx_src->uv.x; 84 | vtx_dst->uv[1] = vtx_src->uv.y; 85 | vtx_dst++; 86 | vtx_src++; 87 | } 88 | memcpy(idx_dst, cmd_list->IdxBuffer.Data, cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx)); 89 | idx_dst += cmd_list->IdxBuffer.Size; 90 | } 91 | g_pVB->Unlock(); 92 | g_pIB->Unlock(); 93 | g_pd3dDevice->SetStreamSource(0, g_pVB, 0, sizeof(CUSTOMVERTEX)); 94 | g_pd3dDevice->SetIndices(g_pIB); 95 | g_pd3dDevice->SetFVF(D3DFVF_CUSTOMVERTEX); 96 | 97 | // Setup viewport 98 | D3DVIEWPORT9 vp; 99 | vp.X = vp.Y = 0; 100 | vp.Width = (DWORD)io.DisplaySize.x; 101 | vp.Height = (DWORD)io.DisplaySize.y; 102 | vp.MinZ = 0.0f; 103 | vp.MaxZ = 1.0f; 104 | g_pd3dDevice->SetViewport(&vp); 105 | 106 | // Setup render state: fixed-pipeline, alpha-blending, no face culling, no depth testing 107 | g_pd3dDevice->SetPixelShader(NULL); 108 | g_pd3dDevice->SetVertexShader(NULL); 109 | g_pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); 110 | g_pd3dDevice->SetRenderState(D3DRS_LIGHTING, false); 111 | g_pd3dDevice->SetRenderState(D3DRS_ZENABLE, false); 112 | g_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, true); 113 | g_pd3dDevice->SetRenderState(D3DRS_ALPHATESTENABLE, false); 114 | g_pd3dDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD); 115 | g_pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); 116 | g_pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); 117 | g_pd3dDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, true); 118 | g_pd3dDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE); 119 | g_pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); 120 | g_pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE); 121 | g_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE); 122 | g_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); 123 | g_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE); 124 | g_pd3dDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); 125 | g_pd3dDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); 126 | 127 | // Setup orthographic projection matrix 128 | // Being agnostic of whether or can be used, we aren't relying on D3DXMatrixIdentity()/D3DXMatrixOrthoOffCenterLH() or DirectX::XMMatrixIdentity()/DirectX::XMMatrixOrthographicOffCenterLH() 129 | { 130 | const float L = 0.5f, R = io.DisplaySize.x+0.5f, T = 0.5f, B = io.DisplaySize.y+0.5f; 131 | D3DMATRIX mat_identity = { { 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f } }; 132 | D3DMATRIX mat_projection = 133 | { 134 | 2.0f/(R-L), 0.0f, 0.0f, 0.0f, 135 | 0.0f, 2.0f/(T-B), 0.0f, 0.0f, 136 | 0.0f, 0.0f, 0.5f, 0.0f, 137 | (L+R)/(L-R), (T+B)/(B-T), 0.5f, 1.0f, 138 | }; 139 | g_pd3dDevice->SetTransform(D3DTS_WORLD, &mat_identity); 140 | g_pd3dDevice->SetTransform(D3DTS_VIEW, &mat_identity); 141 | g_pd3dDevice->SetTransform(D3DTS_PROJECTION, &mat_projection); 142 | } 143 | 144 | // Render command lists 145 | int vtx_offset = 0; 146 | int idx_offset = 0; 147 | for (int n = 0; n < draw_data->CmdListsCount; n++) 148 | { 149 | const ImDrawList* cmd_list = draw_data->CmdLists[n]; 150 | for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++) 151 | { 152 | const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i]; 153 | if (pcmd->UserCallback) 154 | { 155 | pcmd->UserCallback(cmd_list, pcmd); 156 | } 157 | else 158 | { 159 | const RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w }; 160 | g_pd3dDevice->SetTexture(0, (LPDIRECT3DTEXTURE9)pcmd->TextureId); 161 | g_pd3dDevice->SetScissorRect(&r); 162 | g_pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, vtx_offset, 0, (UINT)cmd_list->VtxBuffer.Size, idx_offset, pcmd->ElemCount/3); 163 | } 164 | idx_offset += pcmd->ElemCount; 165 | } 166 | vtx_offset += cmd_list->VtxBuffer.Size; 167 | } 168 | 169 | // Restore the DX9 state 170 | d3d9_state_block->Apply(); 171 | d3d9_state_block->Release(); 172 | } 173 | 174 | static bool IsAnyMouseButtonDown() 175 | { 176 | ImGuiIO& io = ImGui::GetIO(); 177 | for (int n = 0; n < ARRAYSIZE(io.MouseDown); n++) 178 | if (io.MouseDown[n]) 179 | return true; 180 | return false; 181 | } 182 | 183 | // We use the Win32 capture API (GetCapture/SetCapture/ReleaseCapture) to be able to read mouse coordinations when dragging mouse outside of our window bounds. 184 | IMGUI_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) 185 | { 186 | ImGuiIO& io = ImGui::GetIO(); 187 | switch (msg) 188 | { 189 | case WM_LBUTTONDOWN: 190 | case WM_RBUTTONDOWN: 191 | case WM_MBUTTONDOWN: 192 | { 193 | int button = 0; 194 | if (msg == WM_LBUTTONDOWN) button = 0; 195 | if (msg == WM_RBUTTONDOWN) button = 1; 196 | if (msg == WM_MBUTTONDOWN) button = 2; 197 | if (!IsAnyMouseButtonDown() && GetCapture() == NULL) 198 | SetCapture(hwnd); 199 | io.MouseDown[button] = true; 200 | return 0; 201 | } 202 | case WM_LBUTTONUP: 203 | case WM_RBUTTONUP: 204 | case WM_MBUTTONUP: 205 | { 206 | int button = 0; 207 | if (msg == WM_LBUTTONUP) button = 0; 208 | if (msg == WM_RBUTTONUP) button = 1; 209 | if (msg == WM_MBUTTONUP) button = 2; 210 | io.MouseDown[button] = false; 211 | if (!IsAnyMouseButtonDown() && GetCapture() == hwnd) 212 | ReleaseCapture(); 213 | return 0; 214 | } 215 | case WM_MOUSEWHEEL: 216 | io.MouseWheel += GET_WHEEL_DELTA_WPARAM(wParam) > 0 ? +1.0f : -1.0f; 217 | return 0; 218 | case WM_MOUSEMOVE: 219 | io.MousePos.x = (signed short)(lParam); 220 | io.MousePos.y = (signed short)(lParam >> 16); 221 | return 0; 222 | case WM_KEYDOWN: 223 | case WM_SYSKEYDOWN: 224 | if (wParam < 256) 225 | io.KeysDown[wParam] = 1; 226 | return 0; 227 | case WM_KEYUP: 228 | case WM_SYSKEYUP: 229 | if (wParam < 256) 230 | io.KeysDown[wParam] = 0; 231 | return 0; 232 | case WM_CHAR: 233 | // You can also use ToAscii()+GetKeyboardState() to retrieve characters. 234 | if (wParam > 0 && wParam < 0x10000) 235 | io.AddInputCharacter((unsigned short)wParam); 236 | return 0; 237 | } 238 | return 0; 239 | } 240 | 241 | bool ImGui_ImplDX9_Init(void* hwnd, IDirect3DDevice9* device) 242 | { 243 | g_hWnd = (HWND)hwnd; 244 | g_pd3dDevice = device; 245 | 246 | if (!QueryPerformanceFrequency((LARGE_INTEGER *)&g_TicksPerSecond)) 247 | return false; 248 | if (!QueryPerformanceCounter((LARGE_INTEGER *)&g_Time)) 249 | return false; 250 | 251 | ImGuiIO& io = ImGui::GetIO(); 252 | io.KeyMap[ImGuiKey_Tab] = VK_TAB; // Keyboard mapping. ImGui will use those indices to peek into the io.KeyDown[] array that we will update during the application lifetime. 253 | io.KeyMap[ImGuiKey_LeftArrow] = VK_LEFT; 254 | io.KeyMap[ImGuiKey_RightArrow] = VK_RIGHT; 255 | io.KeyMap[ImGuiKey_UpArrow] = VK_UP; 256 | io.KeyMap[ImGuiKey_DownArrow] = VK_DOWN; 257 | io.KeyMap[ImGuiKey_PageUp] = VK_PRIOR; 258 | io.KeyMap[ImGuiKey_PageDown] = VK_NEXT; 259 | io.KeyMap[ImGuiKey_Home] = VK_HOME; 260 | io.KeyMap[ImGuiKey_End] = VK_END; 261 | io.KeyMap[ImGuiKey_Delete] = VK_DELETE; 262 | io.KeyMap[ImGuiKey_Backspace] = VK_BACK; 263 | io.KeyMap[ImGuiKey_Enter] = VK_RETURN; 264 | io.KeyMap[ImGuiKey_Escape] = VK_ESCAPE; 265 | io.KeyMap[ImGuiKey_A] = 'A'; 266 | io.KeyMap[ImGuiKey_C] = 'C'; 267 | io.KeyMap[ImGuiKey_V] = 'V'; 268 | io.KeyMap[ImGuiKey_X] = 'X'; 269 | io.KeyMap[ImGuiKey_Y] = 'Y'; 270 | io.KeyMap[ImGuiKey_Z] = 'Z'; 271 | 272 | io.RenderDrawListsFn = ImGui_ImplDX9_RenderDrawLists; // Alternatively you can set this to NULL and call ImGui::GetDrawData() after ImGui::Render() to get the same ImDrawData pointer. 273 | io.ImeWindowHandle = g_hWnd; 274 | 275 | return true; 276 | } 277 | 278 | void ImGui_ImplDX9_Shutdown() 279 | { 280 | ImGui_ImplDX9_InvalidateDeviceObjects(); 281 | ImGui::Shutdown(); 282 | g_pd3dDevice = NULL; 283 | g_hWnd = 0; 284 | } 285 | 286 | static bool ImGui_ImplDX9_CreateFontsTexture() 287 | { 288 | // Build texture atlas 289 | ImGuiIO& io = ImGui::GetIO(); 290 | unsigned char* pixels; 291 | int width, height, bytes_per_pixel; 292 | io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height, &bytes_per_pixel); 293 | 294 | // Upload texture to graphics system 295 | g_FontTexture = NULL; 296 | if (g_pd3dDevice->CreateTexture(width, height, 1, D3DUSAGE_DYNAMIC, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &g_FontTexture, NULL) < 0) 297 | return false; 298 | D3DLOCKED_RECT tex_locked_rect; 299 | if (g_FontTexture->LockRect(0, &tex_locked_rect, NULL, 0) != D3D_OK) 300 | return false; 301 | for (int y = 0; y < height; y++) 302 | memcpy((unsigned char *)tex_locked_rect.pBits + tex_locked_rect.Pitch * y, pixels + (width * bytes_per_pixel) * y, (width * bytes_per_pixel)); 303 | g_FontTexture->UnlockRect(0); 304 | 305 | // Store our identifier 306 | io.Fonts->TexID = (void *)g_FontTexture; 307 | 308 | return true; 309 | } 310 | 311 | bool ImGui_ImplDX9_CreateDeviceObjects() 312 | { 313 | if (!g_pd3dDevice) 314 | return false; 315 | if (!ImGui_ImplDX9_CreateFontsTexture()) 316 | return false; 317 | return true; 318 | } 319 | 320 | void ImGui_ImplDX9_InvalidateDeviceObjects() 321 | { 322 | if (!g_pd3dDevice) 323 | return; 324 | if (g_pVB) 325 | { 326 | g_pVB->Release(); 327 | g_pVB = NULL; 328 | } 329 | if (g_pIB) 330 | { 331 | g_pIB->Release(); 332 | g_pIB = NULL; 333 | } 334 | 335 | // At this point note that we set ImGui::GetIO().Fonts->TexID to be == g_FontTexture, so clear both. 336 | ImGuiIO& io = ImGui::GetIO(); 337 | IM_ASSERT(g_FontTexture == io.Fonts->TexID); 338 | if (g_FontTexture) 339 | g_FontTexture->Release(); 340 | g_FontTexture = NULL; 341 | io.Fonts->TexID = NULL; 342 | } 343 | 344 | void ImGui_ImplDX9_NewFrame() 345 | { 346 | if (!g_FontTexture) 347 | ImGui_ImplDX9_CreateDeviceObjects(); 348 | 349 | ImGuiIO& io = ImGui::GetIO(); 350 | 351 | // Setup display size (every frame to accommodate for window resizing) 352 | RECT rect; 353 | GetClientRect(g_hWnd, &rect); 354 | io.DisplaySize = ImVec2((float)(rect.right - rect.left), (float)(rect.bottom - rect.top)); 355 | 356 | // Setup time step 357 | INT64 current_time; 358 | QueryPerformanceCounter((LARGE_INTEGER *)¤t_time); 359 | io.DeltaTime = (float)(current_time - g_Time) / g_TicksPerSecond; 360 | g_Time = current_time; 361 | 362 | // Read keyboard modifiers inputs 363 | io.KeyCtrl = (GetKeyState(VK_CONTROL) & 0x8000) != 0; 364 | io.KeyShift = (GetKeyState(VK_SHIFT) & 0x8000) != 0; 365 | io.KeyAlt = (GetKeyState(VK_MENU) & 0x8000) != 0; 366 | io.KeySuper = false; 367 | // io.KeysDown : filled by WM_KEYDOWN/WM_KEYUP events 368 | // io.MousePos : filled by WM_MOUSEMOVE events 369 | // io.MouseDown : filled by WM_*BUTTON* events 370 | // io.MouseWheel : filled by WM_MOUSEWHEEL events 371 | 372 | // Set OS mouse position if requested last frame by io.WantMoveMouse flag (used when io.NavMovesTrue is enabled by user and using directional navigation) 373 | if (io.WantMoveMouse) 374 | { 375 | POINT pos = { (int)io.MousePos.x, (int)io.MousePos.y }; 376 | ClientToScreen(g_hWnd, &pos); 377 | SetCursorPos(pos.x, pos.y); 378 | } 379 | 380 | // Hide OS mouse cursor if ImGui is drawing it 381 | if (io.MouseDrawCursor) 382 | SetCursor(NULL); 383 | 384 | // Start the frame 385 | ImGui::NewFrame(); 386 | } 387 | -------------------------------------------------------------------------------- /src/SDK.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "SDK/declarations.hpp" 3 | #include "SDK/DataTable.hpp" 4 | #include "SDK/CBaseClientState.hpp" 5 | #include "SDK/ClientClass.hpp" 6 | #include "SDK/IGameEvent.hpp" 7 | #include "SDK/IClientEntity.hpp" 8 | #include "SDK/CBaseEntity.hpp" 9 | 10 | #include "SDK/IBaseClientDLL.hpp" 11 | #include "SDK/IClientEntityList.hpp" 12 | #include "SDK/IGameEventManager2.hpp" 13 | #include "SDK/IVEngineClient.hpp" 14 | #include "SDK/IVModelInfoClient.hpp" 15 | #include "SDK/ILocalize.hpp" 16 | #include "SDK/IInputSystem.hpp" 17 | 18 | #include "SDK/interfaces.hpp" 19 | 20 | #include "Utilities/vmt_smart_hook.hpp" 21 | #include "Utilities/platform.hpp" 22 | #include "Utilities/netvar_manager.hpp" 23 | -------------------------------------------------------------------------------- /src/SDK/CBaseClientState.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | namespace sdk 5 | { 6 | class CBaseClientState 7 | { 8 | public: 9 | void ForceFullUpdate() 10 | { 11 | *reinterpret_cast(std::uintptr_t(this) + 0x174) = -1; 12 | }; 13 | }; 14 | } -------------------------------------------------------------------------------- /src/SDK/CBaseEntity.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "declarations.hpp" 3 | #include "IClientEntity.hpp" 4 | #include "../Utilities/netvar_manager.hpp" 5 | 6 | namespace sdk 7 | { 8 | class C_BaseEntity : public IClientEntity 9 | { 10 | public: 11 | NETVAR_OFFSET(GetIndex, "CBaseEntity", "m_bIsAutoaimTarget", +0x4, int); 12 | NETVAR(GetModelIndex, "CBaseEntity", "m_nModelIndex", unsigned); 13 | 14 | void SetModelIndex(const int index) 15 | { 16 | get_vfunc(this, 75)(this, index); 17 | } 18 | }; 19 | 20 | class C_BaseCombatCharacter : public C_BaseEntity 21 | { 22 | public: 23 | NETVAR(GetWeapons, "CBaseCombatCharacter", "m_hMyWeapons", std::array); 24 | PNETVAR(GetWearables, "CBaseCombatCharacter", "m_hMyWearables", CBaseHandle); 25 | }; 26 | 27 | class C_BasePlayer : public C_BaseCombatCharacter 28 | { 29 | public: 30 | NETVAR(GetLifeState, "CBasePlayer", "m_lifeState", LifeState); 31 | NETVAR(GetViewModel, "CBasePlayer", "m_hViewModel[0]", CBaseHandle); 32 | }; 33 | 34 | class C_BaseCombatWeapon : public C_BaseEntity 35 | { 36 | public: 37 | NETVAR(GetViewModelIndex, "CBaseCombatWeapon", "m_iViewModelIndex", int); 38 | NETVAR(GetWorldModelIndex, "CBaseCombatWeapon", "m_iWorldModelIndex", int); 39 | NETVAR(GetWorldDroppedModelIndex, "CBaseCombatWeapon", "m_iWorldDroppedModelIndex", int); 40 | NETVAR(GetWeaponWorldModel, "CBaseCombatWeapon", "m_hWeaponWorldModel", CBaseHandle); 41 | }; 42 | 43 | class C_BaseAttributableItem : public C_BaseCombatWeapon 44 | { 45 | public: 46 | NETVAR(GetAccountID, "CBaseAttributableItem", "m_iAccountID", int); 47 | NETVAR(GetItemDefinitionIndex, "CBaseAttributableItem", "m_iItemDefinitionIndex", short); 48 | NETVAR(GetItemIDHigh, "CBaseAttributableItem", "m_iItemIDHigh", int); 49 | NETVAR(GetEntityQuality, "CBaseAttributableItem", "m_iEntityQuality", int); 50 | NETVAR(GetCustomName, "CBaseAttributableItem", "m_szCustomName", char[32]); 51 | NETVAR(GetFallbackPaintKit, "CBaseAttributableItem", "m_nFallbackPaintKit", unsigned); 52 | NETVAR(GetFallbackSeed, "CBaseAttributableItem", "m_nFallbackSeed", unsigned); 53 | NETVAR(GetFallbackWear, "CBaseAttributableItem", "m_flFallbackWear", float); 54 | NETVAR(GetFallbackStatTrak, "CBaseAttributableItem", "m_nFallbackStatTrak", unsigned); 55 | }; 56 | 57 | class C_BaseViewModel : public C_BaseEntity 58 | { 59 | public: 60 | NETVAR(GetOwner, "CBaseViewModel", "m_hOwner", CBaseHandle); 61 | NETVAR(GetWeapon, "CBaseViewModel", "m_hWeapon", CBaseHandle); 62 | NETPROP(GetSequenceProp, "CBaseViewModel", "m_nSequence"); 63 | }; 64 | 65 | class C_PlayerResource 66 | { 67 | public: 68 | NETPROP(GetTeamProp, "CPlayerResource", "m_iTeam"); 69 | }; 70 | 71 | class C_CS_PlayerResource : public C_PlayerResource 72 | { 73 | public: 74 | NETVAR(GetRanks, "CCSPlayerResource", "m_iCompetitiveRanking", int[MAX_PLAYERS]); 75 | NETVAR(GetWins, "CCSPlayerResource", "m_iCompetitiveWins", int[MAX_PLAYERS]); 76 | NETVAR(GetClanTags, "CCSPlayerResource", "m_szClan", char[MAX_PLAYERS][32]); 77 | NETVAR(GetCoins, "CCSPlayerResource", "m_nActiveCoinRank", unsigned[MAX_PLAYERS]); 78 | NETVAR(GetMusicKits, "CCSPlayerResource", "m_nMusicID", unsigned[MAX_PLAYERS]); 79 | }; 80 | 81 | class CBaseWeaponWorldModel : public C_BaseEntity 82 | { 83 | }; 84 | } -------------------------------------------------------------------------------- /src/SDK/ClientClass.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "declarations.hpp" 3 | 4 | namespace sdk 5 | { 6 | class ClientClass 7 | { 8 | public: 9 | CreateClientClassFn m_pCreateFn; 10 | CreateEventFn m_pCreateEventFn; 11 | const char* m_pNetworkName; 12 | RecvTable* m_pRecvTable; 13 | ClientClass* m_pNext; 14 | int m_ClassID; 15 | }; 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/SDK/DataTable.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "declarations.hpp" 3 | #include 4 | 5 | namespace sdk 6 | { 7 | struct DVariant 8 | { 9 | union 10 | { 11 | float m_Float; 12 | long m_Int; 13 | char* m_pString; 14 | void* m_pData; 15 | Vector m_Vector; 16 | int64_t m_Int64; 17 | }; 18 | 19 | int m_Type; 20 | }; 21 | 22 | struct CRecvProxyData 23 | { 24 | const RecvProp* m_pRecvProp; 25 | DVariant m_Value; 26 | int m_iElement; 27 | int m_ObjectID; 28 | }; 29 | 30 | enum SendPropType : int 31 | { 32 | DPT_Int = 0, 33 | DPT_Float, 34 | DPT_Vector, 35 | DPT_VectorXY, 36 | DPT_String, 37 | DPT_Array, 38 | DPT_DataTable, 39 | DPT_Int64, 40 | DPT_NUMSendPropTypes 41 | }; 42 | 43 | class RecvProp 44 | { 45 | public: 46 | char* m_pVarName; 47 | SendPropType m_RecvType; 48 | int m_Flags; 49 | int m_StringBufferSize; 50 | bool m_bInsideArray; 51 | const void* m_pExtraData; 52 | RecvProp* m_pArrayProp; 53 | void* m_ArrayLengthProxy; 54 | RecvVarProxyFn m_ProxyFn; 55 | void* m_DataTableProxyFn; 56 | RecvTable* m_pDataTable; 57 | int m_Offset; 58 | int m_ElementStride; 59 | int m_nElements; 60 | const char* m_pParentArrayPropName; 61 | }; 62 | 63 | class RecvTable 64 | { 65 | public: 66 | RecvProp* m_pProps; 67 | int m_nProps; 68 | void* m_pDecoder; 69 | char* m_pNetTableName; 70 | bool m_bInitialized; 71 | bool m_bInMainList; 72 | }; 73 | } 74 | -------------------------------------------------------------------------------- /src/SDK/IAppSystem.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace sdk 4 | { 5 | enum InitReturnVal_t 6 | { 7 | INIT_FAILED = 0, 8 | INIT_OK, 9 | 10 | INIT_LAST_VAL, 11 | }; 12 | 13 | enum AppSystemTier_t 14 | { 15 | APP_SYSTEM_TIER0 = 0, 16 | APP_SYSTEM_TIER1, 17 | APP_SYSTEM_TIER2, 18 | APP_SYSTEM_TIER3, 19 | 20 | APP_SYSTEM_TIER_OTHER, 21 | }; 22 | 23 | class IAppSystem 24 | { 25 | public: 26 | virtual bool Connect(CreateInterfaceFn factory) = 0; 27 | virtual void Disconnect() = 0; 28 | virtual void* QueryInterface(const char* pInterfaceName) = 0; 29 | virtual InitReturnVal_t Init() = 0; 30 | virtual void Shutdown() = 0; 31 | virtual const AppSystemInfo_t* GetDependencies() = 0; 32 | virtual AppSystemTier_t GetTier() = 0; 33 | virtual void Reconnect(CreateInterfaceFn factory, const char* pInterfaceName) = 0; 34 | virtual bool IsSingleton() = 0; 35 | }; 36 | } -------------------------------------------------------------------------------- /src/SDK/IBaseClientDLL.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace sdk 4 | { 5 | enum ClientFrameStage_t : int 6 | { 7 | FRAME_UNDEFINED = -1, 8 | FRAME_START, 9 | FRAME_NET_UPDATE_START, 10 | FRAME_NET_UPDATE_POSTDATAUPDATE_START, 11 | FRAME_NET_UPDATE_POSTDATAUPDATE_END, 12 | FRAME_NET_UPDATE_END, 13 | FRAME_RENDER_START, 14 | FRAME_RENDER_END 15 | }; 16 | 17 | class IBaseClientDLL 18 | { 19 | public: 20 | ClientClass* GetAllClasses() 21 | { 22 | return get_vfunc(this, 8)(this); 23 | } 24 | }; 25 | 26 | } -------------------------------------------------------------------------------- /src/SDK/IClientEntity.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace sdk 4 | { 5 | class IHandleEntity 6 | { 7 | public: 8 | virtual ~IHandleEntity() {} 9 | virtual void SetRefEHandle(const CBaseHandle& handle) = 0; 10 | virtual const CBaseHandle& GetRefEHandle() const = 0; 11 | }; 12 | 13 | class IClientUnknown : public IHandleEntity 14 | { 15 | public: 16 | virtual ICollideable* GetCollideable() = 0; 17 | virtual IClientNetworkable* GetClientNetworkable() = 0; 18 | virtual IClientRenderable* GetClientRenderable() = 0; 19 | virtual IClientEntity* GetIClientEntity() = 0; 20 | virtual C_BaseEntity* GetBaseEntity() = 0; 21 | virtual IClientThinkable* GetClientThinkable() = 0; 22 | //virtual IClientModelRenderable* GetClientModelRenderable() = 0; 23 | virtual IClientAlphaProperty* GetClientAlphaProperty() = 0; 24 | }; 25 | 26 | class IClientThinkable 27 | { 28 | public: 29 | virtual ~IClientThinkable() {}; 30 | }; 31 | 32 | class IClientRenderable 33 | { 34 | public: 35 | virtual ~IClientRenderable() {}; 36 | }; 37 | 38 | class IClientNetworkable 39 | { 40 | public: 41 | virtual IClientUnknown* GetIClientUnknown() = 0; 42 | virtual void Release() = 0; 43 | virtual ClientClass* GetClientClass() = 0; 44 | virtual void NotifyShouldTransmit(int state) = 0; 45 | virtual void OnPreDataChanged(int updateType) = 0; 46 | virtual void OnDataChanged(int updateType) = 0; 47 | virtual void PreDataUpdate(int updateType) = 0; 48 | virtual void PostDataUpdate(int updateType) = 0; 49 | virtual void OnDataUnchangedInPVS() = 0; 50 | virtual bool IsDormant() = 0; 51 | virtual int EntIndex() const = 0; 52 | virtual void ReceiveMessage(int classID, bf_read& msg) = 0; 53 | virtual void* GetDataTableBasePtr() = 0; 54 | virtual void SetDestroyedOnRecreateEntities() = 0; 55 | }; 56 | 57 | class IClientEntity : public IClientUnknown, public IClientRenderable, public IClientNetworkable, public IClientThinkable 58 | { 59 | public: 60 | virtual ~IClientEntity() {}; 61 | }; 62 | } -------------------------------------------------------------------------------- /src/SDK/IClientEntityList.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace sdk 4 | { 5 | class IClientEntityList 6 | { 7 | public: 8 | virtual IClientNetworkable* GetClientNetworkable(int iEnt) = 0; 9 | virtual IClientNetworkable* GetClientNetworkableFromHandle(CBaseHandle hEnt) = 0; 10 | virtual IClientUnknown* GetClientUnknownFromHandle(CBaseHandle hEnt) = 0; 11 | virtual IClientEntity* GetClientEntity(int iEnt) = 0; 12 | virtual IClientEntity* GetClientEntityFromHandle(CBaseHandle hEnt) = 0; 13 | virtual int NumberOfEntities(bool bIncludeNonNetworkable) = 0; 14 | virtual int GetHighestEntityIndex() = 0; 15 | virtual void SetMaxEntities(int iMax) = 0; 16 | virtual int GetMaxEntities() = 0; 17 | }; 18 | } -------------------------------------------------------------------------------- /src/SDK/IGameEvent.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | namespace sdk 5 | { 6 | class IGameEvent 7 | { 8 | public: 9 | virtual ~IGameEvent() {}; 10 | virtual const char* GetName() const = 0; 11 | 12 | virtual bool IsReliable() const = 0; 13 | virtual bool IsLocal() const = 0; 14 | virtual bool IsEmpty(const char* keyname = nullptr) = 0; 15 | 16 | virtual bool GetBool(const char* keyname = nullptr, bool default_value = false) = 0; 17 | virtual int GetInt(const char* keyname = nullptr, int default_value = 0) = 0; 18 | virtual uint64_t GetUint64(const char* keyname = nullptr, uint64_t default_value = 0) = 0; 19 | virtual float GetFloat(const char* keyname = nullptr, float default_value = 0.0f) = 0; 20 | virtual const char* GetString(const char* keyname = nullptr, const char* default_value = "") = 0; 21 | virtual const wchar_t* GetWString(const char* keyname = nullptr, const wchar_t* default_value = L"") = 0; 22 | virtual const void* GetPtr(const char* keyname = nullptr, const void* default_values = nullptr) = 0; 23 | 24 | virtual void SetBool(const char* keyname, bool value) = 0; 25 | virtual void SetInt(const char* keyname, int value) = 0; 26 | virtual void SetUint64(const char* keyname, uint64_t value) = 0; 27 | virtual void SetFloat(const char* keyname, float value) = 0; 28 | virtual void SetString(const char* keyname, const char* value) = 0; 29 | virtual void SetWString(const char* keyname, const wchar_t* value) = 0; 30 | virtual void SetPtr(const char* keyname, const void* value) = 0; 31 | }; 32 | 33 | } -------------------------------------------------------------------------------- /src/SDK/IGameEventManager2.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace sdk 4 | { 5 | class IGameEventListener2 6 | { 7 | public: 8 | virtual ~IGameEventListener2() {}; 9 | virtual void FireGameEvent(IGameEvent* event) = 0; 10 | virtual int GetEventDebugID() = 0; 11 | }; 12 | 13 | class IGameEventManager2 14 | { 15 | public: 16 | virtual ~IGameEventManager2() {}; 17 | virtual int LoadEventsFromFile(const char* filename) = 0; 18 | virtual void Reset() = 0; 19 | virtual bool AddListener(IGameEventListener2* listener, const char* name, bool serverside) = 0; 20 | virtual bool FindListener(IGameEventListener2* listener, const char* name) = 0; 21 | virtual void RemoveListener(IGameEventListener2* listener) = 0; 22 | virtual void AddListenerGlobal(IGameEventListener2* listener, bool serverside) = 0; 23 | virtual IGameEvent* CreateEvent(const char* name, bool force = false, int* cookie = nullptr) = 0; 24 | virtual bool FireEvent(IGameEvent* event, bool bDontBroadcast = false) = 0; 25 | virtual bool FireEventClientSide(IGameEvent* event) = 0; 26 | virtual IGameEvent* DuplicateEvent(IGameEvent* event) = 0; 27 | virtual void FreeEvent(IGameEvent* event) = 0; 28 | virtual bool SerializeEvent(IGameEvent* event, bf_write* buffer) = 0; 29 | virtual IGameEvent* UnserializeEvent(bf_read* buffer) = 0; 30 | virtual KeyValues* GetEventDataTypes(IGameEvent* event) = 0; 31 | }; 32 | } -------------------------------------------------------------------------------- /src/SDK/IInputSystem.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace sdk 4 | { 5 | class IInputSystem 6 | { 7 | public: 8 | void EnableInput(bool bEnable) 9 | { 10 | return get_vfunc(this, 11)(this, bEnable); 11 | } 12 | 13 | void*& get_window() 14 | { 15 | static uint32_t offset = 0; 16 | if (!offset) 17 | offset = *(uint32_t*)((*(char***)this)[10] + 5); 18 | return *(void**)((char*)this + offset); 19 | } 20 | }; 21 | 22 | } -------------------------------------------------------------------------------- /src/SDK/ILocalize.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "IAppSystem.hpp" 3 | 4 | namespace sdk 5 | { 6 | class ILocalizeTextQuery 7 | { 8 | public: 9 | virtual int ComputeTextWidth(const wchar_t* pString) = 0; 10 | }; 11 | 12 | class ILocalizationChangeCallback 13 | { 14 | public: 15 | virtual void OnLocalizationChanged() = 0; 16 | }; 17 | 18 | class ILocalize : public IAppSystem 19 | { 20 | public: 21 | virtual bool AddFile(const char* fileName, const char* pPathID = nullptr, bool bIncludeFallbackSearchPaths = false) = 0; 22 | virtual void RemoveAll() = 0; 23 | virtual wchar_t* Find(const char* tokenName) = 0; 24 | virtual const wchar_t* FindSafe(const char* tokenName) = 0; 25 | virtual int ConvertANSIToUnicode(const char* ansi, wchar_t* unicode, int unicodeBufferSizeInBytes) = 0; 26 | virtual int ConvertUnicodeToANSI(const wchar_t* unicode, char* ansi, int ansiBufferSize) = 0; 27 | virtual LocalizeStringIndex_t FindIndex(const char* tokenName) = 0; 28 | virtual void ConstructString(wchar_t* unicodeOuput, int unicodeBufferSizeInBytes, const wchar_t* formatString, int numFormatParameters, ...) = 0; 29 | virtual const char* GetNameByIndex(LocalizeStringIndex_t index) = 0; 30 | virtual wchar_t* GetValueByIndex(LocalizeStringIndex_t index) = 0; 31 | }; 32 | } -------------------------------------------------------------------------------- /src/SDK/IVEngineClient.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "declarations.hpp" 3 | 4 | namespace sdk 5 | { 6 | typedef struct player_info_s 7 | { 8 | private: 9 | int64_t unknown; 10 | public: 11 | union 12 | { 13 | int64_t xuid; 14 | 15 | struct 16 | { 17 | int xuid_low; 18 | int xuid_high; 19 | }; 20 | }; 21 | 22 | char name[MAX_PLAYER_NAME_LENGTH]; 23 | int userid; 24 | int m_nUserID; 25 | char guid[SIGNED_GUID_LEN + 1]; 26 | unsigned int friendsid; 27 | char friendsname[MAX_PLAYER_NAME_LENGTH]; 28 | bool fakeplayer; 29 | bool ishltv; 30 | unsigned int customfiles[4]; 31 | unsigned char filesdownloaded; 32 | } player_info_t; 33 | 34 | class IVEngineClient 35 | { 36 | public: 37 | bool GetPlayerInfo(const int index, player_info_t* player_info) 38 | { 39 | return get_vfunc(this, 8)(this, index, player_info); 40 | } 41 | 42 | int GetPlayerForUserID(const int userid) 43 | { 44 | return get_vfunc(this, 9)(this, userid); 45 | } 46 | 47 | int GetLocalPlayer() 48 | { 49 | return get_vfunc(this, 12)(this); 50 | } 51 | 52 | bool IsInGame() 53 | { 54 | return get_vfunc(this, 26)(this); 55 | } 56 | 57 | bool IsConnected() 58 | { 59 | return get_vfunc(this, 27)(this); 60 | } 61 | 62 | void ClientCmd_Unrestricted(const char* command, const bool delayed = false) 63 | { 64 | return get_vfunc(this, 114)(this, command, delayed); 65 | } 66 | }; 67 | 68 | } -------------------------------------------------------------------------------- /src/SDK/IVModelInfoClient.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace sdk 4 | { 5 | class IVModelInfoClient 6 | { 7 | public: 8 | virtual ~IVModelInfoClient() {}; 9 | virtual const model_t* GetModel(int modelindex) const = 0; 10 | virtual int GetModelIndex(const char* name) const = 0; 11 | virtual const char* GetModelName(const model_t* model) const = 0; 12 | }; 13 | } -------------------------------------------------------------------------------- /src/SDK/declarations.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | template 6 | Fn get_vfunc(void* class_base, const std::size_t index) 7 | { 8 | return (*reinterpret_cast(class_base))[index]; 9 | } 10 | 11 | namespace sdk 12 | { 13 | class C_BaseEntity; 14 | class ClientClass; 15 | class ClientClass; 16 | class IClientAlphaProperty; 17 | class IClientEntity; 18 | class IClientEntity; 19 | class IClientNetworkable; 20 | class IClientNetworkable; 21 | class IClientRenderable; 22 | class IClientThinkable; 23 | class IClientUnknown; 24 | class ICollideable; 25 | class IGameEvent; 26 | class KeyValues; 27 | class RecvProp; 28 | class RecvTable; 29 | 30 | struct AppSystemInfo_t; 31 | struct CRecvProxyData; 32 | struct bf_read; 33 | struct bf_read; 34 | struct bf_write; 35 | struct model_t; 36 | 37 | using CBaseHandle = unsigned long; 38 | using CreateClientClassFn = IClientNetworkable* (*)(int, int); 39 | using CreateEventFn = IClientNetworkable* (*)(); 40 | using CreateInterfaceFn = void* (*)(const char*, int*); 41 | using LocalizeStringIndex_t = unsigned; 42 | using RecvVarProxyFn = void(__cdecl *)(const CRecvProxyData*, void*, void*); 43 | using Vector = std::array; 44 | 45 | constexpr static auto INVALID_EHANDLE_INDEX = 0xFFFFFFFF; 46 | constexpr static auto MAX_PLAYER_NAME_LENGTH = 128; 47 | constexpr static auto SIGNED_GUID_LEN = 32; 48 | constexpr static auto MAX_WEAPONS = 48; 49 | constexpr static auto MAX_PLAYERS = 65; // Only cstrike and csgo 50 | 51 | enum class LifeState 52 | { 53 | ALIVE = 0, 54 | DYING, 55 | DEAD, 56 | RESPAWNABLE, 57 | DISCARDBODY, 58 | }; 59 | } -------------------------------------------------------------------------------- /src/SDK/interfaces.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "CBaseClientState.hpp" 3 | #include "IBaseClientDLL.hpp" 4 | #include "IClientEntityList.hpp" 5 | #include "IGameEventManager2.hpp" 6 | #include "ILocalize.hpp" 7 | #include "IVEngineClient.hpp" 8 | #include "IVModelInfoClient.hpp" 9 | 10 | #define CLIENT_DLL_INTERFACE_VERSION "VClient018" 11 | extern sdk::IBaseClientDLL* g_client; 12 | 13 | #define VCLIENTENTITYLIST_INTERFACE_VERSION "VClientEntityList003" 14 | extern sdk::IClientEntityList* g_entity_list; 15 | 16 | #define VENGINE_CLIENT_INTERFACE_VERSION "VEngineClient014" 17 | extern sdk::IVEngineClient* g_engine; 18 | 19 | #define VMODELINFO_CLIENT_INTERFACE_VERSION "VModelInfoClient004" 20 | extern sdk::IVModelInfoClient* g_model_info; 21 | 22 | #define INTERFACEVERSION_GAMEEVENTSMANAGER2 "GAMEEVENTSMANAGER002" 23 | extern sdk::IGameEventManager2* g_game_event_manager; 24 | 25 | #define ILOCALIZE_CLIENT_INTERFACE_VERSION "Localize_001" 26 | extern sdk::ILocalize* g_localize; 27 | 28 | #define INPUTSYSTEM_INTERFACE_VERSION "InputSystemVersion001" 29 | extern sdk::IInputSystem* g_input_system; 30 | 31 | extern sdk::CBaseClientState** g_client_state; 32 | extern sdk::C_CS_PlayerResource** g_player_resource; -------------------------------------------------------------------------------- /src/Utilities/Platform.cpp: -------------------------------------------------------------------------------- 1 | /* This file is part of nSkinz by namazso, licensed under the MIT license: 2 | * 3 | * MIT License 4 | * 5 | * Copyright (c) namazso 2018 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | #include "../SDK.hpp" 26 | #include "platform.hpp" 27 | #include 28 | #include 29 | 30 | // Platform tools for windows. Maybe I'll make linux ones too 31 | 32 | #include 33 | #include 34 | 35 | auto platform::get_export(const char* module_name, const char* export_name) -> void* 36 | { 37 | HMODULE mod; 38 | while(!((mod = GetModuleHandleA(module_name)))) 39 | Sleep(100); 40 | 41 | return reinterpret_cast(GetProcAddress(mod, export_name)); 42 | } 43 | 44 | auto platform::get_interface(const char* module_name, const char* interface_name) -> void* 45 | { 46 | const auto addr = get_export(module_name, "CreateInterface"); 47 | const auto create_interface_fn = reinterpret_cast(addr); 48 | 49 | return create_interface_fn(interface_name, nullptr); 50 | } 51 | 52 | auto platform::get_module_info(const char* module_name) -> std::pair 53 | { 54 | const auto module = GetModuleHandleA(module_name); 55 | if (!module) 56 | return { 0, 0 }; 57 | MODULEINFO module_info; 58 | K32GetModuleInformation(GetCurrentProcess(), module, &module_info, sizeof(MODULEINFO)); 59 | return { std::uintptr_t(module_info.lpBaseOfDll), module_info.SizeOfImage }; 60 | } 61 | 62 | /*auto platform::find_pattern(const char* module_name, const char* pattern, const char* mask) -> std::uintptr_t 63 | { 64 | MODULEINFO module_info = {}; 65 | K32GetModuleInformation(GetCurrentProcess(), GetModuleHandleA(module_name), &module_info, sizeof(MODULEINFO)); 66 | 67 | const auto address = reinterpret_cast(module_info.lpBaseOfDll); 68 | const auto size = module_info.SizeOfImage; 69 | 70 | std::vector> signature; 71 | 72 | for (auto i = 0u; mask[i]; i++) 73 | signature.push_back(std::make_pair(pattern[i], mask[i] == 'x')); 74 | 75 | auto ret = std::search(address, address + size, signature.begin(), signature.end(), 76 | [](std::uint8_t curr, std::pair curr_pattern) 77 | { 78 | return (!curr_pattern.second) || curr == curr_pattern.first; 79 | }); 80 | 81 | return ret == address + size ? 0 : std::uintptr_t(ret); 82 | }*/ 83 | 84 | auto platform::is_code_ptr(void* ptr) -> bool 85 | { 86 | constexpr const DWORD protect_flags = PAGE_EXECUTE | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY; 87 | 88 | MEMORY_BASIC_INFORMATION out; 89 | VirtualQuery(ptr, &out, sizeof out); 90 | 91 | return out.Type 92 | && !(out.Protect & (PAGE_GUARD | PAGE_NOACCESS)) 93 | && out.Protect & protect_flags; 94 | } 95 | -------------------------------------------------------------------------------- /src/Utilities/Platform.hpp: -------------------------------------------------------------------------------- 1 | /* This file is part of nSkinz by namazso, licensed under the MIT license: 2 | * 3 | * MIT License 4 | * 5 | * Copyright (c) namazso 2018 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | #pragma once 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | namespace platform 32 | { 33 | namespace detail 34 | { 35 | constexpr auto process_pattern_byte(const std::pair pair) -> std::pair 36 | { 37 | return { std::uint8_t(pair.first), pair.second == 'x' }; 38 | } 39 | 40 | template 41 | constexpr auto select_pattern_byte(const char(&pattern)[N], const char(&mask)[N], std::size_t n) -> std::pair 42 | { 43 | return { pattern[n], mask[n] }; 44 | } 45 | 46 | template 47 | struct sig_processor {}; 48 | 49 | template 50 | struct sig_processor> 51 | { 52 | template 53 | static constexpr auto process(const char(&pattern)[N], const char(&mask)[N]) -> std::array, N> 54 | { 55 | return { process_pattern_byte(select_pattern_byte(pattern, mask, Indices))... }; 56 | } 57 | }; 58 | } 59 | 60 | auto get_interface(const char* module_name, const char* interface_name) -> void*; 61 | auto get_module_info(const char* module_name) -> std::pair; 62 | //auto find_pattern(const char* module_name, const char* pattern, const char* mask) -> std::uintptr_t; 63 | auto is_code_ptr(void* ptr) -> bool; 64 | auto get_export(const char* module_name, const char* export_name) -> void*; 65 | 66 | template 67 | auto find_pattern(const char* module_name, const char(&pattern)[N], const char(&mask)[N]) -> std::uintptr_t 68 | { 69 | const std::array, N> signature = detail::sig_processor>::process(pattern, mask); 70 | 71 | const auto info = get_module_info(module_name); 72 | const auto address = reinterpret_cast(info.first); 73 | const auto size = info.second; 74 | 75 | const auto ret = std::search(address, address + size, signature.begin(), signature.end(), 76 | [](std::uint8_t curr, std::pair curr_pattern) 77 | { 78 | return (!curr_pattern.second) || curr == curr_pattern.first; 79 | }); 80 | 81 | return ret == address + size ? 0 : std::uintptr_t(ret); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/Utilities/fnv_hash.hpp: -------------------------------------------------------------------------------- 1 | /* This file is part of nSkinz by namazso, licensed under the MIT license: 2 | * 3 | * MIT License 4 | * 5 | * Copyright (c) namazso 2018 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | #pragma once 26 | #include 27 | 28 | namespace detail 29 | { 30 | template 31 | struct size_dependant_data 32 | { 33 | using type = Type; 34 | constexpr static auto k_offset_basis = OffsetBasis; 35 | constexpr static auto k_prime = Prime; 36 | }; 37 | 38 | template 39 | struct size_selector; 40 | 41 | template <> 42 | struct size_selector<32> 43 | { 44 | using type = size_dependant_data; 45 | }; 46 | 47 | template <> 48 | struct size_selector<64> 49 | { 50 | using type = size_dependant_data; 51 | }; 52 | 53 | // Implements FNV-1a hash algorithm 54 | template 55 | class fnv_hash 56 | { 57 | private: 58 | using data_t = typename size_selector::type; 59 | 60 | public: 61 | using hash = typename data_t::type; 62 | 63 | private: 64 | constexpr static auto k_offset_basis = data_t::k_offset_basis; 65 | constexpr static auto k_prime = data_t::k_prime; 66 | 67 | public: 68 | template 69 | static __forceinline constexpr auto hash_constexpr(const char(&str)[N], const std::size_t size = N) -> hash 70 | { 71 | return static_cast(1ull * (size == 1 72 | ? (k_offset_basis ^ str[0]) 73 | : (hash_constexpr(str, size - 1) ^ str[size - 1])) * k_prime); 74 | } 75 | 76 | static auto __forceinline hash_runtime(const char* str) -> hash 77 | { 78 | auto result = k_offset_basis; 79 | do 80 | { 81 | result ^= *str++; 82 | result *= k_prime; 83 | } while(*(str - 1) != '\0'); 84 | 85 | return result; 86 | } 87 | }; 88 | } 89 | 90 | using fnv = ::detail::fnv_hash; 91 | 92 | #define FNV(str) (std::integral_constant::value) -------------------------------------------------------------------------------- /src/Utilities/netvar_manager.cpp: -------------------------------------------------------------------------------- 1 | /* This file is part of nSkinz by namazso, licensed under the MIT license: 2 | * 3 | * MIT License 4 | * 5 | * Copyright (c) namazso 2018 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | #include "netvar_manager.hpp" 26 | #include "../SDK.hpp" 27 | #include 28 | 29 | //#define DUMP_NETVARS 30 | 31 | #ifdef DUMP_NETVARS 32 | #define IF_DUMPING(...) __VA_ARGS__ 33 | #else 34 | #define IF_DUMPING(...) 35 | #endif 36 | 37 | IF_DUMPING(static FILE* s_fp;) 38 | 39 | netvar_manager::netvar_manager() 40 | { 41 | IF_DUMPING(fopen_s(&s_fp, "netvar_dump.txt", "w");) 42 | for (auto clazz = g_client->GetAllClasses(); clazz; clazz = clazz->m_pNext) 43 | if (clazz->m_pRecvTable) 44 | dump_recursive(clazz->m_pNetworkName, clazz->m_pRecvTable, 0); 45 | IF_DUMPING(fclose(s_fp);) 46 | } 47 | 48 | auto netvar_manager::dump_recursive(const char* base_class, sdk::RecvTable* table, const std::uint16_t offset) -> void 49 | { 50 | for (auto i = 0; i < table->m_nProps; ++i) 51 | { 52 | const auto prop_ptr = &table->m_pProps[i]; 53 | 54 | //Skip trash array items 55 | if (!prop_ptr || isdigit(prop_ptr->m_pVarName[0])) 56 | continue; 57 | 58 | //We dont care about the base class, we already know that 59 | if (fnv::hash_runtime(prop_ptr->m_pVarName) == FNV("baseclass")) 60 | continue; 61 | 62 | if (prop_ptr->m_RecvType == sdk::DPT_DataTable && 63 | prop_ptr->m_pDataTable != nullptr && 64 | prop_ptr->m_pDataTable->m_pNetTableName[0] == 'D') // Skip shitty tables 65 | { 66 | dump_recursive(base_class, prop_ptr->m_pDataTable, std::uint16_t(offset + prop_ptr->m_Offset)); 67 | } 68 | 69 | char hash_name[256]; 70 | 71 | strcpy_s(hash_name, base_class); 72 | strcat_s(hash_name, "->"); 73 | strcat_s(hash_name, prop_ptr->m_pVarName); 74 | 75 | const auto hash = fnv::hash_runtime(hash_name); 76 | const auto total_offset = std::uint16_t(offset + prop_ptr->m_Offset); 77 | 78 | IF_DUMPING(fprintf(s_fp, "%s\t0x%04X\t%s\n", base_class, total_offset, prop_ptr->m_pVarName);) 79 | 80 | m_props[hash] = 81 | { 82 | prop_ptr, 83 | total_offset 84 | }; 85 | } 86 | } -------------------------------------------------------------------------------- /src/Utilities/netvar_manager.hpp: -------------------------------------------------------------------------------- 1 | /* This file is part of nSkinz by namazso, licensed under the MIT license: 2 | * 3 | * MIT License 4 | * 5 | * Copyright (c) namazso 2018 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | #pragma once 26 | #include "../SDK/DataTable.hpp" 27 | #include "fnv_hash.hpp" 28 | #include 29 | #include 30 | 31 | class netvar_manager 32 | { 33 | private: 34 | struct stored_data 35 | { 36 | sdk::RecvProp* prop_ptr; 37 | std::uint16_t class_relative_offset; 38 | }; 39 | 40 | public: 41 | // Return a const instance, others shouldnt modify this. 42 | static auto get() -> const netvar_manager& 43 | { 44 | static netvar_manager instance; 45 | return instance; 46 | } 47 | 48 | auto get_offset(const fnv::hash hash) const -> std::uint16_t 49 | { 50 | return m_props.at(hash).class_relative_offset; 51 | } 52 | 53 | auto get_prop(const fnv::hash hash) const -> sdk::RecvProp* 54 | { 55 | return m_props.at(hash).prop_ptr; 56 | } 57 | 58 | // Prevent instruction cache pollution caused by automatic 59 | // inlining of `get` and get_offset every netvar usage when 60 | // there are a lot of netvars 61 | __declspec(noinline) static auto get_offset_by_hash(const fnv::hash hash) -> std::uint16_t 62 | { 63 | return get().get_offset(hash); 64 | } 65 | 66 | template 67 | static auto get_offset_by_hash_cached() -> std::uint16_t 68 | { 69 | static auto offset = std::uint16_t(0); 70 | if(!offset) 71 | offset = get_offset_by_hash(Hash); 72 | return offset; 73 | } 74 | 75 | private: 76 | netvar_manager(); 77 | auto dump_recursive(const char* base_class, sdk::RecvTable* table, std::uint16_t offset) -> void; 78 | 79 | private: 80 | std::map m_props; 81 | }; 82 | 83 | 84 | #define PNETVAR_OFFSET(funcname, class_name, var_name, offset, ...) \ 85 | auto funcname() -> std::add_pointer_t<__VA_ARGS__> \ 86 | { \ 87 | constexpr auto hash = fnv::hash_constexpr(class_name "->" var_name); \ 88 | const auto addr = std::uintptr_t(this) + offset + netvar_manager::get_offset_by_hash_cached(); \ 89 | return reinterpret_cast>(addr); \ 90 | } 91 | 92 | #define PNETVAR(funcname, class_name, var_name, ...) \ 93 | PNETVAR_OFFSET(funcname, class_name, var_name, 0, __VA_ARGS__) 94 | 95 | #define NETVAR_OFFSET(funcname, class_name, var_name, offset, ...) \ 96 | auto funcname() -> std::add_lvalue_reference_t<__VA_ARGS__> \ 97 | { \ 98 | constexpr auto hash = fnv::hash_constexpr(class_name "->" var_name); \ 99 | const auto addr = std::uintptr_t(this) + offset + netvar_manager::get_offset_by_hash_cached(); \ 100 | return *reinterpret_cast>(addr); \ 101 | } 102 | 103 | #define NETVAR(funcname, class_name, var_name, ...) \ 104 | NETVAR_OFFSET(funcname, class_name, var_name, 0, __VA_ARGS__) 105 | 106 | #define NETPROP(funcname, class_name, var_name) \ 107 | static auto funcname() -> RecvProp* \ 108 | { \ 109 | constexpr auto hash = fnv::hash_constexpr(class_name "->" var_name); \ 110 | static sdk::RecvProp* prop_ptr; \ 111 | if(!prop_ptr) prop_ptr = netvar_manager::get().get_prop(hash); \ 112 | return prop_ptr; \ 113 | } -------------------------------------------------------------------------------- /src/Utilities/vmt_smart_hook.hpp: -------------------------------------------------------------------------------- 1 | /* This file is part of nSkinz by namazso, licensed under the MIT license: 2 | * 3 | * MIT License 4 | * 5 | * Copyright (c) namazso 2018 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | #pragma once 26 | #include "platform.hpp" 27 | #include 28 | #include 29 | 30 | using proc_t = void(*)(); 31 | 32 | class vmt_base_hook 33 | { 34 | protected: 35 | constexpr vmt_base_hook() = default; 36 | 37 | public: 38 | ~vmt_base_hook() 39 | { 40 | if(m_new_vmt) 41 | delete[] (m_new_vmt - 1); 42 | } 43 | 44 | vmt_base_hook(const vmt_base_hook&) = delete; 45 | vmt_base_hook(vmt_base_hook&&) = delete; 46 | 47 | vmt_base_hook& operator=(const vmt_base_hook&) = delete; 48 | vmt_base_hook& operator=(vmt_base_hook&&) = delete; 49 | 50 | protected: 51 | auto initialize(proc_t* original_table) -> void 52 | { 53 | m_old_vmt = original_table; 54 | 55 | size_t size = 0; 56 | while(m_old_vmt[size] && platform::is_code_ptr(m_old_vmt[size])) 57 | ++size; 58 | 59 | m_new_vmt = (new proc_t[size + 1]) + 1; 60 | //std::copy(m_old_vmt - 1, m_old_vmt + size, m_new_vmt - 1); 61 | memcpy(m_new_vmt - 1, m_old_vmt - 1, sizeof(void*) * (size + 1)); 62 | } 63 | 64 | constexpr auto leak_table() -> void 65 | { 66 | m_new_vmt = nullptr; 67 | } 68 | 69 | auto hook_instance(void* inst) const -> void 70 | { 71 | auto& vtbl = *reinterpret_cast(inst); 72 | assert(vtbl == m_old_vmt || vtbl == m_new_vmt); 73 | vtbl = m_new_vmt; 74 | } 75 | 76 | auto unhook_instance(void* inst) const -> void 77 | { 78 | auto& vtbl = *reinterpret_cast(inst); 79 | assert(vtbl == m_old_vmt || vtbl == m_new_vmt); 80 | vtbl = m_old_vmt; 81 | } 82 | 83 | auto initialize_and_hook_instance(void* inst) -> bool 84 | { 85 | auto& vtbl = *reinterpret_cast(inst); 86 | auto initialized = false; 87 | if(!m_old_vmt) 88 | { 89 | initialized = true; 90 | initialize(vtbl); 91 | } 92 | hook_instance(inst); 93 | return initialized; 94 | } 95 | 96 | template 97 | auto hook_function(Fn hooked_fn, const std::size_t index) -> Fn 98 | { 99 | m_new_vmt[index] = (proc_t)(hooked_fn); 100 | return (Fn)(m_old_vmt[index]); 101 | } 102 | 103 | template 104 | auto apply_hook(std::size_t idx) -> void 105 | { 106 | T::m_original = hook_function(&T::hooked, idx); 107 | } 108 | 109 | template 110 | auto get_original_function(const int index) -> Fn 111 | { 112 | return (Fn)(m_old_vmt[index]); 113 | } 114 | 115 | private: 116 | proc_t* m_new_vmt = nullptr; 117 | proc_t* m_old_vmt = nullptr; 118 | }; 119 | 120 | class vmt_smart_hook : vmt_base_hook 121 | { 122 | public: 123 | vmt_smart_hook(void* class_base) 124 | : m_class{class_base} 125 | { 126 | initialize_and_hook_instance(class_base); 127 | } 128 | 129 | ~vmt_smart_hook() 130 | { 131 | unhook_instance(m_class); 132 | } 133 | 134 | vmt_smart_hook(const vmt_smart_hook&) = delete; 135 | vmt_smart_hook(vmt_smart_hook&&) = delete; 136 | 137 | vmt_smart_hook& operator=(const vmt_smart_hook&) = delete; 138 | vmt_smart_hook& operator=(vmt_smart_hook&&) = delete; 139 | 140 | auto rehook() const -> void 141 | { 142 | hook_instance(m_class); 143 | } 144 | 145 | auto unhook() const -> void 146 | { 147 | unhook_instance(m_class); 148 | } 149 | 150 | using vmt_base_hook::apply_hook; 151 | using vmt_base_hook::get_original_function; 152 | using vmt_base_hook::hook_function; 153 | 154 | private: 155 | void* m_class = nullptr; 156 | }; 157 | 158 | class vmt_multi_hook : vmt_base_hook 159 | { 160 | public: 161 | constexpr vmt_multi_hook() = default; 162 | 163 | ~vmt_multi_hook() 164 | { 165 | leak_table(); 166 | } 167 | 168 | vmt_multi_hook(const vmt_multi_hook&) = delete; 169 | vmt_multi_hook(vmt_multi_hook&&) = delete; 170 | 171 | vmt_multi_hook& operator=(const vmt_multi_hook&) = delete; 172 | vmt_multi_hook& operator=(vmt_multi_hook&&) = delete; 173 | 174 | using vmt_base_hook::apply_hook; 175 | using vmt_base_hook::get_original_function; 176 | using vmt_base_hook::hook_function; 177 | using vmt_base_hook::hook_instance; 178 | using vmt_base_hook::unhook_instance; 179 | using vmt_base_hook::initialize; 180 | using vmt_base_hook::initialize_and_hook_instance; 181 | }; -------------------------------------------------------------------------------- /src/config.cpp: -------------------------------------------------------------------------------- 1 | /* This file is part of nSkinz by namazso, licensed under the MIT license: 2 | * 3 | * MIT License 4 | * 5 | * Copyright (c) namazso 2018 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | #include "config.hpp" 26 | #include "SDK.hpp" 27 | 28 | #include 29 | #include 30 | 31 | config g_config; 32 | 33 | using json = nlohmann::json; 34 | 35 | #define TO_JSON_HELPER(var_name) {#var_name, o.var_name} 36 | #define FROM_JSON_HELPER(var_name) {const auto it = j.find(#var_name); if(it != std::end(j)) o.var_name = it->get();} 37 | #define FROM_JSON_HELPER_STR(var_name) {const auto it = j.find(#var_name); if(it != std::end(j)) strcpy_s(o.var_name, it->get().c_str());} 38 | 39 | auto to_json(json& j, const sticker_setting& o) -> void 40 | { 41 | j = json 42 | { 43 | TO_JSON_HELPER(kit), 44 | TO_JSON_HELPER(wear), 45 | TO_JSON_HELPER(scale), 46 | TO_JSON_HELPER(rotation), 47 | }; 48 | } 49 | 50 | auto from_json(const json& j, sticker_setting& o) -> void 51 | { 52 | FROM_JSON_HELPER(kit); 53 | FROM_JSON_HELPER(wear); 54 | FROM_JSON_HELPER(scale); 55 | FROM_JSON_HELPER(rotation); 56 | o.update(); 57 | } 58 | 59 | auto to_json(json& j, const item_setting& o) -> void 60 | { 61 | j = json 62 | { 63 | TO_JSON_HELPER(name), 64 | TO_JSON_HELPER(enabled), 65 | TO_JSON_HELPER(definition_index), 66 | TO_JSON_HELPER(entity_quality_index), 67 | TO_JSON_HELPER(paint_kit_index), 68 | TO_JSON_HELPER(definition_override_index), 69 | TO_JSON_HELPER(seed), 70 | TO_JSON_HELPER(stat_trak), 71 | TO_JSON_HELPER(wear), 72 | TO_JSON_HELPER(custom_name), 73 | TO_JSON_HELPER(stickers), 74 | }; 75 | } 76 | 77 | auto from_json(const json& j, item_setting& o) -> void 78 | { 79 | FROM_JSON_HELPER_STR(name); 80 | FROM_JSON_HELPER(enabled); 81 | FROM_JSON_HELPER(definition_index); 82 | FROM_JSON_HELPER(entity_quality_index); 83 | FROM_JSON_HELPER(paint_kit_index); 84 | FROM_JSON_HELPER(definition_override_index); 85 | FROM_JSON_HELPER(seed); 86 | FROM_JSON_HELPER(stat_trak); 87 | FROM_JSON_HELPER(wear); 88 | FROM_JSON_HELPER_STR(custom_name); 89 | const auto sticker_it = j.find("stickers"); 90 | if(sticker_it != std::end(j)) 91 | { 92 | const auto stickers = sticker_it->get>(); 93 | 94 | const auto size = std::min(stickers.size(), o.stickers.size()); 95 | 96 | for(auto i = 0u; i < size; ++i) 97 | o.stickers.at(i) = stickers.at(i); 98 | } 99 | 100 | o.update(); 101 | } 102 | 103 | auto config::save() -> void 104 | { 105 | auto of = std::ofstream("nSkinz.json"); 106 | if(of.good()) 107 | of << json(m_items); 108 | } 109 | 110 | auto config::load() -> void 111 | { 112 | try 113 | { 114 | auto ifile = std::ifstream("nSkinz.json"); 115 | if(ifile.good()) 116 | { 117 | m_items = json::parse(ifile).get>(); 118 | (*g_client_state)->ForceFullUpdate(); 119 | } 120 | } 121 | catch(const std::exception&) 122 | { 123 | // Config file doesn't exists or is malformed, just ignore it 124 | // This will probably crash if you use a manual mapper that doesnt do proper exception handling 125 | } 126 | } 127 | 128 | auto config::get_by_definition_index(const int definition_index) -> item_setting* 129 | { 130 | auto it = std::find_if(m_items.begin(), m_items.end(), [definition_index](const item_setting& e) 131 | { 132 | return e.enabled && e.definition_index == definition_index; 133 | }); 134 | 135 | return it == m_items.end() ? nullptr : &*it; 136 | } 137 | -------------------------------------------------------------------------------- /src/config.hpp: -------------------------------------------------------------------------------- 1 | /* This file is part of nSkinz by namazso, licensed under the MIT license: 2 | * 3 | * MIT License 4 | * 5 | * Copyright (c) namazso 2018 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | #pragma once 26 | #include "item_definitions.hpp" 27 | #include "kit_parser.hpp" 28 | 29 | #include 30 | #include 31 | #include 32 | 33 | template 34 | class value_syncer 35 | { 36 | using container_type = typename Container::value_type; 37 | 38 | const Container& container; 39 | T1& key; 40 | T2& value; 41 | const TC container_type::* member; 42 | 43 | public: 44 | value_syncer(const Container& container, T1& key, T2& value, const TC container_type::* member) 45 | : container{container} 46 | , key{key} 47 | , value{value} 48 | , member{member} 49 | {} 50 | 51 | auto key_to_value() const -> void 52 | { 53 | key = std::clamp(key, T1(0), T1(container.size() - 1)); 54 | value = container.at(key).*member; 55 | } 56 | 57 | auto value_to_key() const -> void 58 | { 59 | auto it = std::find_if(std::begin(container), std::end(container), [this](const container_type& x) 60 | { 61 | return value == x.*member; 62 | }); 63 | 64 | // Originally I wanted this to work with maps too, but fuck that 65 | if(it != std::end(container)) 66 | key = it - std::begin(container); 67 | else 68 | key = T1(0); 69 | } 70 | }; 71 | 72 | enum class sync_type 73 | { 74 | VALUE_TO_KEY, 75 | KEY_TO_VALUE 76 | }; 77 | 78 | template 79 | static auto do_sync(const Container& container, T1& key, T2& value, TC Container::value_type::* member) -> void 80 | { 81 | auto syncer = value_syncer{ container, key, value, member }; 82 | if constexpr(Type == sync_type::VALUE_TO_KEY) 83 | syncer.value_to_key(); 84 | else 85 | syncer.key_to_value(); 86 | } 87 | 88 | struct sticker_setting 89 | { 90 | template 91 | void update() 92 | { 93 | do_sync(game_data::sticker_kits, kit_vector_index, kit, &game_data::paint_kit::id); 94 | } 95 | 96 | int kit = 0; 97 | int kit_vector_index = 0; 98 | float wear = std::numeric_limits::min(); 99 | float scale = 1.f; 100 | float rotation = 0.f; 101 | }; 102 | 103 | struct item_setting 104 | { 105 | template 106 | void update() 107 | { 108 | do_sync( 109 | game_data::weapon_names, 110 | definition_vector_index, 111 | definition_index, 112 | &game_data::weapon_name::definition_index 113 | ); 114 | 115 | do_sync( 116 | game_data::quality_names, 117 | entity_quality_vector_index, 118 | entity_quality_index, 119 | &game_data::quality_name::index 120 | ); 121 | 122 | const std::vector* kit_names; 123 | const std::vector* defindex_names; 124 | 125 | if(definition_index == GLOVE_T_SIDE) 126 | { 127 | kit_names = &game_data::glove_kits; 128 | defindex_names = &game_data::glove_names; 129 | } 130 | else 131 | { 132 | kit_names = &game_data::skin_kits; 133 | defindex_names = &game_data::knife_names; 134 | } 135 | 136 | do_sync( 137 | *kit_names, 138 | paint_kit_vector_index, 139 | paint_kit_index, 140 | &game_data::paint_kit::id 141 | ); 142 | 143 | do_sync( 144 | *defindex_names, 145 | definition_override_vector_index, 146 | definition_override_index, 147 | &game_data::weapon_name::definition_index 148 | ); 149 | 150 | for(auto& sticker : stickers) 151 | sticker.update(); 152 | } 153 | 154 | char name[32] = "Default"; 155 | bool enabled = false; 156 | int definition_vector_index = 0; 157 | int definition_index = 1; 158 | int entity_quality_vector_index = 0; 159 | int entity_quality_index = 0; 160 | int paint_kit_vector_index = 0; 161 | int paint_kit_index = 0; 162 | int definition_override_vector_index = 0; 163 | int definition_override_index = 0; 164 | int seed = 0; 165 | int stat_trak = 0; 166 | float wear = std::numeric_limits::min(); 167 | char custom_name[32] = ""; 168 | std::array stickers; 169 | }; 170 | 171 | class config 172 | { 173 | public: 174 | config() 175 | { 176 | // Ghetto fix for possible race conditions 177 | m_items.reserve(128); 178 | 179 | // Default config 180 | m_items.push_back(item_setting()); 181 | } 182 | 183 | auto save() -> void; 184 | auto load() -> void; 185 | 186 | auto get_by_definition_index(int definition_index) -> item_setting*; 187 | 188 | auto get_items() -> std::vector& 189 | { 190 | return m_items; 191 | } 192 | 193 | auto get_icon_override_map() -> std::unordered_map& 194 | { 195 | return m_icon_overrides; 196 | } 197 | 198 | auto get_icon_override(const std::string_view original) const -> const char* 199 | { 200 | return m_icon_overrides.count(original) ? m_icon_overrides.at(original).data() : nullptr; 201 | } 202 | 203 | private: 204 | std::vector m_items; 205 | std::unordered_map m_icon_overrides; 206 | }; 207 | 208 | extern config g_config; -------------------------------------------------------------------------------- /src/dllmain.cpp: -------------------------------------------------------------------------------- 1 | /* This file is part of nSkinz by namazso, licensed under the MIT license: 2 | * 3 | * MIT License 4 | * 5 | * Copyright (c) namazso 2018 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | #include 26 | 27 | extern auto initialize(void* instance) -> void; 28 | 29 | static auto WINAPI thread_entry(const LPVOID instance) -> DWORD 30 | { 31 | initialize(instance); 32 | return 0; 33 | } 34 | 35 | auto WINAPI DllMain(const HINSTANCE instance, const DWORD reason, LPVOID reserved) -> bool 36 | { 37 | if(reason == DLL_PROCESS_ATTACH) 38 | { 39 | // Manual mappers sometimes pass nullptr here 40 | if(instance) 41 | DisableThreadLibraryCalls(instance); 42 | CreateThread(nullptr, 0, thread_entry, instance, 0, nullptr); 43 | } 44 | 45 | return true; 46 | } 47 | -------------------------------------------------------------------------------- /src/gui.cpp: -------------------------------------------------------------------------------- 1 | /* This file is part of nSkinz by namazso, licensed under the MIT license: 2 | * 3 | * MIT License 4 | * 5 | * Copyright (c) namazso 2018 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | #include "config.hpp" 26 | #include "item_definitions.hpp" 27 | #include "SDK.hpp" 28 | #include "kit_parser.hpp" 29 | #include "update_check.hpp" 30 | 31 | #include 32 | #include 33 | 34 | namespace ImGui 35 | { 36 | // ImGui ListBox lambda binder 37 | static bool ListBox(const char* label, int* current_item, std::function lambda, int items_count, int height_in_items) 38 | { 39 | return ImGui::ListBox(label, current_item, [](void* data, int idx, const char** out_text) 40 | { 41 | *out_text = (*reinterpret_cast*>(data))(idx); 42 | return true; 43 | }, &lambda, items_count, height_in_items); 44 | } 45 | } 46 | 47 | void draw_gui() 48 | { 49 | ImGui::SetNextWindowSize(ImVec2(700, 400)); 50 | if(ImGui::Begin("nSkinz", nullptr, 51 | ImGuiWindowFlags_NoResize | 52 | ImGuiWindowFlags_NoCollapse | 53 | ImGuiWindowFlags_AlwaysAutoResize | 54 | ImGuiWindowFlags_NoSavedSettings)) 55 | { 56 | 57 | auto& entries = g_config.get_items(); 58 | 59 | static auto selected_id = 0; 60 | 61 | ImGui::Columns(2, nullptr, false); 62 | 63 | // Config selection 64 | { 65 | ImGui::PushItemWidth(-1); 66 | 67 | char element_name[64]; 68 | 69 | ImGui::ListBox("##config", &selected_id, [&element_name, &entries](int idx) 70 | { 71 | sprintf_s(element_name, "%s (%s)", entries.at(idx).name, game_data::weapon_names.at(entries.at(idx).definition_vector_index).name); 72 | return element_name; 73 | }, entries.size(), 11); 74 | 75 | const auto button_size = ImVec2(ImGui::GetColumnWidth() / 2 - 12.5f, 31); 76 | 77 | if(ImGui::Button("Add", button_size)) 78 | { 79 | entries.push_back(item_setting()); 80 | selected_id = entries.size() - 1; 81 | } 82 | ImGui::SameLine(); 83 | 84 | if(ImGui::Button("Remove", button_size) && entries.size() > 1) 85 | entries.erase(entries.begin() + selected_id); 86 | 87 | ImGui::PopItemWidth(); 88 | } 89 | 90 | ImGui::NextColumn(); 91 | 92 | selected_id = selected_id < int(entries.size()) ? selected_id : entries.size() - 1; 93 | 94 | auto& selected_entry = entries[selected_id]; 95 | 96 | { 97 | // Name 98 | ImGui::InputText("Name", selected_entry.name, 32); 99 | 100 | // Item to change skins for 101 | ImGui::Combo("Item", &selected_entry.definition_vector_index, [](void* data, int idx, const char** out_text) 102 | { 103 | *out_text = game_data::weapon_names[idx].name; 104 | return true; 105 | }, nullptr, game_data::weapon_names.size(), 5); 106 | 107 | // Enabled 108 | ImGui::Checkbox("Enabled", &selected_entry.enabled); 109 | 110 | // Pattern Seed 111 | ImGui::InputInt("Seed", &selected_entry.seed); 112 | 113 | // Custom StatTrak number 114 | ImGui::InputInt("StatTrak", &selected_entry.stat_trak); 115 | 116 | // Wear Float 117 | ImGui::SliderFloat("Wear", &selected_entry.wear, FLT_MIN, 1.f, "%.10f", 5); 118 | 119 | // Paint kit 120 | if(selected_entry.definition_index != GLOVE_T_SIDE) 121 | { 122 | ImGui::Combo("Paint Kit", &selected_entry.paint_kit_vector_index, [](void* data, int idx, const char** out_text) 123 | { 124 | *out_text = game_data::skin_kits[idx].name.c_str(); 125 | return true; 126 | }, nullptr, game_data::skin_kits.size(), 10); 127 | } 128 | else 129 | { 130 | ImGui::Combo("Paint Kit", &selected_entry.paint_kit_vector_index, [](void* data, int idx, const char** out_text) 131 | { 132 | *out_text = game_data::glove_kits[idx].name.c_str(); 133 | return true; 134 | }, nullptr, game_data::glove_kits.size(), 10); 135 | } 136 | 137 | // Quality 138 | ImGui::Combo("Quality", &selected_entry.entity_quality_vector_index, [](void* data, int idx, const char** out_text) 139 | { 140 | *out_text = game_data::quality_names[idx].name; 141 | return true; 142 | }, nullptr, game_data::quality_names.size(), 5); 143 | 144 | // Yes we do it twice to decide knifes 145 | selected_entry.update(); 146 | 147 | // Item defindex override 148 | if(selected_entry.definition_index == WEAPON_KNIFE) 149 | { 150 | ImGui::Combo("Knife", &selected_entry.definition_override_vector_index, [](void* data, int idx, const char** out_text) 151 | { 152 | *out_text = game_data::knife_names.at(idx).name; 153 | return true; 154 | }, nullptr, game_data::knife_names.size(), 5); 155 | } 156 | else if(selected_entry.definition_index == GLOVE_T_SIDE) 157 | { 158 | ImGui::Combo("Glove", &selected_entry.definition_override_vector_index, [](void* data, int idx, const char** out_text) 159 | { 160 | *out_text = game_data::glove_names.at(idx).name; 161 | return true; 162 | }, nullptr, game_data::glove_names.size(), 5); 163 | } 164 | else 165 | { 166 | // We don't want to override weapons other than knives or gloves 167 | static auto unused_value = 0; 168 | selected_entry.definition_override_vector_index = 0; 169 | ImGui::Combo("Unavailable", &unused_value, "For knives or gloves\0"); 170 | } 171 | 172 | selected_entry.update(); 173 | 174 | // Custom Name tag 175 | ImGui::InputText("Name Tag", selected_entry.custom_name, 32); 176 | } 177 | 178 | ImGui::NextColumn(); 179 | 180 | ImGui::Columns(1, nullptr, false); 181 | 182 | ImGui::Separator(); 183 | 184 | { 185 | ImGui::Columns(2, nullptr, false); 186 | 187 | ImGui::PushID("sticker"); 188 | 189 | static auto selected_sticker_slot = 0; 190 | 191 | auto& selected_sticker = selected_entry.stickers[selected_sticker_slot]; 192 | 193 | ImGui::PushItemWidth(-1); 194 | 195 | char element_name[64]; 196 | 197 | ImGui::ListBox("", &selected_sticker_slot, [&selected_entry, &element_name](int idx) 198 | { 199 | auto kit_vector_index = selected_entry.stickers[idx].kit_vector_index; 200 | sprintf_s(element_name, "#%d (%s)", idx + 1, game_data::sticker_kits.at(kit_vector_index).name.c_str()); 201 | return element_name; 202 | }, 5, 5); 203 | ImGui::PopItemWidth(); 204 | 205 | ImGui::NextColumn(); 206 | 207 | ImGui::Combo("Sticker Kit", &selected_sticker.kit_vector_index, [](void* data, int idx, const char** out_text) 208 | { 209 | *out_text = game_data::sticker_kits.at(idx).name.c_str(); 210 | return true; 211 | }, nullptr, game_data::sticker_kits.size(), 10); 212 | 213 | ImGui::SliderFloat("Wear", &selected_sticker.wear, FLT_MIN, 1.f, "%.10f", 5); 214 | 215 | ImGui::SliderFloat("Scale", &selected_sticker.scale, 0.1f, 5.f, "%.3f"); 216 | 217 | ImGui::SliderFloat("Rotation", &selected_sticker.rotation, 0.f, 360.f); 218 | 219 | ImGui::NextColumn(); 220 | 221 | ImGui::PopID(); 222 | } 223 | 224 | ImGui::Columns(1, nullptr, false); 225 | 226 | ImGui::Separator(); 227 | 228 | ImGui::Columns(3, nullptr, false); 229 | 230 | ImGui::PushItemWidth(-1); 231 | 232 | // Lower buttons for modifying items and saving 233 | { 234 | const auto button_size = ImVec2(ImGui::GetColumnWidth() - 1, 20); 235 | 236 | if(ImGui::Button("Update", button_size)) 237 | //(*g_client_state)->ForceFullUpdate(); 238 | g_engine->ClientCmd_Unrestricted("record x;stop"); //this will be changed at a later date. 239 | 240 | 241 | ImGui::NextColumn(); 242 | 243 | if(ImGui::Button("Save", button_size)) 244 | g_config.save(); 245 | ImGui::NextColumn(); 246 | 247 | if(ImGui::Button("Load", button_size)) 248 | g_config.load(); 249 | ImGui::NextColumn(); 250 | } 251 | 252 | ImGui::PopItemWidth(); 253 | ImGui::Columns(1); 254 | 255 | ImGui::Text("nSkinz by namazso"); 256 | 257 | ImGui::End(); 258 | } 259 | 260 | if(g_update_needed && ImGui::Begin("New commits since compile!", &g_update_needed, 261 | {600, 400}, -1, ImGuiWindowFlags_NoSavedSettings)) 262 | { 263 | ImGui::Columns(3, "commit", true); 264 | for(const auto& commit : g_commits_since_compile) 265 | { 266 | ImGui::Text("%s", commit.author.c_str()); 267 | ImGui::NextColumn(); 268 | ImGui::Text("%s", commit.date.c_str()); 269 | ImGui::NextColumn(); 270 | ImGui::Text("%s", commit.message.c_str()); 271 | ImGui::NextColumn(); 272 | } 273 | 274 | ImGui::End(); 275 | } 276 | } 277 | -------------------------------------------------------------------------------- /src/item_definitions.cpp: -------------------------------------------------------------------------------- 1 | /* This file is part of nSkinz by namazso, licensed under the MIT license: 2 | * 3 | * MIT License 4 | * 5 | * Copyright (c) namazso 2018 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | #include "item_definitions.hpp" 26 | // These are std::vectors because else I'd have to write their size in the header or write my own container 27 | 28 | // We need these for overriding viewmodels and icons 29 | const game_data::weapon_info* game_data::get_weapon_info(int defindex) 30 | { 31 | const static std::map info = 32 | { 33 | {WEAPON_KNIFE,{"models/weapons/v_knife_default_ct.mdl", "knife_default_ct"}}, 34 | {WEAPON_KNIFE_T,{"models/weapons/v_knife_default_t.mdl", "knife_t"}}, 35 | {WEAPON_KNIFE_BAYONET, {"models/weapons/v_knife_bayonet.mdl", "bayonet"}}, 36 | {WEAPON_KNIFE_CSS, {"models/weapons/v_knife_css.mdl", "knife_css"}}, 37 | {WEAPON_KNIFE_FLIP, {"models/weapons/v_knife_flip.mdl", "knife_flip"}}, 38 | {WEAPON_KNIFE_GUT, {"models/weapons/v_knife_gut.mdl", "knife_gut"}}, 39 | {WEAPON_KNIFE_KARAMBIT, {"models/weapons/v_knife_karam.mdl", "knife_karambit"}}, 40 | {WEAPON_KNIFE_M9_BAYONET, {"models/weapons/v_knife_m9_bay.mdl", "knife_m9_bayonet"}}, 41 | {WEAPON_KNIFE_TACTICAL, {"models/weapons/v_knife_tactical.mdl", "knife_tactical"}}, 42 | {WEAPON_KNIFE_FALCHION, {"models/weapons/v_knife_falchion_advanced.mdl", "knife_falchion"}}, 43 | {WEAPON_KNIFE_SURVIVAL_BOWIE, {"models/weapons/v_knife_survival_bowie.mdl", "knife_survival_bowie"}}, 44 | {WEAPON_KNIFE_BUTTERFLY, {"models/weapons/v_knife_butterfly.mdl", "knife_butterfly"}}, 45 | {WEAPON_KNIFE_PUSH, {"models/weapons/v_knife_push.mdl", "knife_push"}}, 46 | {WEAPON_KNIFE_CORD, {"models/weapons/v_knife_cord.mdl", "knife_cord"}}, 47 | {WEAPON_KNIFE_CANIS, {"models/weapons/v_knife_canis.mdl", "knife_canis"}}, 48 | {WEAPON_KNIFE_URSUS,{"models/weapons/v_knife_ursus.mdl", "knife_ursus"}}, 49 | {WEAPON_KNIFE_GYPSY_JACKKNIFE,{"models/weapons/v_knife_gypsy_jackknife.mdl", "knife_gypsy_jackknife"}}, 50 | {WEAPON_KNIFE_OUTDOOR,{"models/weapons/v_knife_outdoor.mdl", "knife_outdoor"}}, 51 | {WEAPON_KNIFE_STILETTO,{"models/weapons/v_knife_stiletto.mdl", "knife_stiletto"}}, 52 | {WEAPON_KNIFE_WIDOWMAKER,{"models/weapons/v_knife_widowmaker.mdl", "knife_widowmaker"}}, 53 | {WEAPON_KNIFE_SKELETON,{"models/weapons/v_knife_skeleton.mdl", "knife_skeleton"}}, 54 | {GLOVE_STUDDED_BLOODHOUND,{"models/weapons/v_models/arms/glove_bloodhound/v_glove_bloodhound.mdl"}}, 55 | {GLOVE_T_SIDE,{"models/weapons/v_models/arms/glove_fingerless/v_glove_fingerless.mdl"}}, 56 | {GLOVE_CT_SIDE,{"models/weapons/v_models/arms/glove_hardknuckle/v_glove_hardknuckle.mdl"}}, 57 | {GLOVE_SPORTY,{"models/weapons/v_models/arms/glove_sporty/v_glove_sporty.mdl"}}, 58 | {GLOVE_SLICK,{"models/weapons/v_models/arms/glove_slick/v_glove_slick.mdl"}}, 59 | {GLOVE_LEATHER_WRAP,{"models/weapons/v_models/arms/glove_handwrap_leathery/v_glove_handwrap_leathery.mdl"}}, 60 | {GLOVE_MOTORCYCLE,{"models/weapons/v_models/arms/glove_motorcycle/v_glove_motorcycle.mdl"}}, 61 | {GLOVE_SPECIALIST,{"models/weapons/v_models/arms/glove_specialist/v_glove_specialist.mdl"}}, 62 | {GLOVE_HYDRA,{"models/weapons/v_models/arms/glove_bloodhound/v_glove_bloodhound_hydra.mdl"}} 63 | }; 64 | 65 | const auto entry = info.find(defindex); 66 | return entry == end(info) ? nullptr : &entry->second; 67 | } 68 | 69 | const std::vector game_data::knife_names = 70 | { 71 | {0, "Default"}, 72 | {WEAPON_KNIFE_BAYONET, "Bayonet"}, 73 | {WEAPON_KNIFE_CSS, "Classic Knife"}, 74 | {WEAPON_KNIFE_FLIP, "Flip Knife"}, 75 | {WEAPON_KNIFE_GUT, "Gut Knife"}, 76 | {WEAPON_KNIFE_KARAMBIT, "Karambit"}, 77 | {WEAPON_KNIFE_M9_BAYONET, "M9 Bayonet"}, 78 | {WEAPON_KNIFE_TACTICAL, "Huntsman Knife"}, 79 | {WEAPON_KNIFE_FALCHION, "Falchion Knife"}, 80 | {WEAPON_KNIFE_SURVIVAL_BOWIE, "Bowie Knife"}, 81 | {WEAPON_KNIFE_BUTTERFLY, "Butterfly Knife"}, 82 | {WEAPON_KNIFE_PUSH, "Shadow Daggers"}, 83 | {WEAPON_KNIFE_CORD, "Paracord Knife"}, 84 | {WEAPON_KNIFE_CANIS, "Survival Knife"}, 85 | {WEAPON_KNIFE_URSUS, "Ursus Knife"}, 86 | {WEAPON_KNIFE_GYPSY_JACKKNIFE, "Navaja Knife"}, 87 | {WEAPON_KNIFE_OUTDOOR, "Nomad Knife"}, 88 | {WEAPON_KNIFE_STILETTO, "Stiletto Knife"}, 89 | {WEAPON_KNIFE_WIDOWMAKER, "Talon Knife"}, 90 | {WEAPON_KNIFE_SKELETON, "Skeleton Knife"} 91 | }; 92 | 93 | const std::vector game_data::glove_names = 94 | { 95 | {0, "Default"}, 96 | {GLOVE_STUDDED_BLOODHOUND, "Bloodhound"}, 97 | {GLOVE_T_SIDE, "Default (Terrorists)"}, 98 | {GLOVE_CT_SIDE, "Default (Counter-Terrorists)"}, 99 | {GLOVE_SPORTY, "Sporty"}, 100 | {GLOVE_SLICK, "Slick"}, 101 | {GLOVE_LEATHER_WRAP, "Handwrap"}, 102 | {GLOVE_MOTORCYCLE, "Motorcycle"}, 103 | {GLOVE_SPECIALIST, "Specialist"}, 104 | {GLOVE_HYDRA, "Hydra"} 105 | }; 106 | 107 | const std::vector game_data::weapon_names = 108 | { 109 | {WEAPON_KNIFE, "Knife"}, 110 | {GLOVE_T_SIDE, "Glove"}, 111 | {7, "AK-47"}, 112 | {8, "AUG"}, 113 | {9, "AWP"}, 114 | {63, "CZ75 Auto"}, 115 | {1, "Desert Eagle"}, 116 | {2, "Dual Berettas"}, 117 | {10, "FAMAS"}, 118 | {3, "Five-SeveN"}, 119 | {11, "G3SG1"}, 120 | {13, "Galil AR"}, 121 | {4, "Glock-18"}, 122 | {14, "M249"}, 123 | {60, "M4A1-S"}, 124 | {16, "M4A4"}, 125 | {17, "MAC-10"}, 126 | {27, "MAG-7"}, 127 | {23, "MP5-SD"}, 128 | {33, "MP7"}, 129 | {34, "MP9"}, 130 | {28, "Negev"}, 131 | {35, "Nova"}, 132 | {32, "P2000"}, 133 | {36, "P250"}, 134 | {19, "P90"}, 135 | {26, "PP-Bizon"}, 136 | {64, "R8 Revolver"}, 137 | {29, "Sawed-Off"}, 138 | {38, "SCAR-20"}, 139 | {40, "SSG 08"}, 140 | {39, "SG 553"}, 141 | {30, "Tec-9"}, 142 | {24, "UMP-45"}, 143 | {61, "USP-S"}, 144 | {25, "XM1014"}, 145 | }; 146 | 147 | const std::vector game_data::quality_names = 148 | { 149 | {0, "Default"}, 150 | {1, "Genuine"}, 151 | {2, "Vintage"}, 152 | {3, "Unusual"}, 153 | {5, "Community"}, 154 | {6, "Developer"}, 155 | {7, "Self-Made"}, 156 | {8, "Customized"}, 157 | {9, "Strange"}, 158 | {10, "Completed"}, 159 | {12, "Tournament"} 160 | }; 161 | -------------------------------------------------------------------------------- /src/item_definitions.hpp: -------------------------------------------------------------------------------- 1 | /* This file is part of nSkinz by namazso, licensed under the MIT license: 2 | * 3 | * MIT License 4 | * 5 | * Copyright (c) namazso 2018 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | #pragma once 26 | #include 27 | #include 28 | 29 | enum ItemDefinitionIndex : int 30 | { 31 | WEAPON_DEAGLE = 1, 32 | WEAPON_ELITE = 2, 33 | WEAPON_FIVESEVEN = 3, 34 | WEAPON_GLOCK = 4, 35 | WEAPON_AK47 = 7, 36 | WEAPON_AUG = 8, 37 | WEAPON_AWP = 9, 38 | WEAPON_FAMAS = 10, 39 | WEAPON_G3SG1 = 11, 40 | WEAPON_GALILAR = 13, 41 | WEAPON_M249 = 14, 42 | WEAPON_M4A1 = 16, 43 | WEAPON_MAC10 = 17, 44 | WEAPON_P90 = 19, 45 | WEAPON_MP5_SD = 23, 46 | WEAPON_UMP45 = 24, 47 | WEAPON_XM1014 = 25, 48 | WEAPON_BIZON = 26, 49 | WEAPON_MAG7 = 27, 50 | WEAPON_NEGEV = 28, 51 | WEAPON_SAWEDOFF = 29, 52 | WEAPON_TEC9 = 30, 53 | WEAPON_TASER = 31, 54 | WEAPON_HKP2000 = 32, 55 | WEAPON_MP7 = 33, 56 | WEAPON_MP9 = 34, 57 | WEAPON_NOVA = 35, 58 | WEAPON_P250 = 36, 59 | WEAPON_SCAR20 = 38, 60 | WEAPON_SG556 = 39, 61 | WEAPON_SSG08 = 40, 62 | WEAPON_KNIFE = 42, 63 | WEAPON_FLASHBANG = 43, 64 | WEAPON_HEGRENADE = 44, 65 | WEAPON_SMOKEGRENADE = 45, 66 | WEAPON_MOLOTOV = 46, 67 | WEAPON_DECOY = 47, 68 | WEAPON_INCGRENADE = 48, 69 | WEAPON_C4 = 49, 70 | WEAPON_KNIFE_T = 59, 71 | WEAPON_M4A1_SILENCER = 60, 72 | WEAPON_USP_SILENCER = 61, 73 | WEAPON_CZ75A = 63, 74 | WEAPON_REVOLVER = 64, 75 | WEAPON_KNIFE_BAYONET = 500, 76 | WEAPON_KNIFE_CSS = 503, 77 | WEAPON_KNIFE_FLIP = 505, 78 | WEAPON_KNIFE_GUT = 506, 79 | WEAPON_KNIFE_KARAMBIT = 507, 80 | WEAPON_KNIFE_M9_BAYONET = 508, 81 | WEAPON_KNIFE_TACTICAL = 509, 82 | WEAPON_KNIFE_FALCHION = 512, 83 | WEAPON_KNIFE_SURVIVAL_BOWIE = 514, 84 | WEAPON_KNIFE_BUTTERFLY = 515, 85 | WEAPON_KNIFE_PUSH = 516, 86 | WEAPON_KNIFE_CORD = 517, 87 | WEAPON_KNIFE_CANIS = 518, 88 | WEAPON_KNIFE_URSUS = 519, 89 | WEAPON_KNIFE_GYPSY_JACKKNIFE = 520, 90 | WEAPON_KNIFE_OUTDOOR = 521, 91 | WEAPON_KNIFE_STILETTO = 522, 92 | WEAPON_KNIFE_WIDOWMAKER = 523, 93 | WEAPON_KNIFE_SKELETON = 525, 94 | GLOVE_STUDDED_BLOODHOUND = 5027, 95 | GLOVE_T_SIDE = 5028, 96 | GLOVE_CT_SIDE = 5029, 97 | GLOVE_SPORTY = 5030, 98 | GLOVE_SLICK = 5031, 99 | GLOVE_LEATHER_WRAP = 5032, 100 | GLOVE_MOTORCYCLE = 5033, 101 | GLOVE_SPECIALIST = 5034, 102 | GLOVE_HYDRA = 5035 103 | }; 104 | 105 | static inline auto is_knife(const int i) -> bool 106 | { 107 | return (i >= WEAPON_KNIFE_BAYONET && i < GLOVE_STUDDED_BLOODHOUND) || i == WEAPON_KNIFE_T || i == WEAPON_KNIFE; 108 | } 109 | 110 | //extern const std::map k_weapon_info; 111 | namespace game_data 112 | { 113 | // Stupid MSVC requires separate constexpr constructors for any initialization 114 | struct weapon_info 115 | { 116 | constexpr weapon_info(const char* model, const char* icon = nullptr) : 117 | model(model), 118 | icon(icon) 119 | {} 120 | 121 | const char* model; 122 | const char* icon; 123 | }; 124 | 125 | struct weapon_name 126 | { 127 | constexpr weapon_name(const int definition_index, const char* name) : 128 | definition_index(definition_index), 129 | name(name) 130 | {} 131 | 132 | int definition_index = 0; 133 | const char* name = nullptr; 134 | }; 135 | 136 | struct quality_name 137 | { 138 | constexpr quality_name(const int index, const char* name) : 139 | index(index), 140 | name(name) 141 | {} 142 | 143 | int index = 0; 144 | const char* name = nullptr; 145 | }; 146 | 147 | const weapon_info* get_weapon_info(int defindex); 148 | extern const std::vector knife_names; 149 | extern const std::vector glove_names; 150 | extern const std::vector weapon_names; 151 | extern const std::vector quality_names; 152 | } 153 | -------------------------------------------------------------------------------- /src/kit_parser.cpp: -------------------------------------------------------------------------------- 1 | /* This file is part of nSkinz by namazso, licensed under the MIT license: 2 | * 3 | * MIT License 4 | * 5 | * Copyright (c) namazso 2018 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | #include "kit_parser.hpp" 26 | #include "Utilities/platform.hpp" 27 | #include "nSkinz.hpp" 28 | 29 | #include 30 | 31 | std::vector game_data::skin_kits; 32 | std::vector game_data::glove_kits; 33 | std::vector game_data::sticker_kits; 34 | 35 | class CCStrike15ItemSchema; 36 | class CCStrike15ItemSystem; 37 | 38 | template 39 | struct Node_t 40 | { 41 | int previous_id; //0x0000 42 | int next_id; //0x0004 43 | void* _unknown_ptr; //0x0008 44 | int _unknown; //0x000C 45 | Key key; //0x0010 46 | Value value; //0x0014 47 | }; 48 | 49 | template 50 | struct Head_t 51 | { 52 | Node_t* memory; //0x0000 53 | int allocation_count; //0x0004 54 | int grow_size; //0x0008 55 | int start_element; //0x000C 56 | int next_available; //0x0010 57 | int _unknown; //0x0014 58 | int last_element; //0x0018 59 | }; //Size=0x001C 60 | 61 | // could use CUtlString but this is just easier and CUtlString isn't needed anywhere else 62 | struct String_t 63 | { 64 | char* buffer; //0x0000 65 | int capacity; //0x0004 66 | int grow_size; //0x0008 67 | int length; //0x000C 68 | }; //Size=0x0010 69 | 70 | struct CPaintKit 71 | { 72 | int id; //0x0000 73 | 74 | String_t name; //0x0004 75 | String_t description; //0x0014 76 | String_t item_name; //0x0024 77 | String_t material_name; //0x0034 78 | String_t image_inventory; //0x0044 79 | 80 | char pad_0x0054[0x8C]; //0x0054 81 | }; //Size=0x00E0 82 | 83 | struct CStickerKit 84 | { 85 | int id; 86 | 87 | int item_rarity; 88 | 89 | String_t name; 90 | String_t description; 91 | String_t item_name; 92 | String_t material_name; 93 | String_t image_inventory; 94 | 95 | int tournament_event_id; 96 | int tournament_team_id; 97 | int tournament_player_id; 98 | bool is_custom_sticker_material; 99 | 100 | float rotate_end; 101 | float rotate_start; 102 | 103 | float scale_min; 104 | float scale_max; 105 | 106 | float wear_min; 107 | float wear_max; 108 | 109 | String_t image_inventory2; 110 | String_t image_inventory_large; 111 | 112 | std::uint32_t pad0[4]; 113 | }; 114 | 115 | auto game_data::initialize_kits() -> void 116 | { 117 | const auto V_UCS2ToUTF8 = static_cast(platform::get_export("vstdlib.dll", "V_UCS2ToUTF8")); 118 | 119 | // Search the relative calls 120 | 121 | // call ItemSystem 122 | // push dword ptr [esi+0Ch] 123 | // lea ecx, [eax+4] 124 | // call CEconItemSchema::GetPaintKitDefinition 125 | 126 | const auto sig_address = platform::find_pattern(get_client_name(), "\xE8\x00\x00\x00\x00\xFF\x76\x0C\x8D\x48\x04\xE8", "x????xxxxxxx"); 127 | 128 | // Skip the opcode, read rel32 address 129 | const auto item_system_offset = *reinterpret_cast(sig_address + 1); 130 | 131 | // Add the offset to the end of the instruction 132 | const auto item_system_fn = reinterpret_cast(sig_address + 5 + item_system_offset); 133 | 134 | // Skip VTable, first member variable of ItemSystem is ItemSchema 135 | const auto item_schema = reinterpret_cast(std::uintptr_t(item_system_fn()) + sizeof(void*)); 136 | 137 | // Dump paint kits 138 | { 139 | // Skip the instructions between, skip the opcode, read rel32 address 140 | const auto get_paint_kit_definition_offset = *reinterpret_cast(sig_address + 11 + 1); 141 | 142 | // Add the offset to the end of the instruction 143 | const auto get_paint_kit_definition_fn = reinterpret_cast(sig_address + 11 + 5 + get_paint_kit_definition_offset); 144 | 145 | // The last offset is start_element, we need that 146 | 147 | // push ebp 148 | // mov ebp, esp 149 | // sub esp, 0Ch 150 | // mov eax, [ecx+298h] 151 | 152 | // Skip instructions, skip opcode, read offset 153 | const auto start_element_offset = *reinterpret_cast(std::uintptr_t(get_paint_kit_definition_fn) + 8 + 2); 154 | 155 | // Calculate head base from start_element's offset 156 | const auto head_offset = start_element_offset - 12; 157 | 158 | const auto map_head = reinterpret_cast*>(std::uintptr_t(item_schema) + head_offset); 159 | 160 | for(auto i = 0; i <= map_head->last_element; ++i) 161 | { 162 | const auto paint_kit = map_head->memory[i].value; 163 | 164 | if(paint_kit->id == 9001) 165 | continue; 166 | 167 | const auto wide_name = g_localize->Find(paint_kit->item_name.buffer + 1); 168 | char name[256]; 169 | V_UCS2ToUTF8(wide_name, name, sizeof(name)); 170 | 171 | if(paint_kit->id < 10000) 172 | game_data::skin_kits.push_back({ paint_kit->id, name }); 173 | else 174 | game_data::glove_kits.push_back({ paint_kit->id, name }); 175 | } 176 | 177 | std::sort(game_data::skin_kits.begin(), game_data::skin_kits.end()); 178 | std::sort(game_data::glove_kits.begin(), game_data::glove_kits.end()); 179 | } 180 | 181 | // Dump sticker kits 182 | { 183 | const auto sticker_sig = platform::find_pattern(get_client_name(), "\x53\x8D\x48\x04\xE8\x00\x00\x00\x00\x8B\x4D\x10", "xxxxx????xxx") + 4; 184 | 185 | // Skip the opcode, read rel32 address 186 | const auto get_sticker_kit_definition_offset = *reinterpret_cast(sticker_sig + 1); 187 | 188 | // Add the offset to the end of the instruction 189 | const auto get_sticker_kit_definition_fn = reinterpret_cast(sticker_sig + 5 + get_sticker_kit_definition_offset); 190 | 191 | // The last offset is head_element, we need that 192 | 193 | // push ebp 194 | // mov ebp, esp 195 | // push ebx 196 | // push esi 197 | // push edi 198 | // mov edi, ecx 199 | // mov eax, [edi + 2BCh] 200 | 201 | // Skip instructions, skip opcode, read offset 202 | const auto start_element_offset = *reinterpret_cast(std::uintptr_t(get_sticker_kit_definition_fn) + 8 + 2); 203 | 204 | // Calculate head base from start_element's offset 205 | const auto head_offset = start_element_offset - 12; 206 | 207 | const auto map_head = reinterpret_cast*>(std::uintptr_t(item_schema) + head_offset); 208 | 209 | for(auto i = 0; i <= map_head->last_element; ++i) 210 | { 211 | const auto sticker_kit = map_head->memory[i].value; 212 | 213 | char sticker_name_if_valve_fucked_up_their_translations[64]; 214 | 215 | auto sticker_name_ptr = sticker_kit->item_name.buffer + 1; 216 | 217 | //if it is SprayKit - ignore, it can`t be installed same as StickerKit 218 | if(sticker_name_ptr[1] == 'p') 219 | continue; 220 | 221 | if(strstr(sticker_name_ptr, "StickerKit_dhw2014_dignitas")) 222 | { 223 | strcpy_s(sticker_name_if_valve_fucked_up_their_translations, "StickerKit_dhw2014_teamdignitas"); 224 | strcat_s(sticker_name_if_valve_fucked_up_their_translations, sticker_name_ptr + 27); 225 | sticker_name_ptr = sticker_name_if_valve_fucked_up_their_translations; 226 | } 227 | 228 | const auto wide_name = g_localize->Find(sticker_name_ptr); 229 | char name[256]; 230 | V_UCS2ToUTF8(wide_name, name, sizeof(name)); 231 | 232 | game_data::sticker_kits.push_back({ sticker_kit->id, name }); 233 | } 234 | 235 | std::sort(game_data::sticker_kits.begin(), game_data::sticker_kits.end()); 236 | 237 | game_data::sticker_kits.insert(game_data::sticker_kits.begin(), { 0, "None" }); 238 | } 239 | } 240 | -------------------------------------------------------------------------------- /src/kit_parser.hpp: -------------------------------------------------------------------------------- 1 | /* This file is part of nSkinz by namazso, licensed under the MIT license: 2 | * 3 | * MIT License 4 | * 5 | * Copyright (c) namazso 2018 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | #pragma once 26 | #include 27 | #include 28 | 29 | namespace game_data 30 | { 31 | struct paint_kit 32 | { 33 | int id; 34 | std::string name; 35 | 36 | auto operator < (const paint_kit& other) const -> bool 37 | { 38 | return name < other.name; 39 | } 40 | }; 41 | 42 | extern std::vector skin_kits; 43 | extern std::vector glove_kits; 44 | extern std::vector sticker_kits; 45 | 46 | extern auto initialize_kits() -> void; 47 | } 48 | -------------------------------------------------------------------------------- /src/nSkinz.cpp: -------------------------------------------------------------------------------- 1 | /* This file is part of nSkinz by namazso, licensed under the MIT license: 2 | * 3 | * MIT License 4 | * 5 | * Copyright (c) namazso 2018 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | #include "nSkinz.hpp" 26 | #include "Hooks/hooks.hpp" 27 | #include "render.hpp" 28 | #include "kit_parser.hpp" 29 | #include "update_check.hpp" 30 | #include "config.hpp" 31 | 32 | sdk::IBaseClientDLL* g_client; 33 | sdk::IClientEntityList* g_entity_list; 34 | sdk::IVEngineClient* g_engine; 35 | sdk::IVModelInfoClient* g_model_info; 36 | sdk::IGameEventManager2* g_game_event_manager; 37 | sdk::ILocalize* g_localize; 38 | sdk::IInputSystem* g_input_system; 39 | 40 | sdk::CBaseClientState** g_client_state; 41 | sdk::C_CS_PlayerResource** g_player_resource; 42 | 43 | //vmt_smart_hook* g_client_hook; 44 | //vmt_smart_hook* g_game_event_manager_hook; 45 | 46 | recv_prop_hook* g_sequence_hook; 47 | 48 | auto ensure_dynamic_hooks() -> void 49 | { 50 | // find by xref to "CHudSaveStatus" 51 | const auto hss = get_vfunc(g_client, 87); 52 | const auto hud = *(void**)(hss + 7); 53 | const auto off = *(int32_t*)(hss + 12); 54 | const auto fn = (void*(__thiscall *)(void*, const char*))(hss + 16 + off); 55 | const auto notice_hud = fn(hud, "SFHudDeathNoticeAndBotStatus"); 56 | if(notice_hud) 57 | { 58 | static vmt_multi_hook notice_hook; 59 | if(notice_hook.initialize_and_hook_instance(notice_hud)) 60 | notice_hook.apply_hook(1); 61 | } 62 | 63 | const auto local_index = g_engine->GetLocalPlayer(); 64 | const auto local = static_cast(g_entity_list->GetClientEntity(local_index)); 65 | if(local) 66 | { 67 | static vmt_multi_hook player_hook; 68 | const auto networkable = static_cast(local); 69 | if(player_hook.initialize_and_hook_instance(networkable)) 70 | player_hook.apply_hook(7); 71 | } 72 | } 73 | 74 | template 75 | auto get_interface(const char* module, const char* name) -> T* 76 | { 77 | return reinterpret_cast(platform::get_interface(module, name)); 78 | } 79 | 80 | auto get_client_name() -> const char* 81 | { 82 | static const char* name = nullptr; 83 | if (!name) 84 | name = platform::get_module_info("client_panorama.dll").first ? "client_panorama.dll" : "client.dll"; 85 | return name; 86 | } 87 | 88 | auto initialize(void* instance) -> void 89 | { 90 | g_client = get_interface(get_client_name(), CLIENT_DLL_INTERFACE_VERSION); 91 | g_entity_list = get_interface(get_client_name(), VCLIENTENTITYLIST_INTERFACE_VERSION); 92 | g_engine = get_interface("engine.dll", VENGINE_CLIENT_INTERFACE_VERSION); 93 | g_model_info = get_interface("engine.dll", VMODELINFO_CLIENT_INTERFACE_VERSION); 94 | g_game_event_manager = get_interface("engine.dll", INTERFACEVERSION_GAMEEVENTSMANAGER2); 95 | g_localize = get_interface("localize.dll", ILOCALIZE_CLIENT_INTERFACE_VERSION); 96 | g_input_system = get_interface("inputsystem.dll", INPUTSYSTEM_INTERFACE_VERSION); 97 | 98 | g_client_state = *reinterpret_cast(get_vfunc(g_engine, 12) + 0x10); 99 | 100 | run_update_check(); 101 | 102 | // Get skins 103 | game_data::initialize_kits(); 104 | 105 | g_config.load(); 106 | 107 | render::initialize(); 108 | 109 | //g_client_hook = new vmt_smart_hook(g_client); 110 | //g_client_hook->apply_hook(36); 111 | 112 | //g_game_event_manager_hook = new vmt_smart_hook(g_game_event_manager); 113 | //g_game_event_manager_hook->apply_hook(9); 114 | 115 | const auto sequence_prop = sdk::C_BaseViewModel::GetSequenceProp(); 116 | g_sequence_hook = new recv_prop_hook(sequence_prop, &hooks::sequence_proxy_fn); 117 | 118 | const auto team_arr_prop = sdk::C_CS_PlayerResource::GetTeamProp(); 119 | const auto team_prop = team_arr_prop->m_pDataTable->m_pProps; 120 | const auto proxy_addr = std::uintptr_t(team_prop->m_ProxyFn); 121 | g_player_resource = *reinterpret_cast(proxy_addr + 0x10); 122 | } 123 | 124 | // If we aren't unloaded correctly (like when you close csgo) 125 | // we should just leak the hooks, since the hooked instances 126 | // might be already destroyed 127 | auto uninitialize() -> void 128 | { 129 | render::uninitialize(); 130 | 131 | //delete g_client_hook; 132 | //delete g_game_event_manager_hook; 133 | 134 | delete g_sequence_hook; 135 | } 136 | -------------------------------------------------------------------------------- /src/nSkinz.hpp: -------------------------------------------------------------------------------- 1 | /* This file is part of nSkinz by namazso, licensed under the MIT license: 2 | * 3 | * MIT License 4 | * 5 | * Copyright (c) namazso 2018 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | #pragma once 26 | #include "SDK.hpp" 27 | #include "recv_proxy_hook.hpp" 28 | 29 | template 30 | auto get_entity_from_handle(sdk::CBaseHandle h) -> T* 31 | { 32 | if(h == sdk::INVALID_EHANDLE_INDEX) 33 | return nullptr; 34 | 35 | return static_cast(g_entity_list->GetClientEntityFromHandle(h)); 36 | } 37 | 38 | auto ensure_dynamic_hooks() -> void; 39 | auto get_client_name() -> const char*; 40 | 41 | extern recv_prop_hook* g_sequence_hook; -------------------------------------------------------------------------------- /src/recv_proxy_hook.hpp: -------------------------------------------------------------------------------- 1 | /* This file is part of nSkinz by namazso, licensed under the MIT license: 2 | * 3 | * MIT License 4 | * 5 | * Copyright (c) namazso 2018 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | #pragma once 26 | #include "SDK.hpp" 27 | 28 | class recv_prop_hook 29 | { 30 | public: 31 | recv_prop_hook(sdk::RecvProp* prop, const sdk::RecvVarProxyFn proxy_fn) : 32 | m_property(prop), 33 | m_original_proxy_fn(prop->m_ProxyFn) 34 | { 35 | set_proxy_function(proxy_fn); 36 | } 37 | 38 | ~recv_prop_hook() 39 | { 40 | m_property->m_ProxyFn = m_original_proxy_fn; 41 | } 42 | 43 | auto get_original_function() const -> sdk::RecvVarProxyFn 44 | { 45 | return m_original_proxy_fn; 46 | } 47 | 48 | auto set_proxy_function(const sdk::RecvVarProxyFn proxy_fn) const -> void 49 | { 50 | m_property->m_ProxyFn = proxy_fn; 51 | } 52 | 53 | private: 54 | sdk::RecvProp* m_property; 55 | sdk::RecvVarProxyFn m_original_proxy_fn; 56 | }; 57 | -------------------------------------------------------------------------------- /src/render.cpp: -------------------------------------------------------------------------------- 1 | /* This file is part of nSkinz by namazso, licensed under the MIT license: 2 | * 3 | * MIT License 4 | * 5 | * Copyright (c) namazso 2018 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | #include "render.hpp" 26 | #include "SDK.hpp" 27 | #include "Utilities/platform.hpp" 28 | 29 | // Renderer for windows. Maybe sometime i'll make a linux one 30 | 31 | #include 32 | #include 33 | 34 | #include 35 | #include 36 | 37 | // Implement this somewhere 38 | extern void draw_gui(); 39 | 40 | extern LRESULT ImGui_ImplWin32_WndProcHandler(HWND, UINT, WPARAM, LPARAM); 41 | 42 | namespace render 43 | { 44 | static vmt_smart_hook* s_d3d_hook; 45 | 46 | static bool s_ready = false; 47 | static bool s_active = false; 48 | 49 | struct d3d9_state 50 | { 51 | D3DMATRIX transform_world[4]; 52 | D3DMATRIX transform_view; 53 | D3DMATRIX transform_projection; 54 | D3DMATRIX transform_texture[8]; 55 | DWORD srgbwrite; 56 | DWORD colorwrite; 57 | DWORD fvf; 58 | 59 | IDirect3DVertexBuffer9* stream_data = nullptr; 60 | UINT stream_offset; 61 | UINT stream_stride; 62 | 63 | IDirect3DBaseTexture9* texture = nullptr; 64 | IDirect3DSurface9* target = nullptr; 65 | IDirect3DIndexBuffer9* indices = nullptr; 66 | IDirect3DVertexDeclaration9* vertex_declaration = nullptr; 67 | IDirect3DPixelShader9* pixel_shader = nullptr; 68 | IDirect3DVertexShader9* vertex_shader = nullptr; 69 | 70 | ~d3d9_state() 71 | { 72 | if (stream_data) 73 | stream_data->Release(); 74 | if (texture) 75 | texture->Release(); 76 | if (target) 77 | target->Release(); 78 | if (indices) 79 | indices->Release(); 80 | if (vertex_declaration) 81 | vertex_declaration->Release(); 82 | if (pixel_shader) 83 | pixel_shader->Release(); 84 | if (vertex_shader) 85 | vertex_shader->Release(); 86 | } 87 | 88 | auto save(IDirect3DDevice9* device) -> void 89 | { 90 | device->GetTransform(D3DTS_WORLD, &transform_world[0]); 91 | device->GetTransform(D3DTS_WORLD1, &transform_world[1]); 92 | device->GetTransform(D3DTS_WORLD2, &transform_world[2]); 93 | device->GetTransform(D3DTS_WORLD3, &transform_world[3]); 94 | device->GetTransform(D3DTS_VIEW, &transform_view); 95 | device->GetTransform(D3DTS_PROJECTION, &transform_projection); 96 | for (auto i = 0; i < 8; ++i) 97 | device->GetTransform(D3DTRANSFORMSTATETYPE(D3DTS_TEXTURE0 + i), &transform_texture[i]); 98 | 99 | device->GetRenderState(D3DRS_SRGBWRITEENABLE, &srgbwrite); 100 | device->GetRenderState(D3DRS_SRGBWRITEENABLE, &colorwrite); 101 | device->GetFVF(&fvf); 102 | 103 | device->GetStreamSource(0, &stream_data, &stream_offset, &stream_stride); 104 | 105 | device->GetTexture(0, &texture); 106 | device->GetRenderTarget(0, &target); 107 | device->GetIndices(&indices); 108 | device->GetVertexDeclaration(&vertex_declaration); 109 | device->GetPixelShader(&pixel_shader); 110 | device->GetVertexShader(&vertex_shader); 111 | } 112 | 113 | auto load(IDirect3DDevice9* device) const -> void 114 | { 115 | device->SetTransform(D3DTS_WORLD, &transform_world[0]); 116 | device->SetTransform(D3DTS_WORLD1, &transform_world[1]); 117 | device->SetTransform(D3DTS_WORLD2, &transform_world[2]); 118 | device->SetTransform(D3DTS_WORLD3, &transform_world[3]); 119 | device->SetTransform(D3DTS_VIEW, &transform_view); 120 | device->SetTransform(D3DTS_PROJECTION, &transform_projection); 121 | for (auto i = 0; i < 8; ++i) 122 | device->SetTransform(D3DTRANSFORMSTATETYPE(D3DTS_TEXTURE0 + i), &transform_texture[i]); 123 | 124 | device->SetRenderState(D3DRS_SRGBWRITEENABLE, srgbwrite); 125 | device->SetRenderState(D3DRS_SRGBWRITEENABLE, colorwrite); 126 | device->SetFVF(fvf); 127 | 128 | device->SetStreamSource(0, stream_data, stream_offset, stream_stride); 129 | 130 | device->SetTexture(0, texture); 131 | device->SetRenderTarget(0, target); 132 | device->SetIndices(indices); 133 | device->SetVertexDeclaration(vertex_declaration); 134 | device->SetPixelShader(pixel_shader); 135 | device->SetVertexShader(vertex_shader); 136 | } 137 | }; 138 | 139 | struct Reset 140 | { 141 | static auto COM_DECLSPEC_NOTHROW STDMETHODCALLTYPE hooked(IDirect3DDevice9* thisptr, D3DPRESENT_PARAMETERS* params) -> HRESULT 142 | { 143 | if(!s_ready) 144 | return m_original(thisptr, params); 145 | 146 | ImGui_ImplDX9_InvalidateDeviceObjects(); 147 | 148 | const auto result = m_original(thisptr, params); 149 | 150 | ImGui_ImplDX9_CreateDeviceObjects(); 151 | 152 | return result; 153 | } 154 | 155 | static decltype(&hooked) m_original; 156 | }; 157 | 158 | decltype(Reset::m_original) Reset::m_original; 159 | 160 | struct EndScene 161 | { 162 | static auto COM_DECLSPEC_NOTHROW STDMETHODCALLTYPE hooked(IDirect3DDevice9* thisptr) -> HRESULT 163 | { 164 | static void* ret_addr; 165 | if (!ret_addr) 166 | ret_addr = _ReturnAddress(); 167 | 168 | if(_ReturnAddress() == ret_addr) 169 | { 170 | // Save the state to prevent messing up stuff 171 | // Doesn't work yet 172 | //d3d9_state state; 173 | //state.save(thisptr); 174 | 175 | IDirect3DStateBlock9* state; 176 | thisptr->CreateStateBlock(D3DSBT_PIXELSTATE, &state); 177 | 178 | //fix drawing without cl_showfps 179 | thisptr->SetRenderState(D3DRS_COLORWRITEENABLE, 0xFFFFFFFF); 180 | 181 | //thisptr->SetRenderState(D3DRS_SRGBWRITEENABLE, 0); 182 | 183 | static void* saved_hwnd; 184 | 185 | if (s_active) 186 | { 187 | if (!saved_hwnd) 188 | { 189 | // We could do this with cvars, but too much work to implement a whole cvar interface just for this. 190 | //g_engine->ClientCmd_Unrestricted("cl_mouseenable 0"); 191 | //g_input_system->EnableInput(false); 192 | //mouse_enabled = false; 193 | std::swap(saved_hwnd, g_input_system->get_window()); 194 | } 195 | 196 | ImGui::GetIO().MouseDrawCursor = true; 197 | 198 | ImGui_ImplDX9_NewFrame(); 199 | 200 | draw_gui(); 201 | 202 | ImGui::Render(); 203 | } 204 | else 205 | { 206 | if (saved_hwnd) 207 | { 208 | //g_engine->ClientCmd_Unrestricted("cl_mouseenable 1"); 209 | g_input_system->EnableInput(true); //reenabling this fixed the movement. 210 | //mouse_enabled = true; 211 | std::swap(saved_hwnd, g_input_system->get_window()); 212 | } 213 | } 214 | 215 | //state.load(thisptr); 216 | state->Apply(); 217 | state->Release(); 218 | } 219 | 220 | return m_original(thisptr); 221 | } 222 | 223 | static decltype(&hooked) m_original; 224 | }; 225 | 226 | decltype(EndScene::m_original) EndScene::m_original; 227 | 228 | static auto set_imgui_style() -> void 229 | { 230 | auto& style = ImGui::GetStyle(); 231 | 232 | style.ChildWindowRounding = 0.f; 233 | style.GrabRounding = 0.f; 234 | style.WindowRounding = 0.f; 235 | style.ScrollbarRounding = 0.f; 236 | style.FrameRounding = 0.f; 237 | style.WindowTitleAlign = ImVec2(0.5f, 0.5f); 238 | 239 | style.Colors[ImGuiCol_Text] = ImVec4(0.73f, 0.73f, 0.73f, 1.00f); 240 | style.Colors[ImGuiCol_TextDisabled] = ImVec4(0.50f, 0.50f, 0.50f, 1.00f); 241 | style.Colors[ImGuiCol_WindowBg] = ImVec4(0.26f, 0.26f, 0.26f, 0.95f); 242 | style.Colors[ImGuiCol_ChildWindowBg] = ImVec4(0.28f, 0.28f, 0.28f, 1.00f); 243 | style.Colors[ImGuiCol_PopupBg] = ImVec4(0.26f, 0.26f, 0.26f, 1.00f); 244 | style.Colors[ImGuiCol_Border] = ImVec4(0.26f, 0.26f, 0.26f, 1.00f); 245 | style.Colors[ImGuiCol_BorderShadow] = ImVec4(0.26f, 0.26f, 0.26f, 1.00f); 246 | style.Colors[ImGuiCol_FrameBg] = ImVec4(0.16f, 0.16f, 0.16f, 1.00f); 247 | style.Colors[ImGuiCol_FrameBgHovered] = ImVec4(0.16f, 0.16f, 0.16f, 1.00f); 248 | style.Colors[ImGuiCol_FrameBgActive] = ImVec4(0.16f, 0.16f, 0.16f, 1.00f); 249 | style.Colors[ImGuiCol_TitleBg] = ImVec4(0.36f, 0.36f, 0.36f, 1.00f); 250 | style.Colors[ImGuiCol_TitleBgCollapsed] = ImVec4(0.36f, 0.36f, 0.36f, 1.00f); 251 | style.Colors[ImGuiCol_TitleBgActive] = ImVec4(0.36f, 0.36f, 0.36f, 1.00f); 252 | style.Colors[ImGuiCol_MenuBarBg] = ImVec4(0.26f, 0.26f, 0.26f, 1.00f); 253 | style.Colors[ImGuiCol_ScrollbarBg] = ImVec4(0.21f, 0.21f, 0.21f, 1.00f); 254 | style.Colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.36f, 0.36f, 0.36f, 1.00f); 255 | style.Colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.36f, 0.36f, 0.36f, 1.00f); 256 | style.Colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.36f, 0.36f, 0.36f, 1.00f); 257 | style.Colors[ImGuiCol_ComboBg] = ImVec4(0.32f, 0.32f, 0.32f, 1.00f); 258 | style.Colors[ImGuiCol_CheckMark] = ImVec4(0.78f, 0.78f, 0.78f, 1.00f); 259 | style.Colors[ImGuiCol_SliderGrab] = ImVec4(0.74f, 0.74f, 0.74f, 1.00f); 260 | style.Colors[ImGuiCol_SliderGrabActive] = ImVec4(0.74f, 0.74f, 0.74f, 1.00f); 261 | style.Colors[ImGuiCol_Button] = ImVec4(0.36f, 0.36f, 0.36f, 1.00f); 262 | style.Colors[ImGuiCol_ButtonHovered] = ImVec4(0.43f, 0.43f, 0.43f, 1.00f); 263 | style.Colors[ImGuiCol_ButtonActive] = ImVec4(0.11f, 0.11f, 0.11f, 1.00f); 264 | style.Colors[ImGuiCol_Header] = ImVec4(0.36f, 0.36f, 0.36f, 1.00f); 265 | style.Colors[ImGuiCol_HeaderHovered] = ImVec4(0.36f, 0.36f, 0.36f, 1.00f); 266 | style.Colors[ImGuiCol_HeaderActive] = ImVec4(0.36f, 0.36f, 0.36f, 1.00f); 267 | style.Colors[ImGuiCol_Column] = ImVec4(0.39f, 0.39f, 0.39f, 1.00f); 268 | style.Colors[ImGuiCol_ColumnHovered] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f); 269 | style.Colors[ImGuiCol_ColumnActive] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f); 270 | style.Colors[ImGuiCol_ResizeGrip] = ImVec4(0.36f, 0.36f, 0.36f, 1.00f); 271 | style.Colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f); 272 | style.Colors[ImGuiCol_ResizeGripActive] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f); 273 | style.Colors[ImGuiCol_CloseButton] = ImVec4(0.59f, 0.59f, 0.59f, 1.00f); 274 | style.Colors[ImGuiCol_CloseButtonHovered] = ImVec4(0.98f, 0.39f, 0.36f, 1.00f); 275 | style.Colors[ImGuiCol_CloseButtonActive] = ImVec4(0.98f, 0.39f, 0.36f, 1.00f); 276 | style.Colors[ImGuiCol_PlotLines] = ImVec4(0.39f, 0.39f, 0.39f, 1.00f); 277 | style.Colors[ImGuiCol_PlotLinesHovered] = ImVec4(1.00f, 0.43f, 0.35f, 1.00f); 278 | style.Colors[ImGuiCol_PlotHistogram] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f); 279 | style.Colors[ImGuiCol_PlotHistogramHovered] = ImVec4(1.00f, 0.60f, 0.00f, 1.00f); 280 | style.Colors[ImGuiCol_TextSelectedBg] = ImVec4(0.32f, 0.52f, 0.65f, 1.00f); 281 | style.Colors[ImGuiCol_ModalWindowDarkening] = ImVec4(0.20f, 0.20f, 0.20f, 0.50f); 282 | 283 | auto& io = ImGui::GetIO(); 284 | 285 | io.Fonts->AddFontDefault(); 286 | } 287 | 288 | static auto s_hwnd = HWND(nullptr); 289 | static auto s_original_wnd_proc = WNDPROC(nullptr); 290 | 291 | static auto does_imgui_handle_message(const UINT message_type) -> bool 292 | { 293 | switch(message_type) 294 | { 295 | case WM_LBUTTONDOWN: 296 | case WM_RBUTTONDOWN: 297 | case WM_MBUTTONDOWN: 298 | case WM_LBUTTONUP: 299 | case WM_RBUTTONUP: 300 | case WM_MBUTTONUP: 301 | case WM_MOUSEWHEEL: 302 | case WM_MOUSEMOVE: 303 | case WM_KEYDOWN: 304 | case WM_SYSKEYDOWN: 305 | case WM_KEYUP: 306 | case WM_SYSKEYUP: 307 | case WM_CHAR: 308 | return true; 309 | default: 310 | return false; 311 | } 312 | } 313 | 314 | static auto handle_input_message(const UINT message_type, const WPARAM w_param, const LPARAM l_param) -> bool 315 | { 316 | if(!s_ready) 317 | return false; 318 | 319 | if(message_type == WM_KEYUP && w_param == VK_INSERT) 320 | s_active = !s_active; 321 | 322 | if(s_active && does_imgui_handle_message(message_type)) 323 | { 324 | ImGui_ImplWin32_WndProcHandler(s_hwnd, message_type, w_param, l_param); 325 | return true; 326 | } 327 | 328 | return false; 329 | } 330 | 331 | static auto CALLBACK wndproc_hook(const HWND hwnd, const UINT message, const WPARAM w_param, const LPARAM l_param) -> LRESULT 332 | { 333 | if(handle_input_message(message, w_param, l_param)) 334 | return 0; 335 | 336 | return CallWindowProcW(s_original_wnd_proc, hwnd, message, w_param, l_param); 337 | }; 338 | 339 | static auto swap_wndproc(const HWND hwnd, WNDPROC new_proc) -> WNDPROC 340 | { 341 | return reinterpret_cast(SetWindowLongW(hwnd, GWLP_WNDPROC, LONG_PTR(new_proc))); 342 | } 343 | 344 | auto initialize() -> void 345 | { 346 | if(s_ready) 347 | { 348 | assert(false); 349 | return; 350 | } 351 | 352 | s_hwnd = HWND(g_input_system->get_window()); 353 | assert(s_hwnd); 354 | 355 | s_original_wnd_proc = swap_wndproc(s_hwnd, &wndproc_hook); 356 | assert(s_original_wnd_proc); 357 | 358 | const auto device_addr = platform::find_pattern("shaderapidx9.dll", "\xA1\x00\x00\x00\x00\x50\x8B\x08\xFF\x51\x0C", "x????xxxxxx"); 359 | const auto device = **reinterpret_cast(device_addr + 1); 360 | assert(device); 361 | 362 | s_d3d_hook = new vmt_smart_hook(device); 363 | s_d3d_hook->apply_hook(16); 364 | s_d3d_hook->apply_hook(42); 365 | 366 | const auto result = ImGui_ImplDX9_Init(s_hwnd, device); 367 | assert(result); 368 | if(result) 369 | s_ready = true; 370 | 371 | set_imgui_style(); 372 | } 373 | 374 | auto uninitialize() -> void 375 | { 376 | if(!s_ready) 377 | return; 378 | 379 | s_ready = false; 380 | 381 | swap_wndproc(s_hwnd, s_original_wnd_proc); 382 | delete s_d3d_hook; 383 | 384 | // In case our hooks are still running 385 | Sleep(100); 386 | } 387 | } 388 | -------------------------------------------------------------------------------- /src/render.hpp: -------------------------------------------------------------------------------- 1 | /* This file is part of nSkinz by namazso, licensed under the MIT license: 2 | * 3 | * MIT License 4 | * 5 | * Copyright (c) namazso 2018 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | #pragma once 26 | 27 | // Other parts don't need to know what goes behind the scenes 28 | namespace render 29 | { 30 | extern void initialize(); 31 | extern void uninitialize(); 32 | } -------------------------------------------------------------------------------- /src/sticker_changer.cpp: -------------------------------------------------------------------------------- 1 | /* This file is part of nSkinz by namazso, licensed under the MIT license: 2 | * 3 | * MIT License 4 | * 5 | * Copyright (c) namazso 2018 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | #include 26 | #include "SDK.hpp" 27 | #include "config.hpp" 28 | 29 | enum class EStickerAttributeType 30 | { 31 | Index, 32 | Wear, 33 | Scale, 34 | Rotation 35 | }; 36 | 37 | static auto s_econ_item_interface_wrapper_offset = std::uint16_t(0); 38 | 39 | struct GetStickerAttributeBySlotIndexFloat 40 | { 41 | static auto __fastcall hooked(void* thisptr, void*, const int slot, 42 | const EStickerAttributeType attribute, const float unknown) -> float 43 | { 44 | auto item = reinterpret_cast(std::uintptr_t(thisptr) - s_econ_item_interface_wrapper_offset); 45 | 46 | const auto defindex = item->GetItemDefinitionIndex(); 47 | 48 | auto config = g_config.get_by_definition_index(defindex); 49 | 50 | if(config) 51 | { 52 | switch(attribute) 53 | { 54 | case EStickerAttributeType::Wear: 55 | return config->stickers.at(slot).wear; 56 | case EStickerAttributeType::Scale: 57 | return config->stickers.at(slot).scale; 58 | case EStickerAttributeType::Rotation: 59 | return config->stickers.at(slot).rotation; 60 | default: 61 | break; 62 | } 63 | } 64 | 65 | return m_original(thisptr, nullptr, slot, attribute, unknown); 66 | } 67 | 68 | static decltype(&hooked) m_original; 69 | }; 70 | 71 | decltype(GetStickerAttributeBySlotIndexFloat::m_original) GetStickerAttributeBySlotIndexFloat::m_original; 72 | 73 | struct GetStickerAttributeBySlotIndexInt 74 | { 75 | static auto __fastcall hooked(void* thisptr, void*, const int slot, 76 | const EStickerAttributeType attribute, const int unknown) -> int 77 | { 78 | auto item = reinterpret_cast(std::uintptr_t(thisptr) - s_econ_item_interface_wrapper_offset); 79 | 80 | if(attribute == EStickerAttributeType::Index) 81 | { 82 | const auto defindex = item->GetItemDefinitionIndex(); 83 | 84 | auto config = g_config.get_by_definition_index(defindex); 85 | 86 | if(config) 87 | return config->stickers.at(slot).kit; 88 | } 89 | 90 | return m_original(thisptr, nullptr, slot, attribute, unknown); 91 | } 92 | 93 | static decltype(&hooked) m_original; 94 | }; 95 | 96 | decltype(GetStickerAttributeBySlotIndexInt::m_original) GetStickerAttributeBySlotIndexInt::m_original; 97 | 98 | auto apply_sticker_changer(sdk::C_BaseAttributableItem* item) -> void 99 | { 100 | if(!s_econ_item_interface_wrapper_offset) 101 | s_econ_item_interface_wrapper_offset = netvar_manager::get().get_offset(FNV("CBaseAttributableItem->m_Item")) + 0xC; 102 | 103 | static vmt_multi_hook hook; 104 | 105 | const auto econ_item_interface_wrapper = std::uintptr_t(item) + s_econ_item_interface_wrapper_offset; 106 | 107 | if(hook.initialize_and_hook_instance(reinterpret_cast(econ_item_interface_wrapper))) 108 | { 109 | hook.apply_hook(4); 110 | hook.apply_hook(5); 111 | } 112 | } -------------------------------------------------------------------------------- /src/sticker_changer.hpp: -------------------------------------------------------------------------------- 1 | /* This file is part of nSkinz by namazso, licensed under the MIT license: 2 | * 3 | * MIT License 4 | * 5 | * Copyright (c) namazso 2018 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | #pragma once 26 | #include "SDK.hpp" 27 | 28 | extern auto apply_sticker_changer(sdk::C_BaseAttributableItem* item) -> void; -------------------------------------------------------------------------------- /src/update_check.cpp: -------------------------------------------------------------------------------- 1 | /* This file is part of nSkinz by namazso, licensed under the MIT license: 2 | * 3 | * MIT License 4 | * 5 | * Copyright (c) namazso 2018 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | #include "update_check.hpp" 26 | #include "Utilities/platform.hpp" 27 | #include "SDK/declarations.hpp" 28 | 29 | #include 30 | #include 31 | 32 | using json = nlohmann::json; 33 | 34 | namespace cx 35 | { 36 | constexpr auto cx_strcmp_part(const char* const a, const char* const b) -> bool 37 | { 38 | return *b ? (*a == *b && cx_strcmp_part(a + 1, b + 1)) : true; 39 | } 40 | 41 | constexpr auto month_str_to_int(const char* const str) -> unsigned 42 | { 43 | return 44 | cx_strcmp_part(str, "Jan") ? 1 : 45 | cx_strcmp_part(str, "Feb") ? 2 : 46 | cx_strcmp_part(str, "Mar") ? 3 : 47 | cx_strcmp_part(str, "Apr") ? 4 : 48 | cx_strcmp_part(str, "May") ? 5 : 49 | cx_strcmp_part(str, "Jun") ? 6 : 50 | cx_strcmp_part(str, "Jul") ? 7 : 51 | cx_strcmp_part(str, "Aug") ? 8 : 52 | cx_strcmp_part(str, "Sep") ? 9 : 53 | cx_strcmp_part(str, "Oct") ? 10 : 54 | cx_strcmp_part(str, "Nov") ? 11 : 12; 55 | } 56 | 57 | constexpr auto char_to_int(const unsigned char c) -> unsigned 58 | { 59 | return (c == ' ' ? '0' : c) - '0'; 60 | } 61 | 62 | constexpr auto twochar_to_int(const char* const str) -> unsigned 63 | { 64 | return (char_to_int(str[0])) * 10 + char_to_int(str[1]); 65 | } 66 | 67 | constexpr auto year_str_to_int(const char* const str) -> unsigned 68 | { 69 | return (char_to_int(str[0])) * 1000 + (char_to_int(str[1])) * 100 + (char_to_int(str[2])) * 10 + char_to_int(str[3]); 70 | } 71 | 72 | constexpr auto days_from_civil(const int y, const int m, const int d) -> unsigned 73 | { 74 | const auto yc = y - (m <= 2 ? 1 : 0); 75 | const auto era = (yc >= 0 ? yc : yc - 399) / 400; 76 | const auto yoe = unsigned(yc - era * 400); // [0, 399] 77 | const auto doy = unsigned((153 * (m + (m > 2 ? -3 : 9)) + 2) / 5 + d - 1); // [0, 365] 78 | const auto doe = yoe * 365 + yoe / 4 - yoe / 100 + doy; // [0, 146096] 79 | return era * 146097 + int(doe) - 719468; 80 | } 81 | 82 | constexpr auto date_str_to_days(const char* const str) -> unsigned 83 | { 84 | return days_from_civil(year_str_to_int(str + 7), month_str_to_int(str), twochar_to_int(str + 4)); 85 | } 86 | 87 | constexpr auto time_str_to_second(const char* const str) -> unsigned 88 | { 89 | return (twochar_to_int(str) * 60 + twochar_to_int(str + 3)) * 60 + twochar_to_int(str + 6); 90 | } 91 | 92 | constexpr auto unix_time() -> std::uint64_t 93 | { 94 | return std::uint64_t(date_str_to_days(__DATE__)) * 24 * 60 * 60 + time_str_to_second(__TIME__); 95 | } 96 | } 97 | 98 | using HTTPRequestHandle = std::uint32_t; 99 | enum : HTTPRequestHandle { INVALID_HTTPREQUEST_HANDLE = 0 }; 100 | 101 | using SteamAPICall_t = std::uint64_t; 102 | enum : SteamAPICall_t { k_uAPICallInvalid = 0 }; 103 | 104 | enum class EHTTPMethod 105 | { 106 | Invalid = 0, 107 | GET, 108 | HEAD, 109 | POST, 110 | PUT, 111 | DELETE, 112 | OPTIONS, 113 | PATCH 114 | }; 115 | 116 | class ISteamHTTP 117 | { 118 | public: 119 | virtual HTTPRequestHandle CreateHTTPRequest(EHTTPMethod eHTTPRequestMethod, const char* pchAbsoluteURL) = 0; 120 | virtual bool SetHTTPRequestContextValue(HTTPRequestHandle hRequest, std::uint64_t ulContextValue) = 0; 121 | virtual bool SetHTTPRequestNetworkActivityTimeout(HTTPRequestHandle hRequest, std::uint32_t unTimeoutSeconds) = 0; 122 | virtual bool SetHTTPRequestHeaderValue(HTTPRequestHandle hRequest, const char* pchHeaderName, const char* pchHeaderValue) = 0; 123 | virtual bool SetHTTPRequestGetOrPostParameter(HTTPRequestHandle hRequest, const char* pchParamName, const char* pchParamValue) = 0; 124 | virtual bool SendHTTPRequest(HTTPRequestHandle hRequest, SteamAPICall_t* pCallHandle) = 0; 125 | virtual bool SendHTTPRequestAndStreamResponse(HTTPRequestHandle hRequest, SteamAPICall_t* pCallHandle) = 0; 126 | virtual bool DeferHTTPRequest(HTTPRequestHandle hRequest) = 0; 127 | virtual bool PrioritizeHTTPRequest(HTTPRequestHandle hRequest) = 0; 128 | virtual bool GetHTTPResponseHeaderSize(HTTPRequestHandle hRequest, const char* pchHeaderName, std::uint32_t* unResponseHeaderSize) = 0; 129 | virtual bool GetHTTPResponseHeaderValue(HTTPRequestHandle hRequest, const char* pchHeaderName, std::uint8_t* pHeaderValueBuffer, std::uint32_t unBufferSize) = 0; 130 | virtual bool GetHTTPResponseBodySize(HTTPRequestHandle hRequest, std::uint32_t* unBodySize) = 0; 131 | virtual bool GetHTTPResponseBodyData(HTTPRequestHandle hRequest, std::uint8_t* pBodyDataBuffer, std::uint32_t unBufferSize) = 0; 132 | virtual bool GetHTTPStreamingResponseBodyData(HTTPRequestHandle hRequest, std::uint32_t cOffset, std::uint8_t* pBodyDataBuffer, std::uint32_t unBufferSize) = 0; 133 | virtual bool ReleaseHTTPRequest(HTTPRequestHandle hRequest) = 0; 134 | virtual bool GetHTTPDownloadProgressPct(HTTPRequestHandle hRequest, float* pflPercentOut) = 0; 135 | virtual bool SetHTTPRequestRawPostBody(HTTPRequestHandle hRequest, const char* pchContentType, std::uint8_t* pubBody, std::uint32_t unBodyLen) = 0; 136 | }; 137 | 138 | ISteamHTTP* s_steam_http; 139 | 140 | #pragma pack(push, 8) 141 | 142 | struct HTTPRequestCompleted_t 143 | { 144 | enum { k_iCallback = 2101 }; 145 | HTTPRequestHandle m_hRequest; 146 | std::uint64_t m_ulContextValue; 147 | bool m_bRequestSuccessful; 148 | int m_eStatusCode; 149 | std::uint32_t m_unBodySize; 150 | }; 151 | 152 | #pragma pack(pop) 153 | 154 | class VersionCheckCallback 155 | { 156 | public: 157 | virtual void Run(HTTPRequestCompleted_t *pvParam); 158 | virtual void Run(HTTPRequestCompleted_t *pvParam, bool bIOFailure, SteamAPICall_t hSteamAPICall) { Run(pvParam); }; 159 | virtual int GetCallbackSizeBytes() { return sizeof(HTTPRequestCompleted_t); } 160 | protected: 161 | std::uint8_t m_nCallbackFlags = 0; 162 | int m_iCallback = HTTPRequestCompleted_t::k_iCallback; 163 | }; 164 | 165 | static VersionCheckCallback s_check_callback; 166 | 167 | bool g_update_needed = false; 168 | std::vector g_commits_since_compile; 169 | 170 | void from_json(const json& j, commit_entry& commit) 171 | { 172 | commit.author = j["commit"]["author"]["name"].get(); 173 | commit.date = j["commit"]["author"]["date"].get(); 174 | commit.message = j["commit"]["message"].get(); 175 | } 176 | 177 | void VersionCheckCallback::Run(HTTPRequestCompleted_t* pvParam) 178 | { 179 | if(pvParam->m_eStatusCode == 200 && pvParam->m_unBodySize > 50) 180 | { 181 | 182 | std::string body; 183 | 184 | body.resize(pvParam->m_unBodySize + 1); 185 | 186 | const auto body_cstr = reinterpret_cast(const_cast(body.data())); 187 | 188 | s_steam_http->GetHTTPResponseBodyData(pvParam->m_hRequest, body_cstr, pvParam->m_unBodySize); 189 | 190 | body_cstr[pvParam->m_unBodySize] = 0; 191 | 192 | try 193 | { 194 | g_commits_since_compile = json::parse(body).get>(); 195 | g_update_needed = true; 196 | } 197 | catch(const std::exception&) 198 | { 199 | // Do nothing. Something is malformed. 200 | } 201 | } 202 | 203 | s_steam_http->ReleaseHTTPRequest(pvParam->m_hRequest); 204 | } 205 | 206 | static auto SteamAPI_RegisterCallResult(VersionCheckCallback* callback, const SteamAPICall_t handle) -> void 207 | { 208 | static auto addr = platform::get_export("steam_api.dll", "SteamAPI_RegisterCallResult"); 209 | reinterpret_cast(addr)(callback, handle); 210 | } 211 | 212 | static auto GetISteamHTTP(const char* version) -> ISteamHTTP* 213 | { 214 | const auto steamclient_addr = platform::get_export("steam_api.dll", "SteamClient"); 215 | const auto gethsteamuser_addr = platform::get_export("steam_api.dll", "SteamAPI_GetHSteamUser"); 216 | const auto gethsteampipe_addr = platform::get_export("steam_api.dll", "SteamAPI_GetHSteamPipe"); 217 | 218 | const auto thisptr = reinterpret_cast(steamclient_addr)(); 219 | const auto steamuser = reinterpret_cast(gethsteamuser_addr)(); 220 | const auto steampipe = reinterpret_cast(gethsteampipe_addr)(); 221 | 222 | const auto vfunc = get_vfunc(thisptr, 23); 223 | 224 | return vfunc(thisptr, steamuser, steampipe, version); 225 | } 226 | 227 | auto run_update_check() -> void 228 | { 229 | s_steam_http = GetISteamHTTP("STEAMHTTP_INTERFACE_VERSION002"); 230 | 231 | const auto handle = s_steam_http->CreateHTTPRequest(EHTTPMethod::GET, "http://api.github.com/repos/namazso/nSkinz/commits"); 232 | 233 | constexpr static auto build_time = std::integral_constant::value; 234 | 235 | tm build_time_tm; 236 | gmtime_s(&build_time_tm, &build_time); 237 | char build_time_str[32]; 238 | strftime(build_time_str, sizeof build_time_str, "%FT%TZ", &build_time_tm); 239 | 240 | s_steam_http->SetHTTPRequestGetOrPostParameter(handle, "since", build_time_str); 241 | 242 | SteamAPICall_t api_call; 243 | s_steam_http->SendHTTPRequest(handle, &api_call); 244 | 245 | SteamAPI_RegisterCallResult(&s_check_callback, api_call); 246 | } 247 | 248 | -------------------------------------------------------------------------------- /src/update_check.hpp: -------------------------------------------------------------------------------- 1 | /* This file is part of nSkinz by namazso, licensed under the MIT license: 2 | * 3 | * MIT License 4 | * 5 | * Copyright (c) namazso 2018 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | #pragma once 26 | #include 27 | #include 28 | 29 | extern auto run_update_check() -> void; 30 | 31 | struct commit_entry 32 | { 33 | std::string author; 34 | std::string date; 35 | std::string message; 36 | }; 37 | 38 | extern bool g_update_needed; 39 | extern std::vector g_commits_since_compile; --------------------------------------------------------------------------------