mirror of
https://github.com/EricPlayZ/EGameTools.git
synced 2026-10-10 04:43:03 +08:00
Compare commits
64 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 190d4232bd | |||
| 642d0f17e2 | |||
| 405cdcef1f | |||
| 7993931f88 | |||
| c163301344 | |||
| 8b4e3c4b75 | |||
| 0ee417db70 | |||
| 3280768125 | |||
| df039e495e | |||
| 4803e3b5ce | |||
| 4961177ef7 | |||
| d907cf0b0d | |||
| f6848f37c7 | |||
| 2d9c4bcd45 | |||
| 67a98a8130 | |||
| 4766d630ac | |||
| 71b67d0e46 | |||
| 2cadab18ae | |||
| 3c31878ef8 | |||
| 263db930a4 | |||
| 099fd311e3 | |||
| d3f36c047e | |||
| 96fa5c0a0f | |||
| 598c88bbd6 | |||
| 3d546cc198 | |||
| 38acd3ebe0 | |||
| 4043de504b | |||
| f50c883efc | |||
| dae6072423 | |||
| 61922760a3 | |||
| ce56c7e71e | |||
| 7c79bc18e3 | |||
| bb21fb7446 | |||
| ef4e179600 | |||
| b17ce3e9a9 | |||
| 55e4712990 | |||
| 870a625728 | |||
| 1bd10e06d6 | |||
| ba09473499 | |||
| 7876a52b39 | |||
| a7435e3088 | |||
| 725b0bff41 | |||
| 7dc2fd4de1 | |||
| da99802546 | |||
| bd19d3f45a | |||
| 05fcf607f1 | |||
| fa6a9e0fb8 | |||
| f692641c28 | |||
| 0b6c04f107 | |||
| e3a90c6d58 | |||
| 7d048316e9 | |||
| a580147272 | |||
| 3a51834d4b | |||
| 1dcd0b884e | |||
| e2be96af15 | |||
| f4699cdd30 | |||
| 65e2dc3d44 | |||
| 0ec06592c4 | |||
| 0f3cd3546e | |||
| 0755d8523f | |||
| ba953c90be | |||
| 9a980ca48c | |||
| 4879e68867 | |||
| 4ca2ddf7b2 |
+2
-1
@@ -10,4 +10,5 @@
|
||||
/Tools/ExtractPlayerVarsFromDecompiledFunc/.vs
|
||||
/Tools/ExtractPlayerVarsFromDecompiledFunc/ExtractPlayerVarsFromDecompiledFunc/bin
|
||||
/Tools/ExtractPlayerVarsFromDecompiledFunc/ExtractPlayerVarsFromDecompiledFunc/obj
|
||||
/Tools/ExtractPlayerVarsFromDecompiledFunc/ExtractPlayerVarsFromDecompiledFunc/ExtractPlayerVarsFromDecompiledFunc.csproj.user
|
||||
/Tools/ExtractPlayerVarsFromDecompiledFunc/ExtractPlayerVarsFromDecompiledFunc/ExtractPlayerVarsFromDecompiledFunc.csproj.user
|
||||
/enc_temp_folder
|
||||
|
||||
@@ -30,19 +30,21 @@
|
||||
<ClCompile Include="source\game\Engine\CoPhysicsProperty.cpp" />
|
||||
<ClCompile Include="source\game\Engine\CVideoSettings.cpp" />
|
||||
<ClCompile Include="source\game\Engine\engine_hooks.cpp" />
|
||||
<ClCompile Include="source\game\Engine\engine_misc.cpp" />
|
||||
<ClCompile Include="source\game\GamePH\DayNightCycle.cpp" />
|
||||
<ClCompile Include="source\game\GamePH\FreeCamera.cpp" />
|
||||
<ClCompile Include="source\game\GamePH\GameDI_PH.cpp" />
|
||||
<ClCompile Include="source\game\GamePH\GameDI_PH2.cpp" />
|
||||
<ClCompile Include="source\game\GamePH\gen_TPPModel.cpp" />
|
||||
<ClCompile Include="source\game\GamePH\game_hooks.cpp" />
|
||||
<ClCompile Include="source\game\GamePH\InventoryContainerDI.cpp" />
|
||||
<ClCompile Include="source\game\GamePH\InventoryItem.cpp" />
|
||||
<ClCompile Include="source\game\GamePH\LevelDI.cpp" />
|
||||
<ClCompile Include="source\game\GamePH\LocalClientDI.cpp" />
|
||||
<ClCompile Include="source\game\GamePH\LogicalPlayer.cpp" />
|
||||
<ClCompile Include="source\game\GamePH\Other.cpp" />
|
||||
<ClCompile Include="source\game\GamePH\gameph_misc.cpp" />
|
||||
<ClCompile Include="source\game\GamePH\PlayerDI_PH.cpp" />
|
||||
<ClCompile Include="source\game\GamePH\PlayerHealthModule.cpp" />
|
||||
<ClCompile Include="source\game\GamePH\PlayerObjProperties.cpp" />
|
||||
<ClCompile Include="source\game\GamePH\PlayerInfectionModule.cpp" />
|
||||
<ClCompile Include="source\game\GamePH\PlayerState.cpp" />
|
||||
<ClCompile Include="source\game\GamePH\PlayerVariables.cpp" />
|
||||
<ClCompile Include="source\game\GamePH\SessionCooperativeDI.cpp" />
|
||||
@@ -89,16 +91,27 @@
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="source\kiero.cpp" />
|
||||
<ClCompile Include="source\memscan\memscan.c">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="source\memscan\util\util.c">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="source\menu\camera.cpp" />
|
||||
<ClCompile Include="source\menu\debug.cpp" />
|
||||
<ClCompile Include="source\menu\init.cpp" />
|
||||
<ClCompile Include="source\menu\menu.cpp" />
|
||||
<ClCompile Include="source\menu\misc.cpp" />
|
||||
<ClCompile Include="source\menu\player.cpp" />
|
||||
<ClCompile Include="source\menu\teleport.cpp" />
|
||||
<ClCompile Include="source\menu\weapon.cpp" />
|
||||
<ClCompile Include="source\menu\world.cpp" />
|
||||
<ClCompile Include="source\utils\files.cpp" />
|
||||
<ClCompile Include="source\utils\hook.cpp" />
|
||||
<ClCompile Include="source\utils\memory.cpp" />
|
||||
<ClCompile Include="source\utils\rtti.cpp" />
|
||||
<ClCompile Include="source\utils\sigscan.cpp" />
|
||||
<ClCompile Include="source\utils\texture.cpp" />
|
||||
<ClCompile Include="source\utils\time.cpp" />
|
||||
@@ -127,19 +140,23 @@
|
||||
<ClInclude Include="source\game\Engine\CoPhysicsProperty.h" />
|
||||
<ClInclude Include="source\game\Engine\CVideoSettings.h" />
|
||||
<ClInclude Include="source\game\Engine\engine_hooks.h" />
|
||||
<ClInclude Include="source\game\Engine\engine_misc.h" />
|
||||
<ClInclude Include="source\game\GamePH\CoBaseCameraProxy.h" />
|
||||
<ClInclude Include="source\game\GamePH\DayNightCycle.h" />
|
||||
<ClInclude Include="source\game\GamePH\FreeCamera.h" />
|
||||
<ClInclude Include="source\game\GamePH\GameDI_PH.h" />
|
||||
<ClInclude Include="source\game\GamePH\GameDI_PH2.h" />
|
||||
<ClInclude Include="source\game\GamePH\gen_TPPModel.h" />
|
||||
<ClInclude Include="source\game\GamePH\InventoryContainerDI.h" />
|
||||
<ClInclude Include="source\game\GamePH\InventoryItem.h" />
|
||||
<ClInclude Include="source\game\GamePH\InventoryMoney.h" />
|
||||
<ClInclude Include="source\game\GamePH\ItemDescWithContext.h" />
|
||||
<ClInclude Include="source\game\GamePH\LevelDI.h" />
|
||||
<ClInclude Include="source\game\GamePH\LocalClientDI.h" />
|
||||
<ClInclude Include="source\game\GamePH\LogicalPlayer.h" />
|
||||
<ClInclude Include="source\game\GamePH\Other.h" />
|
||||
<ClInclude Include="source\game\GamePH\gameph_misc.h" />
|
||||
<ClInclude Include="source\game\GamePH\PlayerDI_PH.h" />
|
||||
<ClInclude Include="source\game\GamePH\PlayerHealthModule.h" />
|
||||
<ClInclude Include="source\game\GamePH\PlayerObjProperties.h" />
|
||||
<ClInclude Include="source\game\GamePH\PlayerInfectionModule.h" />
|
||||
<ClInclude Include="source\game\GamePH\PlayerState.h" />
|
||||
<ClInclude Include="source\game\GamePH\PlayerVariables.h" />
|
||||
<ClInclude Include="source\game\GamePH\SessionCooperativeDI.h" />
|
||||
@@ -166,18 +183,23 @@
|
||||
<ClInclude Include="source\ImGui\imstb_truetype.h" />
|
||||
<ClInclude Include="source\ImGui\misc\freetype\imgui_freetype.h" />
|
||||
<ClInclude Include="source\kiero.h" />
|
||||
<ClInclude Include="source\memscan\memscan.h" />
|
||||
<ClInclude Include="source\memscan\util\util.h" />
|
||||
<ClInclude Include="source\menu\camera.h" />
|
||||
<ClInclude Include="source\menu\debug.h" />
|
||||
<ClInclude Include="source\menu\init.h" />
|
||||
<ClInclude Include="source\menu\menu.h" />
|
||||
<ClInclude Include="source\menu\misc.h" />
|
||||
<ClInclude Include="source\menu\player.h" />
|
||||
<ClInclude Include="source\menu\teleport.h" />
|
||||
<ClInclude Include="source\menu\weapon.h" />
|
||||
<ClInclude Include="source\menu\world.h" />
|
||||
<ClInclude Include="source\MinHook\MinHook.h" />
|
||||
<ClInclude Include="source\offsets.h" />
|
||||
<ClInclude Include="source\utils\files.h" />
|
||||
<ClInclude Include="source\utils\hook.h" />
|
||||
<ClInclude Include="source\utils\memory.h" />
|
||||
<ClInclude Include="source\utils\rtti.h" />
|
||||
<ClInclude Include="source\utils\sigscan.h" />
|
||||
<ClInclude Include="source\utils\texture.h" />
|
||||
<ClInclude Include="source\utils\time.h" />
|
||||
@@ -220,7 +242,7 @@
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<TargetExt>.asi</TargetExt>
|
||||
<TargetName>EGameTools</TargetName>
|
||||
<GenerateManifest>false</GenerateManifest>
|
||||
<GenerateManifest>true</GenerateManifest>
|
||||
<LibraryPath>$(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64)</LibraryPath>
|
||||
<IncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);</IncludePath>
|
||||
</PropertyGroup>
|
||||
@@ -255,8 +277,11 @@
|
||||
</Optimization>
|
||||
<IntrinsicFunctions>
|
||||
</IntrinsicFunctions>
|
||||
<AdditionalIncludeDirectories>pch;source\spdlog\include;source\ImGui\freetype\include;source\ImGui;source\MinHook;</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>pch;source\spdlog\include;source\ImGui\freetype\include;source\ImGui;source\MinHook;source\memscan;</AdditionalIncludeDirectories>
|
||||
<PrecompiledHeaderOutputFile>$(IntDir)$(TargetName)_$(PlatformTarget).pch</PrecompiledHeaderOutputFile>
|
||||
<DebugInformationFormat>OldStyle</DebugInformationFormat>
|
||||
<MultiProcessorCompilation>
|
||||
</MultiProcessorCompilation>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
@@ -268,6 +293,10 @@
|
||||
<EnableCOMDATFolding>
|
||||
</EnableCOMDATFolding>
|
||||
<AdditionalLibraryDirectories>source\spdlog\lib;source\ImGui\freetype\lib;source\MinHook\lib;</AdditionalLibraryDirectories>
|
||||
<AssemblyDebug>true</AssemblyDebug>
|
||||
<ImportLibrary />
|
||||
<FixedBaseAddress>
|
||||
</FixedBaseAddress>
|
||||
</Link>
|
||||
<PostBuildEvent>
|
||||
<Command>copy /Y "$(SolutionDir)Extra Files\Default Config\EGameTools.ini" "$(SolutionDir)$(PlatformShortName)\$(Configuration)\EGameTools.ini"</Command>
|
||||
@@ -285,22 +314,24 @@
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
<LanguageStandard>stdcpplatest</LanguageStandard>
|
||||
<AdditionalIncludeDirectories>pch;source\spdlog\include;source\ImGui\freetype\include;source\ImGui;source\MinHook;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<DebugInformationFormat>None</DebugInformationFormat>
|
||||
<AdditionalIncludeDirectories>pch;source\spdlog\include;source\ImGui\freetype\include;source\ImGui;source\MinHook;source\memscan;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<DebugInformationFormat>OldStyle</DebugInformationFormat>
|
||||
<RuntimeTypeInfo>false</RuntimeTypeInfo>
|
||||
<PrecompiledHeaderOutputFile>$(IntDir)$(TargetName)_$(PlatformTarget).pch</PrecompiledHeaderOutputFile>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>false</GenerateDebugInformation>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableUAC>false</EnableUAC>
|
||||
<AdditionalLibraryDirectories>source\spdlog\lib;source\ImGui\freetype\lib;source\MinHook\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalLibraryDirectories>source\spdlog\lib;source\ImGui\freetype\lib;source\MinHook\lib;source\CrashRpt\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>DbgHelp.lib;Version.lib;spdlog-mt.lib;freetype-mt.lib;libMinHook-x64-v141-mtd.lib;$(CoreLibraryDependencies);%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<ImportLibrary />
|
||||
<AdditionalOptions>/NOIMPLIB /NOEXP %(AdditionalOptions)</AdditionalOptions>
|
||||
<AssemblyDebug>true</AssemblyDebug>
|
||||
</Link>
|
||||
<PostBuildEvent>
|
||||
<Command>copy /Y "$(SolutionDir)Extra Files\Default Config\EGameTools.ini" "$(SolutionDir)$(PlatformShortName)\$(Configuration)\EGameTools.ini"</Command>
|
||||
|
||||
@@ -133,9 +133,6 @@
|
||||
<ClCompile Include="source\game\GamePH\GameDI_PH2.cpp">
|
||||
<Filter>game\GamePH</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="source\game\GamePH\gen_TPPModel.cpp">
|
||||
<Filter>game\GamePH</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="source\game\GamePH\game_hooks.cpp">
|
||||
<Filter>game\GamePH</Filter>
|
||||
</ClCompile>
|
||||
@@ -148,7 +145,7 @@
|
||||
<ClCompile Include="source\game\GamePH\LogicalPlayer.cpp">
|
||||
<Filter>game\GamePH</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="source\game\GamePH\Other.cpp">
|
||||
<ClCompile Include="source\game\GamePH\gameph_misc.cpp">
|
||||
<Filter>game\GamePH</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="source\game\GamePH\PlayerHealthModule.cpp">
|
||||
@@ -191,6 +188,33 @@
|
||||
<ClCompile Include="source\menu\init.cpp">
|
||||
<Filter>menu</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="source\game\Engine\engine_misc.cpp">
|
||||
<Filter>game\Engine</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="source\game\GamePH\PlayerInfectionModule.cpp">
|
||||
<Filter>game\GamePH</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="source\utils\rtti.cpp">
|
||||
<Filter>utils</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="source\menu\weapon.cpp">
|
||||
<Filter>menu</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="source\game\GamePH\InventoryItem.cpp">
|
||||
<Filter>game\GamePH</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="source\game\GamePH\InventoryContainerDI.cpp">
|
||||
<Filter>game\GamePH</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="source\menu\teleport.cpp">
|
||||
<Filter>menu</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="source\memscan\memscan.c">
|
||||
<Filter>memscan</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="source\memscan\util\util.c">
|
||||
<Filter>memscan\util</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="source\kiero.h" />
|
||||
@@ -343,9 +367,6 @@
|
||||
<ClInclude Include="source\game\GamePH\GameDI_PH2.h">
|
||||
<Filter>game\GamePH</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="source\game\GamePH\gen_TPPModel.h">
|
||||
<Filter>game\GamePH</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="source\game\GamePH\LevelDI.h">
|
||||
<Filter>game\GamePH</Filter>
|
||||
</ClInclude>
|
||||
@@ -355,7 +376,7 @@
|
||||
<ClInclude Include="source\game\GamePH\LogicalPlayer.h">
|
||||
<Filter>game\GamePH</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="source\game\GamePH\Other.h">
|
||||
<ClInclude Include="source\game\GamePH\gameph_misc.h">
|
||||
<Filter>game\GamePH</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="source\game\GamePH\PlayerHealthModule.h">
|
||||
@@ -405,6 +426,39 @@
|
||||
<ClInclude Include="source\menu\init.h">
|
||||
<Filter>menu</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="source\game\Engine\engine_misc.h">
|
||||
<Filter>game\Engine</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="source\game\GamePH\PlayerInfectionModule.h">
|
||||
<Filter>game\GamePH</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="source\utils\rtti.h">
|
||||
<Filter>utils</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="source\menu\weapon.h">
|
||||
<Filter>menu</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="source\game\GamePH\InventoryItem.h">
|
||||
<Filter>game\GamePH</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="source\game\GamePH\ItemDescWithContext.h">
|
||||
<Filter>game\GamePH</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="source\game\GamePH\InventoryContainerDI.h">
|
||||
<Filter>game\GamePH</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="source\game\GamePH\InventoryMoney.h">
|
||||
<Filter>game\GamePH</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="source\menu\teleport.h">
|
||||
<Filter>menu</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="source\memscan\memscan.h">
|
||||
<Filter>memscan</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="source\memscan\util\util.h">
|
||||
<Filter>memscan\util</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Filter Include="MinHook">
|
||||
@@ -449,5 +503,11 @@
|
||||
<Filter Include="ImGui\misc\freetype">
|
||||
<UniqueIdentifier>{122420d5-ac60-4778-80bf-1384697fcc44}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="memscan">
|
||||
<UniqueIdentifier>{1e82ab1f-550e-4fac-8fac-0888e1e62873}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="memscan\util">
|
||||
<UniqueIdentifier>{7e81ee9f-f74a-4af8-8a10-7530b26c3c86}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -37,6 +37,8 @@
|
||||
#include <assert.h>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <semaphore>
|
||||
#include <atomic>
|
||||
|
||||
#include <dxgi.h>
|
||||
#include <dxgi1_4.h>
|
||||
@@ -65,13 +67,16 @@
|
||||
#include <imstb_textedit.h>
|
||||
#include <imstb_truetype.h>
|
||||
#include <MinHook.h>
|
||||
#include <memscan.h>
|
||||
|
||||
#include "..\source\config\ini.h"
|
||||
#include "..\source\game\Engine\GameSpeedHandler.h"
|
||||
#include "..\source\game\Vector3.h"
|
||||
#include "..\source\game\buffer.h"
|
||||
#include "..\source\utils\files.h"
|
||||
#include "..\source\utils\hook.h"
|
||||
#include "..\source\utils\memory.h"
|
||||
#include "..\source\utils\rtti.h"
|
||||
#include "..\source\utils\sigscan.h"
|
||||
#include "..\source\utils\texture.h"
|
||||
#include "..\source\utils\time.h"
|
||||
|
||||
@@ -41,11 +41,29 @@ namespace ImGui {
|
||||
|
||||
const float oneTabWidthWithSpacing = width / tabs;
|
||||
const float oneTabWidth = oneTabWidthWithSpacing - (tabIndex == tabs ? 0.0f : GImGui->Style.ItemSpacing.x / 2.0f);
|
||||
ImGui::SetNextItemWidth(oneTabWidth);
|
||||
SetNextItemWidth(oneTabWidth);
|
||||
}
|
||||
void EndTabBarEx() {
|
||||
ImGui::EndTabBar();
|
||||
EndTabBar();
|
||||
tabIndex = 1;
|
||||
}
|
||||
bool Button(const char* label, const char* tooltip, const ImVec2& size) {
|
||||
bool btn = Button(label, size);
|
||||
if (tooltip)
|
||||
SetItemTooltip(tooltip);
|
||||
return btn;
|
||||
}
|
||||
bool ButtonHotkey(const char* label, KeyBindOption* v, const char* tooltip, const ImVec2& size) {
|
||||
bool btn = Button(label, size);
|
||||
if (tooltip)
|
||||
SetItemTooltip(tooltip);
|
||||
Hotkey(std::string(label + std::string("##ToggleKey")), v);
|
||||
return btn;
|
||||
}
|
||||
bool Checkbox(const char* label, bool* v, const char* tooltip) {
|
||||
bool checkbox = Checkbox(label, v);
|
||||
SetItemTooltip(tooltip);
|
||||
return checkbox;
|
||||
}
|
||||
bool Checkbox(const char* label, Option* v) {
|
||||
ImGuiWindow* window = GetCurrentWindow();
|
||||
@@ -97,18 +115,37 @@ namespace ImGui {
|
||||
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags | ImGuiItemStatusFlags_Checkable | (v->GetValue() ? ImGuiItemStatusFlags_Checked : 0));
|
||||
return pressed;
|
||||
}
|
||||
bool CheckboxHotkey(const char* label, KeyBindOption* v) {
|
||||
const bool checkbox = ImGui::Checkbox(label, v);
|
||||
ImGui::Hotkey(std::string(label + std::string("##ToggleKey")), v);
|
||||
bool Checkbox(const char* label, Option* v, const char* tooltip) {
|
||||
bool checkbox = Checkbox(label, v);
|
||||
SetItemTooltip(tooltip);
|
||||
return checkbox;
|
||||
}
|
||||
bool CheckboxHotkey(const char* label, KeyBindOption* v, const char* tooltip) {
|
||||
const bool checkbox = Checkbox(label, v);
|
||||
if (tooltip)
|
||||
SetItemTooltip(tooltip);
|
||||
Hotkey(std::string(label + std::string("##ToggleKey")), v);
|
||||
return checkbox;
|
||||
}
|
||||
bool SliderInt(const char* label, const char* tooltip, int* v, int v_min, int v_max, const char* format, ImGuiSliderFlags flags) {
|
||||
const bool sliderInt = SliderInt(label, v, v_min, v_max, format, flags);
|
||||
if (tooltip)
|
||||
SetItemTooltip(tooltip);
|
||||
return sliderInt;
|
||||
}
|
||||
bool SliderFloat(const char* label, const char* tooltip, float* v, float v_min, float v_max, const char* format, ImGuiSliderFlags flags) {
|
||||
const bool sliderFloat = SliderFloat(label, v, v_min, v_max, format, flags);
|
||||
if (tooltip)
|
||||
SetItemTooltip(tooltip);
|
||||
return sliderFloat;
|
||||
}
|
||||
static const float CalculateIndentation(const float window_width, const float text_width, const float min_indentation) {
|
||||
const float indentation = (window_width - text_width) * 0.5f;
|
||||
return (indentation > min_indentation ? indentation : min_indentation);
|
||||
}
|
||||
void TextCentered(const char* text, const bool calculateWithScrollbar) {
|
||||
const float min_indentation = 20.0f;
|
||||
const float window_width = ImGui::GetWindowSize().x - (calculateWithScrollbar ? GImGui->Style.ScrollbarSize : 0.0f) - (GImGui->Style.WindowPadding.x);
|
||||
const float window_width = GetWindowSize().x - (calculateWithScrollbar ? GImGui->Style.ScrollbarSize : 0.0f) - (GImGui->Style.WindowPadding.x);
|
||||
const float wrap_pos = window_width - min_indentation;
|
||||
|
||||
std::istringstream iss(text);
|
||||
@@ -117,26 +154,26 @@ namespace ImGui {
|
||||
std::string line{};
|
||||
for (const auto& word : words) {
|
||||
std::string new_line = line.empty() ? word : line + " " + word;
|
||||
if (ImGui::CalcTextSize(new_line.c_str()).x <= wrap_pos) {
|
||||
if (CalcTextSize(new_line.c_str()).x <= wrap_pos) {
|
||||
line = new_line;
|
||||
continue;
|
||||
}
|
||||
|
||||
ImGui::SameLine(CalculateIndentation(window_width, ImGui::CalcTextSize(line.c_str()).x, min_indentation));
|
||||
ImGui::TextUnformatted(line.c_str());
|
||||
ImGui::NewLine();
|
||||
SameLine(CalculateIndentation(window_width, CalcTextSize(line.c_str()).x, min_indentation));
|
||||
TextUnformatted(line.c_str());
|
||||
NewLine();
|
||||
line = word;
|
||||
}
|
||||
|
||||
if (!line.empty()) {
|
||||
ImGui::SameLine(CalculateIndentation(window_width, ImGui::CalcTextSize(line.c_str()).x, min_indentation));
|
||||
ImGui::TextUnformatted(line.c_str());
|
||||
ImGui::NewLine();
|
||||
SameLine(CalculateIndentation(window_width, CalcTextSize(line.c_str()).x, min_indentation));
|
||||
TextUnformatted(line.c_str());
|
||||
NewLine();
|
||||
}
|
||||
}
|
||||
void TextCenteredColored(const char* text, const ImU32 col, const bool calculateWithScrollbar) {
|
||||
const float min_indentation = 20.0f;
|
||||
const float window_width = ImGui::GetWindowSize().x - (calculateWithScrollbar ? GImGui->Style.ScrollbarSize : 0.0f) - (GImGui->Style.WindowPadding.x);
|
||||
const float window_width = GetWindowSize().x - (calculateWithScrollbar ? GImGui->Style.ScrollbarSize : 0.0f) - (GImGui->Style.WindowPadding.x);
|
||||
const float wrap_pos = window_width - min_indentation;
|
||||
|
||||
std::istringstream iss(text);
|
||||
@@ -145,62 +182,62 @@ namespace ImGui {
|
||||
std::string line{};
|
||||
for (const auto& word : words) {
|
||||
std::string new_line = line.empty() ? word : line + " " + word;
|
||||
if (ImGui::CalcTextSize(new_line.c_str()).x <= wrap_pos) {
|
||||
if (CalcTextSize(new_line.c_str()).x <= wrap_pos) {
|
||||
line = new_line;
|
||||
continue;
|
||||
}
|
||||
|
||||
ImGui::SameLine(CalculateIndentation(window_width, ImGui::CalcTextSize(line.c_str()).x, min_indentation));
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, col);
|
||||
ImGui::TextUnformatted(line.c_str());
|
||||
ImGui::PopStyleColor();
|
||||
ImGui::NewLine();
|
||||
SameLine(CalculateIndentation(window_width, CalcTextSize(line.c_str()).x, min_indentation));
|
||||
PushStyleColor(ImGuiCol_Text, col);
|
||||
TextUnformatted(line.c_str());
|
||||
PopStyleColor();
|
||||
NewLine();
|
||||
line = word;
|
||||
}
|
||||
|
||||
if (!line.empty()) {
|
||||
ImGui::SameLine(CalculateIndentation(window_width, ImGui::CalcTextSize(line.c_str()).x, min_indentation));
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, col);
|
||||
ImGui::TextUnformatted(line.c_str());
|
||||
ImGui::PopStyleColor();
|
||||
ImGui::NewLine();
|
||||
SameLine(CalculateIndentation(window_width, CalcTextSize(line.c_str()).x, min_indentation));
|
||||
PushStyleColor(ImGuiCol_Text, col);
|
||||
TextUnformatted(line.c_str());
|
||||
PopStyleColor();
|
||||
NewLine();
|
||||
}
|
||||
}
|
||||
bool ButtonCentered(const char* label, const ImVec2 size) {
|
||||
ImGuiStyle& style = ImGui::GetStyle();
|
||||
const float window_width = ImGui::GetContentRegionAvail().x;
|
||||
const float button_width = ImGui::CalcTextSize(label).x + style.FramePadding.x * 2.0f;
|
||||
ImGuiStyle& style = GetStyle();
|
||||
const float window_width = GetContentRegionAvail().x;
|
||||
const float button_width = CalcTextSize(label).x + style.FramePadding.x * 2.0f;
|
||||
float button_indentation = (window_width - button_width) * 0.5f;
|
||||
|
||||
const float min_indentation = 20.0f;
|
||||
if (button_indentation <= min_indentation)
|
||||
button_indentation = min_indentation;
|
||||
|
||||
ImGui::SameLine(button_indentation);
|
||||
return ImGui::Button(label, size);
|
||||
ImGui::NewLine();
|
||||
SameLine(button_indentation);
|
||||
return Button(label, size);
|
||||
NewLine();
|
||||
}
|
||||
void SeparatorTextColored(const char* label, const ImU32 col) {
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, col);
|
||||
ImGui::SeparatorText(label);
|
||||
ImGui::PopStyleColor();
|
||||
PushStyleColor(ImGuiCol_Text, col);
|
||||
SeparatorText(label);
|
||||
PopStyleColor();
|
||||
}
|
||||
void Spacing(const ImVec2 size, const bool customPosOffset) {
|
||||
ImGuiWindow* window = ImGui::GetCurrentWindow();
|
||||
ImGuiWindow* window = GetCurrentWindow();
|
||||
if (window->SkipItems)
|
||||
return;
|
||||
|
||||
if (!customPosOffset) {
|
||||
ImGui::ItemSize(size);
|
||||
ItemSize(size);
|
||||
return;
|
||||
}
|
||||
|
||||
const ImVec2 currentCursorPos = ImGui::GetCursorPos();
|
||||
const ImVec2 currentCursorPos = GetCursorPos();
|
||||
if (size.y == 0.0f)
|
||||
ImGui::SetCursorPosX(currentCursorPos.x + size.x);
|
||||
SetCursorPosX(currentCursorPos.x + size.x);
|
||||
else if (size.x == 0.0f)
|
||||
ImGui::SetCursorPosY(currentCursorPos.y + size.y);
|
||||
SetCursorPosY(currentCursorPos.y + size.y);
|
||||
else
|
||||
ImGui::SetCursorPos(currentCursorPos + size);
|
||||
SetCursorPos(currentCursorPos + size);
|
||||
}
|
||||
}
|
||||
@@ -5,8 +5,14 @@ namespace ImGui {
|
||||
extern void StyleScaleAllSizes(ImGuiStyle* style, const float scale_factor, ImGuiStyle* defStyle = nullptr);
|
||||
extern void SpanNextTabAcrossWidth(const float width, const size_t tabs = 1);
|
||||
extern void EndTabBarEx();
|
||||
extern bool Button(const char* label, const char* tooltip, const ImVec2& size = ImVec2(0, 0));
|
||||
extern bool ButtonHotkey(const char* label, KeyBindOption* v, const char* tooltip = nullptr, const ImVec2& size = ImVec2(0, 0));
|
||||
extern bool Checkbox(const char* label, bool* v, const char* tooltip);
|
||||
extern bool Checkbox(const char* label, Option* v);
|
||||
extern bool CheckboxHotkey(const char* label, KeyBindOption* v);
|
||||
extern bool Checkbox(const char* label, Option* v, const char* tooltip);
|
||||
extern bool CheckboxHotkey(const char* label, KeyBindOption* v, const char* tooltip = nullptr);
|
||||
extern bool SliderInt(const char* label, const char* tooltip, int* v, int v_min, int v_max, const char* format = "%d", ImGuiSliderFlags flags = 0);
|
||||
extern bool SliderFloat(const char* label, const char* tooltip, float* v, float v_min, float v_max, const char* format = "%.3f", ImGuiSliderFlags flags = 0);
|
||||
extern void TextCentered(const char* text, const bool calculateWithScrollbar = true);
|
||||
extern void TextCenteredColored(const char* text, const ImU32 col, const bool calculateWithScrollbar = true);
|
||||
extern bool ButtonCentered(const char* label, const ImVec2 size = ImVec2(0.0f, 0.0f));
|
||||
|
||||
@@ -175,6 +175,9 @@ namespace impl {
|
||||
}
|
||||
|
||||
static void CleanupRenderTarget() {
|
||||
if (!frameContext)
|
||||
return;
|
||||
|
||||
for (UINT i = 0; i < buffersCounts; ++i) {
|
||||
if (frameContext[i].main_render_target_resource) {
|
||||
frameContext[i].main_render_target_resource->Release();
|
||||
|
||||
@@ -49,6 +49,107 @@ Thank you everyone for the support <3)" },
|
||||
R"(- Added compatibility with v1.16.0 "Nightmare Mode" update
|
||||
- Fixed really fast player speed when executing a slow motion kill, dodging or ground pounding at 1.00x game speed (will still happen at any other game speed unfortunately)
|
||||
- Added function hooking timeout for easier debugging
|
||||
- Fetch game version using Windows' API instead of using the game's function)" }
|
||||
- Fetch game version using Windows' API instead of using the game's function)" },
|
||||
{ "v1.2.0",
|
||||
R"(Before you read the changelog of this mod, I want to make a few statements, regarding the future of Dying Light 2 and modding, as well as to raise attention to other modders.
|
||||
Recently, some of you, or many of you might have noticed that one of the most popular and known mods for Dying Light 2, or the second most popular on NexusMods, IALR, aka "I Am Legion Reborn", has been very unfortunately discontinued.
|
||||
I'm not going to dive into it too much as it has been explained very well by the author himself, DocOnHoliday, and I recommend you check out his latest video from YouTube (@DocOnHoliday) and also the description and the articles pages of the NexusMods page, where everything is explained in detail.
|
||||
|
||||
The short version of the situation is that a while ago, almost a year ago in fact, Techland reached out to Doc in order to try and support his mod officially, seeing how well it did independently.
|
||||
After the entire ordeal with Tencent's acquisition of the majority of Techland, Techland stopped reaching out to Doc for unknown reasons. Some time passed, and some EULA changes were made, effectively granting Techland the ability of practically owning your mods and being able to do anything with them.
|
||||
I quote the EULA: "Techland will in particular have the right to copy, reproduce, fix, modify, adapt, translate, prepare derivative works, publish, distribute, license, sublicense, transfer, publicly display, publicly perform, provide access to, and broadcast Mods as well as all modified and derivative works thereof."
|
||||
Assuming this change was made due to Tencent's entry into the field, everyone was mad, and rightfully so. Doc still hasn't received any sort of communication from Techland ever since, and recently, after so long, someone from Techland reached out to him.
|
||||
It was unfortunate news for Doc. He was asked to take down his Patreon (effectively a verbal cease & desist, which technically is not a cease & desist but I'll get more into it later) because of a report made by someone in the community, stating that a paywall to his mod was made on Patreon, implying that Doc was paywalling IALR.
|
||||
That statement is completely false, as what Doc was doing at the time was simply offering Patreon supporters a special "thank you" gift, and I quote Doc: "It in no way contained anything that was meant to be paywall restricted, rather was access to a few tools I used for playtesting the mods content, and immediate access to all of the new armors, weapons, and other content for playtesting themselves."
|
||||
Clearly, Doc was not paywalling his mod, IALR, and he was only offering access to special tools that the user would not need for the mod to work or to provide the full experience of the mod.
|
||||
But, obviously, Techland being a business (not just a game dev studio, remember that the gaming industry has become a business industry nowadays), and especially after the whole Tencent ordeal, they've still decided to ask Doc to take down his Patreon for really hard to understand reasons, regardless of whether he was actually truly paywalling his mod or not (which I state again, he was not).
|
||||
Doc made a very informed and hard decision to stop further development for his mod completely, even if Techland was only threatening his Patreon.
|
||||
It was very obvious that Techland might try to pull other shenanigans in the future, regardless of him taking down his Patreon, which keep in mind was (still is, but not for IALR anymore) his main source of donations. Yes, donations, nobody was paying him to get access to a mod... They were paying him to support him and his work.
|
||||
|
||||
The reason I'm writing this is because it is important for anyone else working on mods for this game, or even for games made by Techland, that you need to be aware of possible consequences of modding.
|
||||
A company can make the most unexpected change or decision that you would never think of, as seen with Doc's example. My mod breaks a few EULA agreements, and I'm afraid for the future of this mod knowing that it's only going to grow, because Techland can have the mod removed in the blink of an eye if they add PvP into Dying Light 2 and decide that my mod is problematic, especially with the mod being open-source and even if I did implement an anti-cheat system, anyone could download the source code, modify it and redistribute it because of open-source licensing. Unfortunate world we live in...
|
||||
So either I would have to take down my mod from all sources, or Techland would implement an anti-cheat system which also prevents my mod from properly working in multiplayer. Even if I didn't try to circumvent the anti-cheat system, others would because the mod is open-source.
|
||||
Besides, the entire Patreon problem is ridiculous. I understand that Techland would want to set better modding precedents regarding distribution and development of mods, such as stopping developers from paywalling their mods (for months or even years!).
|
||||
But Doc in this scenario had nothing to do with that, which is what worries me about what other future decisions Techland can and might take towards other mods, especially after seeing their behavior with Doc, who only wanted the game's community good by making his mod more official, polished and easier to maintain.
|
||||
He only had great goals for the game in mind, and so did Techland as you've seen in the previous few paragraphs, until Tencent came into play. I feel like he was completely disregarded for so long, and to make the final blow, they did that with his Patreon.
|
||||
|
||||
So, if you have a long-term modding project in your mind for Dying Light 2, please take a step back and think about it before fully committing your life to it. It's not official (unless Techland reaches out to you and wants to make it official and doesn't ghost you lol), you don't own anything and you agreed to Techland's EULA when you purchased the game.
|
||||
The people working at Techland may be nice, but remember, it's a business, and business decisions will be made, whether they're good for the community of this game or not. Usually (not always), when companies make money, they don't care, period.
|
||||
|
||||
If anyone at Techland is reading this, you have a great dev team and you've made a thriving game series that everyone enjoys, and that I still enjoy to this day. We all have our ups and downs, but these decisions make me feel opposite to what I feel for the Dying Light series, about the state of the company.
|
||||
The game leans too much into monetization... You've done so many harsh changes ever since Tencent came, many micro-transactions, EULA changes specific to modding, and seeing this whole Patreon ordeal, and the lack of communication with the modding community, makes me think you don't always completely wish this community the best.
|
||||
Whether this is Tencent's intention or not, you are the ones who agreed to the deal.
|
||||
|
||||
|
||||
|
||||
With all of that said, here is finally what this update brings:
|
||||
|
||||
- Added compatibility with v1.16.2 hotfix update
|
||||
- Added the ability of using .PAK mods inside "EGameTools\UserModFiles"; just drag and drop a .PAK inside the folder, rename it to whatever you like and enjoy! CREDITS TO @12brendon34 on Discord for finding out how to implement this feature!
|
||||
- Added "Player Immunity" slider (Player)
|
||||
- Added "Old World Money" slider (Player)
|
||||
- Added "Unlimited Immunity" (Player)
|
||||
- Added "Unlimited Stamina" (Player)
|
||||
- Added "Unlimited Items" (Player) - stops the game from lowering the amount of items such as consumables / throwables when using them, alongside other inventory items such as ammo, lockpicks and other items
|
||||
- WARNING: this will not stop the item from getting removed from your inventory if you drop the entire amount; currently, if the amount of item is 1, it will still drop from your inventory unfortunately
|
||||
- Added "One-Hit Kill" (Player)
|
||||
- Added "Invisible to Enemies" (Player)
|
||||
- Added "Allow Grapple Hook in Safezone" (Player)
|
||||
- Added "Disable Air Control" (Player)
|
||||
- Added "Current Weapon Durability" slider (Weapon) - currently only works while your weapon is physically equipped in your hand
|
||||
- Added "Unlimited Durability" (Weapon)
|
||||
- Added "Unlimited Ammo" (Weapon)
|
||||
- Added "No Spread" (Weapon)
|
||||
- Added "No Recoil" (Weapon)
|
||||
- Added "Instant Reload" (Weapon)
|
||||
- Added "Lens Distortion" slider (Camera)
|
||||
- Added "GoPro Mode" (Camera) - this is best used with Head Bob Reduction set to 0 and Player FOV Correction set to 0 in game options; thank you to @c.r.e.x on Discord for the idea of adding this feature!
|
||||
- Added "Disable Head Correction" (Camera) - disables centering of the player's hands to the center of the camera
|
||||
- Added "Teleport to Coords" with X, Y, Z inputs (Teleport), with a "Get Player Coords" button which will automatically fill the X, Y and Z inputs
|
||||
- Added "Teleport to Waypoint" (Teleport)
|
||||
- WARNING: if the waypoint is selected to track an object/item on the map, Teleport to Waypoint will not work, if so just set the waypoint nearby instead
|
||||
- WARNING: your player height won't change when teleporting, so make sure you catch yourself if you fall under the map because of the teleportation
|
||||
- Added "Saved Locations" in Teleport menu, with the ability of saving, deleting and teleporting to said locations; these locations are saved in the config file and will contain a name and a set of coordinates for each location; to reset back to the default list, remove the list from inside the config file and go back into the game; thank you to @Synsteric on Discord for helping me make the default list!
|
||||
- Added "Increase Data PAKs Limit" (Misc; requires game restart to apply) - you can now add more than 8 data PAKs, e.g. data8.pak, data9.pak, data10.pak, etc, up to 200 PAKs in total
|
||||
- Added "Disable Data PAKs CRC Check" (Misc; requires game restart to apply) - stops the game from scanning data PAKs, which allows you to use data PAK mods in multiplayer as well
|
||||
- Added "Disable Savegame CRC Check" (Misc; requires game restart to apply) - stops the game from falsely saying your savegame is corrupt whenever you modify it
|
||||
- Added tooltips when hovering over buttons and sliders inside the mod menu
|
||||
|
||||
- Fixed "God Mode" (Player) staying enabled after toggling FreeCam off
|
||||
- Fixed "God Mode" (Player) not working properly or at all in multiplayer
|
||||
- Fixed blood overlay still displaying after falling from a great height with "God Mode" (Player) enabled
|
||||
- Fixed volatiles still being able to kill you when they jump on top of you while "God Mode" (Player) is enabled
|
||||
- Fixed "Disable Out of Bounds Timer" (Player) not working in missions
|
||||
- Fixed player variables saving and loading using old version of player_variables.scr (which made Max Health drop to negative infinite)
|
||||
- Fixed options that make use of player variables not returning back to their original value after disabling them
|
||||
- Fixed immunity drastically being lowered while rapidly changing the time forward with the "Time" slider (World) at night or while in a dark zone
|
||||
- Fixed long paths to mods inside UserModFiles causing a game crash or causing the mods to not load at all
|
||||
- Changed the config system to only write to the config file whenever there's a change in the mod menu
|
||||
- Changed the way the mod menu gets the list of player variables, meaning the player variables list should self-update, with no manual intervention required even after a game update
|
||||
|
||||
NOTE: Any mods that are put inside "EGameTools\UserModFiles" as a regular file (.scr or any other file that is usually present in .PAK mods) and NOT a .PAK file will make the game ignore the same files that are present in any of the .PAK mods inside "EGameTools\UserModFiles". I recommend using .PAK for most mods. If you run into issues, try extracting the files inside the PAK into the folder directly.
|
||||
|
||||
|
||||
|
||||
I'm soon starting my exams and won't really have the time to update the mod the way I did right now. I had a 2 week leave and so I had plenty of time to further develop this mod.
|
||||
If anyone is looking to help with development, I'm all eyes and ears! Thank you!)" },
|
||||
{ "v1.2.1",
|
||||
R"(- Added compatibility with v1.17.2 Tower Raid update
|
||||
- Added a .PDB file included by default with the mod, for debugging purposes in case the game crashes, now I can more easily detect the cause of a game crash!
|
||||
- Added a crash handler which handles game crashes and generates a "EGameTools-dump.dmp" file in the game's exe directory for debugging purposes; if you encounter a crash and this file gets generated, please send it to me anywhere you can, for example on Discord, so I can try to find out the cause of the game crash!
|
||||
|
||||
- Fixed "Game Speed" (World) not getting applied with the mod menu opened while having another tab selected other than the World tab
|
||||
|
||||
I have some things planned for the next updates, but time will decide when I'll be able to work on the updates. I'm almost done with my exams!)" },
|
||||
{ "v1.2.2",
|
||||
R"(- Added compatibility with v1.18.0 "Community QoL" update
|
||||
- Fixed an issue with classes not always getting detected correctly for everyone (Debug tab; if you still run into issues, please open a bug report!))" },
|
||||
{ "v1.2.3",
|
||||
R"(- Fixed co-op issues related to Player and Weapon options, such as God Mode, Player Health, Player Immunity, Weapon Durability sliders not working (if you still run into issues, please open a bug report!))" },
|
||||
{ "v1.2.4",
|
||||
R"(- Added compatibility with v1.19 Tower Raid: Halloween Run update
|
||||
- Improved CPU performance at game startup when using the mod, this should stop the system from freezing for some people when starting up the game
|
||||
- Improved memory signature scanning, increasing reliability and performance; if you encounter issues with classses in the Debug menu being NULL, please open up a bug report!
|
||||
- Improved MountDataPaks hook error detection (the error related to MountDataPaks should not show up in the console as often anymore))" }
|
||||
};
|
||||
}
|
||||
+6907
-4161
File diff suppressed because it is too large
Load Diff
@@ -5,5 +5,4 @@ namespace Config {
|
||||
extern void SaveConfig();
|
||||
extern void InitConfig();
|
||||
extern void ConfigLoop();
|
||||
extern void ConfigSaveLoop();
|
||||
}
|
||||
+82
-42
@@ -1,10 +1,14 @@
|
||||
#include <pch.h>
|
||||
#include "config\config.h"
|
||||
#include "core.h"
|
||||
#include "game\Engine\engine_hooks.h"
|
||||
#include "game\GamePH\LevelDI.h"
|
||||
#include "game\GamePH\Other.h"
|
||||
#include "game\GamePH\PlayerHealthModule.h"
|
||||
#include "game\GamePH\PlayerInfectionModule.h"
|
||||
#include "game\GamePH\PlayerVariables.h"
|
||||
#include "game\GamePH\gameph_misc.h"
|
||||
#include "menu\menu.h"
|
||||
#include "menu\misc.h"
|
||||
|
||||
#pragma region KeyBindOption
|
||||
bool KeyBindOption::wasAnyKeyPressed = false;
|
||||
@@ -36,12 +40,15 @@ namespace Core {
|
||||
#pragma endregion
|
||||
|
||||
// Core
|
||||
bool exiting = false;
|
||||
static bool createdConfigThread = false;
|
||||
std::atomic<bool> exiting = false;
|
||||
static std::vector<std::thread> threads{};
|
||||
static HANDLE keepAliveEvent{};
|
||||
|
||||
int rendererAPI = 0;
|
||||
DWORD gameVer = 0;
|
||||
|
||||
std::counting_semaphore<4> maxHookThreads(4);
|
||||
|
||||
static void LoopHookRenderer() {
|
||||
while (true) {
|
||||
if (exiting)
|
||||
@@ -162,20 +169,22 @@ namespace Core {
|
||||
}
|
||||
|
||||
void OnPostUpdate() {
|
||||
if (!createdConfigThread) {
|
||||
std::thread(Config::ConfigLoop).detach();
|
||||
std::thread(Config::ConfigSaveLoop).detach();
|
||||
|
||||
createdConfigThread = true;
|
||||
}
|
||||
|
||||
if (!GamePH::PlayerVariables::gotPlayerVars)
|
||||
GamePH::PlayerVariables::GetPlayerVars();
|
||||
GamePH::PlayerVariables::GetPlayerVars();
|
||||
|
||||
for (auto& menuTab : *Menu::MenuTab::GetInstances())
|
||||
menuTab.second->Update();
|
||||
|
||||
GamePH::PlayerHealthModule::UpdateClassAddr();
|
||||
GamePH::PlayerInfectionModule::UpdateClassAddr();
|
||||
|
||||
static bool mountDataPaksErrorShown = false;
|
||||
if (!mountDataPaksErrorShown && Engine::Hooks::mountDataPaksRanWith8Count < 3 && Menu::Misc::increaseDataPAKsLimit.GetValue() && GamePH::PlayerVariables::Get()) {
|
||||
spdlog::error("MountDataPaks hook ran less than 3 times with the data PAKs limit set to 8. This means the increased data PAKs limit might not work correctly! If this error message appears and your data PAKs past \"data7.pak\" have not loaded, please contact author.");
|
||||
mountDataPaksErrorShown = true;
|
||||
}
|
||||
}
|
||||
/*static bool WriteMiniDump(PEXCEPTION_POINTERS pExceptionPointers) {
|
||||
#ifndef EXCP_HANDLER_DISABLE_DEBUG
|
||||
static bool WriteMiniDump(PEXCEPTION_POINTERS pExceptionPointers) {
|
||||
HANDLE hFile = CreateFileA("EGameTools-dump.dmp", GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
|
||||
if (hFile == INVALID_HANDLE_VALUE)
|
||||
return false;
|
||||
@@ -185,21 +194,27 @@ namespace Core {
|
||||
mdei.ExceptionPointers = pExceptionPointers;
|
||||
mdei.ClientPointers = false;
|
||||
|
||||
int success = MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hFile, MiniDumpNormal, &mdei, nullptr, nullptr);
|
||||
int success = MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hFile, MiniDumpNormal, (pExceptionPointers ? &mdei : nullptr), nullptr, nullptr);
|
||||
CloseHandle(hFile);
|
||||
|
||||
return success;
|
||||
}
|
||||
static long WINAPI VectoredExceptionHandler(PEXCEPTION_POINTERS ExceptionInfo) {
|
||||
spdlog::error("VEH threw an exception with code {}. Trying to continue execution, writing mini-dump in the mean time.", ExceptionInfo->ExceptionRecord->ExceptionCode);
|
||||
static long WINAPI CrashHandler(PEXCEPTION_POINTERS ExceptionInfo) {
|
||||
spdlog::error("Crash Handler threw an exception with code {}. Game is exiting, writing mini-dump in the mean time.", ExceptionInfo->ExceptionRecord->ExceptionCode);
|
||||
std::string errorMsg = "";
|
||||
|
||||
if (WriteMiniDump(ExceptionInfo))
|
||||
if (WriteMiniDump(ExceptionInfo)) {
|
||||
spdlog::info("Mini-dump written to \"EGameTools-dump.dmp\". Please send this to mod author for further help!");
|
||||
else
|
||||
errorMsg = "EGameTools encountered a fatal error that caused the game to crash.\n\nA file \"" + Utils::Files::GetCurrentProcDirectory() + "\\EGameTools-dump.dmp\" has been generated. Please send this file to the author of the mod!\n\nThe game will now close once you press OK.";
|
||||
} else {
|
||||
spdlog::error("Failed to write mini-dump.");
|
||||
errorMsg = "EGameTools encountered a fatal error that caused the game to crash.\n\nEGameTools failed to generate a crash dump file unfortunately, which means it is harder to find the cause of the crash.\n\nThe game will now close once you press OK.";
|
||||
}
|
||||
|
||||
return EXCEPTION_CONTINUE_EXECUTION;
|
||||
}*/
|
||||
MessageBoxA(nullptr, errorMsg.c_str(), "Fatal game error", MB_ICONERROR | MB_OK | MB_SETFOREGROUND);
|
||||
exit(0);
|
||||
}
|
||||
#endif
|
||||
static void GameVersionCheck() {
|
||||
try {
|
||||
gameVer = GamePH::GetCurrentGameVersion();
|
||||
@@ -218,38 +233,61 @@ namespace Core {
|
||||
EnableConsole();
|
||||
InitLogger();
|
||||
|
||||
//AddVectoredExceptionHandler(0, &VectoredExceptionHandler);
|
||||
|
||||
spdlog::warn("Initializing config");
|
||||
Config::InitConfig();
|
||||
CreateSymlinkForLoadingFiles();
|
||||
spdlog::warn("Sorting Player Variables");
|
||||
GamePH::PlayerVariables::SortPlayerVars();
|
||||
spdlog::info("Player Variables sorted");
|
||||
|
||||
spdlog::warn("Initializing MinHook");
|
||||
MH_Initialize();
|
||||
spdlog::info("Initialized MinHook");
|
||||
#ifndef EXCP_HANDLER_DISABLE_DEBUG
|
||||
SetUnhandledExceptionFilter(CrashHandler);
|
||||
#endif
|
||||
|
||||
spdlog::warn("Getting game version");
|
||||
GameVersionCheck();
|
||||
|
||||
spdlog::warn("Initializing config");
|
||||
Config::InitConfig();
|
||||
threads.emplace_back(Config::ConfigLoop);
|
||||
|
||||
CreateSymlinkForLoadingFiles();
|
||||
|
||||
for (auto& hook : *Utils::Hook::HookBase::GetInstances()) {
|
||||
threads.emplace_back([&hook]() {
|
||||
maxHookThreads.acquire();
|
||||
|
||||
if (hook->isHooking) {
|
||||
spdlog::warn("Hooking \"{}\"", hook->name.data());
|
||||
while (hook->isHooking)
|
||||
Sleep(10);
|
||||
|
||||
if (hook->isHooked)
|
||||
spdlog::info("Hooked \"{}\"!", hook->name.data());
|
||||
} else if (hook->isHooked)
|
||||
spdlog::info("Hooked \"{}\"!", hook->name.data());
|
||||
else {
|
||||
spdlog::warn("Hooking \"{}\"", hook->name.data());
|
||||
if (hook->HookLoop())
|
||||
spdlog::info("Hooked \"{}\"!", hook->name.data());
|
||||
}
|
||||
|
||||
maxHookThreads.release();
|
||||
}).detach();
|
||||
}
|
||||
|
||||
spdlog::warn("Sorting Player Variables");
|
||||
threads.emplace_back([]() {
|
||||
GamePH::PlayerVariables::SortPlayerVars();
|
||||
spdlog::info("Player Variables sorted");
|
||||
}).detach();
|
||||
|
||||
spdlog::warn("Hooking DX11/DX12 renderer");
|
||||
std::thread([]() {
|
||||
threads.emplace_back([]() {
|
||||
LoopHookRenderer();
|
||||
spdlog::info("Hooked \"DX11/DX12 renderer\"!");
|
||||
}).detach();
|
||||
|
||||
for (auto& hook : *Utils::Hook::HookBase::GetInstances()) {
|
||||
spdlog::warn("Hooking \"{}\"", hook->name.data());
|
||||
std::thread([&hook]() {
|
||||
hook->HookLoop();
|
||||
spdlog::info("Hooked \"{}\"!", hook->name.data());
|
||||
}).detach();
|
||||
}
|
||||
keepAliveEvent = CreateEventA(nullptr, TRUE, FALSE, nullptr);
|
||||
WaitForSingleObject(keepAliveEvent, INFINITE);
|
||||
|
||||
const HANDLE proc = GetCurrentProcess();
|
||||
WaitForSingleObject(proc, INFINITE);
|
||||
for (auto& thread : threads) {
|
||||
if (thread.joinable())
|
||||
thread.join();
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@@ -266,5 +304,7 @@ namespace Core {
|
||||
MH_DisableHook(MH_ALL_HOOKS);
|
||||
MH_Uninitialize();
|
||||
spdlog::info("Unhooked everything");
|
||||
|
||||
SetEvent(keepAliveEvent);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,12 +3,14 @@
|
||||
#include <imgui.h>
|
||||
#include <ranges>
|
||||
#include <set>
|
||||
#include <atomic>
|
||||
#include "..\utils\values.h"
|
||||
|
||||
#ifndef VK_NONE
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define LLMH_IMPL_DISABLE_DEBUG // this is for disabling low-level mouse hook in case ure trying to debug and u dont want ur pc to die lol
|
||||
#define EXCP_HANDLER_DISABLE_DEBUG // this is for disabling exception handling in case ure trying to debug and u dont want ur debugger to keep crying about errors lol
|
||||
#endif
|
||||
|
||||
#define VK_NONE -1
|
||||
@@ -16,9 +18,9 @@
|
||||
#define VK_MWHEELUP 0x101
|
||||
#endif
|
||||
|
||||
constexpr const char* MOD_VERSION_STR = "v1.1.3";
|
||||
constexpr DWORD MOD_VERSION = 10103;
|
||||
constexpr DWORD GAME_VER_COMPAT = 11600;
|
||||
constexpr const char* MOD_VERSION_STR = "v1.2.4";
|
||||
constexpr DWORD MOD_VERSION = 10204;
|
||||
constexpr DWORD GAME_VER_COMPAT = 11900;
|
||||
|
||||
struct Key {
|
||||
constexpr Key(std::string_view name, int code, ImGuiKey imGuiCode) : name(name), code(code), imGuiCode(imGuiCode) {}
|
||||
@@ -224,7 +226,7 @@ private:
|
||||
};
|
||||
|
||||
namespace Core {
|
||||
extern bool exiting;
|
||||
extern std::atomic<bool> exiting;
|
||||
|
||||
extern int rendererAPI;
|
||||
extern DWORD gameVer;
|
||||
|
||||
@@ -3,15 +3,33 @@
|
||||
namespace Core {
|
||||
extern void DisableConsole();
|
||||
|
||||
extern std::counting_semaphore<4> maxHookThreads;
|
||||
|
||||
extern DWORD64 WINAPI MainThread(HMODULE hModule);
|
||||
extern void Cleanup();
|
||||
}
|
||||
|
||||
namespace Engine {
|
||||
namespace Hooks {
|
||||
extern Utils::Hook::MHook<LPVOID, DWORD64(*)(DWORD64, UINT, UINT, DWORD64*, DWORD64(*)(DWORD64, DWORD, DWORD64, char*, int), INT16, DWORD64, UINT)> MountDataPaksHook;
|
||||
extern Utils::Hook::MHook<LPVOID, LPVOID(*)(LPVOID)> AuthenticateDataAddNewFileHook;
|
||||
extern Utils::Hook::MHook<LPVOID, bool(*)(LPVOID)> FsCheckZipCrcHook;
|
||||
extern Utils::Hook::MHook<LPVOID, DWORD64(*)(DWORD64, DWORD, DWORD)> FsOpenHook;
|
||||
}
|
||||
}
|
||||
|
||||
static HANDLE hMainThread{};
|
||||
|
||||
BOOL APIENTRY DllMain(HMODULE hModule, DWORD64 ul_reason_for_call, LPVOID lpReserved) {
|
||||
switch (ul_reason_for_call) {
|
||||
case DLL_PROCESS_ATTACH: {
|
||||
MH_Initialize();
|
||||
|
||||
Engine::Hooks::MountDataPaksHook.HookLoop();
|
||||
Engine::Hooks::AuthenticateDataAddNewFileHook.HookLoop();
|
||||
Engine::Hooks::FsCheckZipCrcHook.HookLoop();
|
||||
Engine::Hooks::FsOpenHook.HookLoop();
|
||||
|
||||
DisableThreadLibraryCalls(hModule);
|
||||
hMainThread = CreateThread(nullptr, 0, (LPTHREAD_START_ROUTINE)Core::MainThread, hModule, 0, nullptr);
|
||||
|
||||
|
||||
@@ -46,4 +46,27 @@ namespace Engine {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void CBaseCamera::SetPosition(const Vector3* pos) {
|
||||
__try {
|
||||
void* (*pSetPosition)(LPVOID pCBaseCamera, const Vector3* pos) = (decltype(pSetPosition))Utils::Memory::GetProcAddr("engine_x64_rwdi.dll", "?SetPosition@IBaseCamera@@QEAAXAEBVvec3@@@Z");
|
||||
if (!pSetPosition)
|
||||
return;
|
||||
|
||||
pSetPosition(this, pos);
|
||||
} __except (EXCEPTION_EXECUTE_HANDLER) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
void CBaseCamera::SetFOV(float fov) {
|
||||
__try {
|
||||
void* (*pSetFOV)(LPVOID pCBaseCamera, float fov) = (decltype(pSetFOV))Utils::Memory::GetProcAddr("engine_x64_rwdi.dll", "?SetFOV@IBaseCamera@@QEAAXM@Z");
|
||||
if (!pSetFOV)
|
||||
return;
|
||||
|
||||
pSetFOV(this, fov);
|
||||
} __except (EXCEPTION_EXECUTE_HANDLER) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,5 +15,8 @@ namespace Engine {
|
||||
Vector3* GetUpVector(Vector3* outUpVec);
|
||||
Vector3* GetLeftVector(Vector3* outLeftVec);
|
||||
Vector3* GetPosition(Vector3* outPos);
|
||||
|
||||
void SetPosition(const Vector3* pos);
|
||||
void SetFOV(float fov);
|
||||
};
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
#include <pch.h>
|
||||
#include "..\offsets.h"
|
||||
#include "CBulletPhysicsCharacter.h"
|
||||
#include "CoPhysicsProperty.h"
|
||||
|
||||
@@ -23,6 +24,8 @@ namespace Engine {
|
||||
CBulletPhysicsCharacter* ptr = pCoPhysicsProperty->pCBulletPhysicsCharacter;
|
||||
if (!Utils::Memory::IsValidPtrMod(ptr, "engine_x64_rwdi.dll"))
|
||||
return nullptr;
|
||||
if (*reinterpret_cast<DWORD64**>(ptr) != Offsets::GetVT_CBulletPhysicsCharacter())
|
||||
return nullptr;
|
||||
|
||||
return ptr;
|
||||
} __except (EXCEPTION_EXECUTE_HANDLER) {
|
||||
|
||||
@@ -6,9 +6,9 @@ namespace Engine {
|
||||
class CBulletPhysicsCharacter {
|
||||
public:
|
||||
union {
|
||||
buffer<0x8A0, Vector3> playerPos2;
|
||||
buffer<0x8B8, Vector3> playerPos;
|
||||
buffer<0xC38, float> playerDownwardVelocity;
|
||||
buffer<0xA08, Vector3> playerPos2;
|
||||
buffer<0xA20, Vector3> playerPos;
|
||||
buffer<0xDA0, float> playerDownwardVelocity;
|
||||
};
|
||||
|
||||
static Vector3 posBeforeFreeze;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include <pch.h>
|
||||
#include "..\offsets.h"
|
||||
#include "CGSObject.h"
|
||||
#include "CLevel.h"
|
||||
|
||||
@@ -12,6 +13,8 @@ namespace Engine {
|
||||
CGSObject* ptr = pCLevel->pCGSObject;
|
||||
if (!Utils::Memory::IsValidPtrMod(ptr, "engine_x64_rwdi.dll"))
|
||||
return nullptr;
|
||||
if (*reinterpret_cast<DWORD64**>(ptr) != Offsets::GetVT_CGSObject())
|
||||
return nullptr;
|
||||
|
||||
return ptr;
|
||||
} __except (EXCEPTION_EXECUTE_HANDLER) {
|
||||
|
||||
@@ -18,6 +18,8 @@ namespace Engine {
|
||||
CInput* ptr = *reinterpret_cast<CInput**>(Offsets::Get_g_CInput());
|
||||
if (!Utils::Memory::IsValidPtrMod(ptr, "engine_x64_rwdi.dll"))
|
||||
return nullptr;
|
||||
if (*reinterpret_cast<DWORD64**>(ptr) != Offsets::GetVT_CInput())
|
||||
return nullptr;
|
||||
|
||||
return ptr;
|
||||
} __except (EXCEPTION_EXECUTE_HANDLER) {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include <pch.h>
|
||||
#include "..\offsets.h"
|
||||
#include "CGame.h"
|
||||
#include "CLevel.h"
|
||||
|
||||
@@ -12,6 +13,8 @@ namespace Engine {
|
||||
CLevel* ptr = pCGame->pCLevel;
|
||||
if (!Utils::Memory::IsValidPtrMod(ptr, "engine_x64_rwdi.dll"))
|
||||
return nullptr;
|
||||
if (*reinterpret_cast<DWORD64**>(ptr) != Offsets::GetVT_CLevel())
|
||||
return nullptr;
|
||||
|
||||
return ptr;
|
||||
} __except (EXCEPTION_EXECUTE_HANDLER) {
|
||||
|
||||
@@ -11,6 +11,8 @@ namespace Engine {
|
||||
CLobbySteam* ptr = *reinterpret_cast<CLobbySteam**>(Offsets::Get_CLobbySteam());
|
||||
if (!Utils::Memory::IsValidPtrMod(ptr, "engine_x64_rwdi.dll"))
|
||||
return nullptr;
|
||||
if (*reinterpret_cast<DWORD64**>(ptr) != Offsets::GetVT_CLobbySteam())
|
||||
return nullptr;
|
||||
|
||||
return ptr;
|
||||
} __except (EXCEPTION_EXECUTE_HANDLER) {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include <pch.h>
|
||||
#include "..\offsets.h"
|
||||
#include "CGame.h"
|
||||
#include "CVideoSettings.h"
|
||||
|
||||
@@ -12,6 +13,8 @@ namespace Engine {
|
||||
CVideoSettings* ptr = pCGame->pCVideoSettings;
|
||||
if (!Utils::Memory::IsValidPtrMod(ptr, "engine_x64_rwdi.dll"))
|
||||
return nullptr;
|
||||
if (*reinterpret_cast<DWORD64**>(ptr) != Offsets::GetVT_CVideoSettings())
|
||||
return nullptr;
|
||||
|
||||
return ptr;
|
||||
} __except (EXCEPTION_EXECUTE_HANDLER) {
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
#include <pch.h>
|
||||
#include "..\GamePH\PlayerObjProperties.h"
|
||||
#include "..\GamePH\PlayerDI_PH.h"
|
||||
#include "CoPhysicsProperty.h"
|
||||
|
||||
namespace Engine {
|
||||
CoPhysicsProperty* CoPhysicsProperty::Get() {
|
||||
__try {
|
||||
GamePH::PlayerObjProperties* pPlayerObjProperties = GamePH::PlayerObjProperties::Get();
|
||||
if (!pPlayerObjProperties)
|
||||
GamePH::PlayerDI_PH* pPlayerDI_PH = GamePH::PlayerDI_PH::Get();
|
||||
if (!pPlayerDI_PH)
|
||||
return nullptr;
|
||||
|
||||
CoPhysicsProperty* ptr = pPlayerObjProperties->pCoPhysicsProperty;
|
||||
CoPhysicsProperty* ptr = pPlayerDI_PH->pCoPhysicsProperty;
|
||||
if (!Utils::Memory::IsValidPtrMod(ptr, "engine_x64_rwdi.dll"))
|
||||
return nullptr;
|
||||
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
// UNUSED CPP
|
||||
#include <pch.h>
|
||||
|
||||
namespace Engine {
|
||||
namespace GameSpeedHandler {
|
||||
float speed = 1.0;
|
||||
bool initialized = false;
|
||||
|
||||
/*#pragma region GetTickCount64Hook
|
||||
ULONGLONG GTC64_BaseTime = 0;
|
||||
ULONGLONG GTC64_OffsetTime = 0;
|
||||
|
||||
static LPVOID GetGetTickCount64() {
|
||||
return &GetTickCount64;
|
||||
}
|
||||
static ULONGLONG WINAPI detourGetTickCount64();
|
||||
static Utils::Hook::MHook<LPVOID, ULONGLONG(WINAPI*)()> GetTickCount64Hook{ "GetTickCount64", &GetGetTickCount64, &detourGetTickCount64 };
|
||||
|
||||
ULONGLONG WINAPI detourGetTickCount64() {
|
||||
return GTC64_OffsetTime + ((GetTickCount64Hook.pOriginal() - GTC64_BaseTime) * static_cast<double>(speed));
|
||||
}
|
||||
#pragma endregion
|
||||
|
||||
#pragma region QueryPerformanceCounterHook
|
||||
LARGE_INTEGER QPC_BaseTime = LARGE_INTEGER();
|
||||
LARGE_INTEGER QPC_OffsetTime = LARGE_INTEGER();
|
||||
|
||||
static LPVOID GetQueryPerformanceCounter() {
|
||||
return &QueryPerformanceCounter;
|
||||
}
|
||||
static BOOL WINAPI detourQueryPerformanceCounter(LARGE_INTEGER* lpPerformanceCount);
|
||||
static Utils::Hook::MHook<LPVOID, BOOL(WINAPI*)(LARGE_INTEGER*)> QueryPerformanceCounterHook{ "QueryPerformanceCounter", &GetQueryPerformanceCounter, &detourQueryPerformanceCounter };
|
||||
|
||||
BOOL WINAPI detourQueryPerformanceCounter(LARGE_INTEGER* lpPerformanceCount) {
|
||||
LARGE_INTEGER x;
|
||||
QueryPerformanceCounterHook.pOriginal(&x);
|
||||
lpPerformanceCount->QuadPart = QPC_OffsetTime.QuadPart + ((x.QuadPart - QPC_BaseTime.QuadPart) * static_cast<double>(speed));
|
||||
|
||||
return true;
|
||||
}
|
||||
#pragma endregion
|
||||
|
||||
void Setup() {
|
||||
if (!GetTickCount64Hook.pOriginal || !QueryPerformanceCounterHook.pOriginal || initialized)
|
||||
return;
|
||||
|
||||
GTC64_BaseTime = GetTickCount64Hook.pOriginal();
|
||||
GTC64_OffsetTime = GTC64_BaseTime;
|
||||
|
||||
QueryPerformanceCounterHook.pOriginal(&QPC_BaseTime);
|
||||
QPC_OffsetTime.QuadPart = QPC_BaseTime.QuadPart;
|
||||
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
void SetGameSpeed(float gameSpeed) {
|
||||
if (initialized) {
|
||||
GTC64_OffsetTime = detourGetTickCount64();
|
||||
GTC64_BaseTime = GetTickCount64Hook.pOriginal();
|
||||
|
||||
detourQueryPerformanceCounter(&QPC_OffsetTime);
|
||||
QueryPerformanceCounterHook.pOriginal(&QPC_BaseTime);
|
||||
}
|
||||
|
||||
speed = gameSpeed;
|
||||
}*/
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
// UNUSED HEADER
|
||||
namespace Engine {
|
||||
namespace GameSpeedHandler {
|
||||
extern float speed;
|
||||
extern bool initialized;
|
||||
|
||||
/*void Setup();
|
||||
void SetGameSpeed(float gameSpeed);*/
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,13 @@
|
||||
#include <pch.h>
|
||||
#include "..\GamePH\GameDI_PH.h"
|
||||
#include "..\GamePH\LevelDI.h"
|
||||
#include "..\GamePH\Other.h"
|
||||
#include "..\GamePH\gen_TPPModel.h"
|
||||
#include "..\GamePH\gameph_misc.h"
|
||||
#include "..\core.h"
|
||||
#include "..\menu\camera.h"
|
||||
#include "..\menu\misc.h"
|
||||
#include "..\offsets.h"
|
||||
#include "CBaseCamera.h"
|
||||
#include "engine_misc.h"
|
||||
|
||||
namespace Engine {
|
||||
namespace Hooks {
|
||||
@@ -67,6 +68,8 @@ namespace Engine {
|
||||
#pragma endregion
|
||||
|
||||
#pragma region fs::open
|
||||
static const std::string userModFilesFullPath = "\\\\?\\" + std::filesystem::absolute("..\\..\\..\\source\\data\\EGameTools\\UserModFiles").string();
|
||||
|
||||
static std::vector<std::string> cachedUserModDirs{};
|
||||
static Utils::Time::Timer timeSinceCache{ 0 };
|
||||
static void CacheUserModDirs() {
|
||||
@@ -75,15 +78,17 @@ namespace Engine {
|
||||
if (!cachedUserModDirs.empty())
|
||||
cachedUserModDirs.clear();
|
||||
|
||||
const char* userModFilesPath = "..\\..\\..\\source\\data\\EGameTools\\UserModFiles";
|
||||
cachedUserModDirs.push_back(userModFilesFullPath);
|
||||
try {
|
||||
const auto rdi = std::filesystem::recursive_directory_iterator(userModFilesFullPath);
|
||||
for (auto entry = std::filesystem::begin(rdi); entry != std::filesystem::end(rdi); ++entry) {
|
||||
if (!entry->is_directory())
|
||||
continue;
|
||||
|
||||
cachedUserModDirs.push_back(userModFilesPath);
|
||||
for (const auto& entry : std::filesystem::recursive_directory_iterator(userModFilesPath)) {
|
||||
const std::filesystem::path pathToDir = entry.path();
|
||||
if (!std::filesystem::is_directory(pathToDir))
|
||||
continue;
|
||||
|
||||
cachedUserModDirs.push_back(pathToDir.string());
|
||||
cachedUserModDirs.push_back(entry->path().string());
|
||||
}
|
||||
} catch (const std::exception& e) {
|
||||
spdlog::error("Exception thrown while caching user mod directories: {}", e.what());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,7 +96,7 @@ namespace Engine {
|
||||
return Utils::Memory::GetProcAddr("filesystem_x64_rwdi.dll", "?open@fs@@YAPEAUSFsFile@@V?$string_const@D@ttl@@W4TYPE@EFSMode@@W45FFSOpenFlags@@@Z");
|
||||
}
|
||||
static DWORD64 detourFsOpen(DWORD64 file, DWORD a2, DWORD a3);
|
||||
static Utils::Hook::MHook<LPVOID, DWORD64(*)(DWORD64, DWORD, DWORD)> FsOpenHook{ "fs::open", &GetFsOpen, &detourFsOpen };
|
||||
Utils::Hook::MHook<LPVOID, DWORD64(*)(DWORD64, DWORD, DWORD)> FsOpenHook{ "fs::open", &GetFsOpen, &detourFsOpen };
|
||||
|
||||
static DWORD64 detourFsOpen(DWORD64 file, DWORD a2, DWORD a3) {
|
||||
const DWORD64 firstByte = (file >> 56) & 0xFF; // get first byte of addr
|
||||
@@ -107,22 +112,25 @@ namespace Engine {
|
||||
}
|
||||
|
||||
std::string finalPath{};
|
||||
|
||||
try {
|
||||
for (const auto& entry : cachedUserModDirs) {
|
||||
finalPath = entry + "\\" + fileName;
|
||||
if (!std::filesystem::exists(finalPath))
|
||||
continue;
|
||||
|
||||
const std::string finalPath2 = std::filesystem::absolute(finalPath).string();
|
||||
const char* filePath2 = finalPath2.c_str();
|
||||
|
||||
finalPath.erase(0, userModFilesFullPath.size() + 1); // erase entire path until mod folder
|
||||
const char* filePath2 = finalPath.c_str();
|
||||
spdlog::warn("Loading user mod file \"{}\"", finalPath.c_str());
|
||||
|
||||
const DWORD64 finalAddr = firstByte != 0x0 ? (reinterpret_cast<DWORD64>(filePath2) | (firstByte << 56)) : reinterpret_cast<DWORD64>(filePath2); // restores first byte of addr if first byte was not 0
|
||||
DWORD64 finalAddr = reinterpret_cast<DWORD64>(filePath2);
|
||||
if (firstByte != 0x0)
|
||||
finalAddr |= (firstByte << 56);
|
||||
|
||||
const DWORD64 result = FsOpenHook.pOriginal(finalAddr, a2, a3);
|
||||
if (!result)
|
||||
spdlog::error("fs::open returned 0! Something went wrong with loading user mod file \"{}\"!", finalPath.c_str());
|
||||
if (!result) {
|
||||
spdlog::error("fs::open returned 0! Something went wrong with loading user mod file \"{}\"!\nPlease make sure the path to the file is no longer than 260 characters!", finalPath.c_str());
|
||||
return FsOpenHook.pOriginal(file, a2, a3);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
} catch (const std::exception& e) {
|
||||
@@ -131,5 +139,109 @@ namespace Engine {
|
||||
return FsOpenHook.pOriginal(file, a2, a3);
|
||||
}
|
||||
#pragma endregion
|
||||
|
||||
// Thank you @12brendon34 on Discord for help with finding the function responsible for .PAK loading!
|
||||
#pragma region CResourceLoadingRuntimeCreate
|
||||
namespace fs {
|
||||
struct mount_path {
|
||||
union {
|
||||
const char* gamePath;
|
||||
buffer<0x8, const char*> pakPath;
|
||||
buffer<0x10, const char*> fullPakPath;
|
||||
};
|
||||
};
|
||||
|
||||
static DWORD64 mount(mount_path* path, USHORT flags, LPVOID* a3) {
|
||||
DWORD64(*pMount)(mount_path*, USHORT, LPVOID*) = (decltype(pMount))Utils::Memory::GetProcAddr("filesystem_x64_rwdi.dll", "?mount@fs@@YA_NAEBUmount_path@1@GPEAPEAVCFsMount@@@Z");
|
||||
if (!pMount)
|
||||
return 0;
|
||||
|
||||
return pMount(path, flags, a3);
|
||||
}
|
||||
}
|
||||
|
||||
static LPVOID GetCResourceLoadingRuntimeCreate() {
|
||||
return Utils::Memory::GetProcAddr("engine_x64_rwdi.dll", "?Create@CResourceLoadingRuntime@@SAPEAV1@_N@Z");
|
||||
}
|
||||
static LPVOID detourCResourceLoadingRuntimeCreate(bool noTexStreaming);
|
||||
Utils::Hook::MHook<LPVOID, LPVOID(*)(bool)> CResourceLoadingRuntimeCreateHook{ "CResourceLoadingRuntimeCreate", &GetCResourceLoadingRuntimeCreate, &detourCResourceLoadingRuntimeCreate };
|
||||
|
||||
static LPVOID detourCResourceLoadingRuntimeCreate(bool noTexStreaming) {
|
||||
std::string gamePath = userModFilesFullPath;
|
||||
Utils::Values::str_replace(gamePath, "\\ph\\source\\data\\EGameTools\\UserModFiles", "");
|
||||
|
||||
fs::mount_path pathPtr = fs::mount_path();
|
||||
pathPtr.gamePath = gamePath.c_str();
|
||||
|
||||
try {
|
||||
const auto rdi = std::filesystem::recursive_directory_iterator(userModFilesFullPath);
|
||||
for (auto entry = std::filesystem::begin(rdi); entry != std::filesystem::end(rdi); ++entry) {
|
||||
if (entry->is_directory())
|
||||
continue;
|
||||
std::string fullPakPath = entry->path().string();
|
||||
if (!Utils::Values::str_ends_with_ci(fullPakPath, ".pak"))
|
||||
continue;
|
||||
|
||||
std::string pakPath = fullPakPath;
|
||||
pakPath.erase(0, gamePath.size() + 1);
|
||||
|
||||
pathPtr.pakPath = pakPath.c_str();
|
||||
pathPtr.fullPakPath = fullPakPath.c_str();
|
||||
|
||||
spdlog::warn("Loading user PAK mod file \"{}\"", pakPath.c_str());
|
||||
if (!fs::mount(&pathPtr, 1, nullptr))
|
||||
spdlog::error("fs::mount returned 0! Something went wrong with loading user PAK mod file \"{}\"!\nPlease make sure the path to the file is no longer than 260 characters, and make sure the file is valid!", pakPath.c_str());
|
||||
}
|
||||
} catch (const std::exception& e) {
|
||||
spdlog::error("Exception thrown while iterating over user mod directories for PAK loading: {}", e.what());
|
||||
}
|
||||
|
||||
return CResourceLoadingRuntimeCreateHook.pOriginal(noTexStreaming);
|
||||
}
|
||||
#pragma endregion
|
||||
|
||||
#pragma region MountDataPaks
|
||||
int mountDataPaksRanWith8Count = 0;
|
||||
|
||||
static DWORD64 detourMountDataPaks(DWORD64 a1, UINT a2, UINT a3, DWORD64* a4, DWORD64(*a5)(DWORD64, DWORD, DWORD64, char*, int), INT16 a6, DWORD64 a7, UINT a8);
|
||||
Utils::Hook::MHook<LPVOID, DWORD64(*)(DWORD64, UINT, UINT, DWORD64*, DWORD64(*)(DWORD64, DWORD, DWORD64, char*, int), INT16, DWORD64, UINT)> MountDataPaksHook{ "MountDataPaks", &Offsets::Get_MountDataPaks, &detourMountDataPaks };
|
||||
|
||||
static DWORD64 detourMountDataPaks(DWORD64 a1, UINT a2, UINT a3, DWORD64* a4, DWORD64(*a5)(DWORD64, DWORD, DWORD64, char*, int), INT16 a6, DWORD64 a7, UINT a8) {
|
||||
if (Menu::Misc::increaseDataPAKsLimit.GetValue()) {
|
||||
if (a8 == 8)
|
||||
mountDataPaksRanWith8Count++;
|
||||
|
||||
a8 = 200;
|
||||
}
|
||||
return MountDataPaksHook.pOriginal(a1, a2, a3, a4, a5, a6, a7, a8);
|
||||
}
|
||||
#pragma endregion
|
||||
|
||||
#pragma region FsCheckZipCrc
|
||||
static LPVOID GetFsCheckZipCrc() {
|
||||
return Utils::Memory::GetProcAddr("filesystem_x64_rwdi.dll", "?check_zip_crc@izipped_buffer_file@fs@@QEAA_NXZ");
|
||||
}
|
||||
static bool detourFsCheckZipCrc(LPVOID instance);
|
||||
Utils::Hook::MHook<LPVOID, bool(*)(LPVOID)> FsCheckZipCrcHook{ "FsCheckZipCrc", &GetFsCheckZipCrc, &detourFsCheckZipCrc };
|
||||
|
||||
static bool detourFsCheckZipCrc(LPVOID instance) {
|
||||
return Menu::Misc::disableSavegameCRCCheck.GetValue() ? true : FsCheckZipCrcHook.pOriginal(instance);
|
||||
}
|
||||
#pragma endregion
|
||||
|
||||
#pragma region AuthenticateDataAddNewFile
|
||||
static LPVOID GetAuthenticateDataAddNewFile() {
|
||||
return Utils::Memory::GetProcAddr("engine_x64_rwdi.dll", "?AddNewFile@Results@AuthenticateData@@QEAAAEAVFile@12@XZ");
|
||||
}
|
||||
static LPVOID detourAuthenticateDataAddNewFile(LPVOID instance);
|
||||
Utils::Hook::MHook<LPVOID, LPVOID(*)(LPVOID)> AuthenticateDataAddNewFileHook{ "AuthenticateDataAddNewFile", &GetAuthenticateDataAddNewFile, &detourAuthenticateDataAddNewFile };
|
||||
|
||||
static LPVOID detourAuthenticateDataAddNewFile(LPVOID instance) {
|
||||
LPVOID result = AuthenticateDataAddNewFileHook.pOriginal(instance);
|
||||
if (Menu::Misc::disableDataPAKsCRCCheck.GetValue())
|
||||
AuthenticateDataResultsClear(instance);
|
||||
return result;
|
||||
}
|
||||
#pragma endregion
|
||||
}
|
||||
}
|
||||
@@ -7,5 +7,6 @@ namespace Engine {
|
||||
namespace Hooks {
|
||||
extern bool switchedFreeCamByGamePause;
|
||||
extern Vector3 freeCamPosBeforeGamePause;
|
||||
extern int mountDataPaksRanWith8Count;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
#include <pch.h>
|
||||
|
||||
namespace Engine {
|
||||
void AuthenticateDataResultsClear(LPVOID instance) {
|
||||
void(*pAuthenticateDataResultsClear)(LPVOID instance) = (decltype(pAuthenticateDataResultsClear))Utils::Memory::GetProcAddr("engine_x64_rwdi.dll", "?Clear@Results@AuthenticateData@@QEAAXXZ");
|
||||
if (!pAuthenticateDataResultsClear)
|
||||
return;
|
||||
|
||||
pAuthenticateDataResultsClear(instance);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
#include <minwindef.h>
|
||||
|
||||
namespace Engine {
|
||||
extern void AuthenticateDataResultsClear(LPVOID instance);
|
||||
}
|
||||
@@ -18,6 +18,8 @@ namespace GamePH {
|
||||
DayNightCycle* ptr = *reinterpret_cast<DayNightCycle**>(Offsets::Get_g_DayNightCycle());
|
||||
if (!Utils::Memory::IsValidPtrMod(ptr, "gamedll_ph_x64_rwdi.dll"))
|
||||
return nullptr;
|
||||
if (*reinterpret_cast<DWORD64**>(ptr) != Offsets::GetVT_DayNightCycle())
|
||||
return nullptr;
|
||||
|
||||
return ptr;
|
||||
} __except (EXCEPTION_EXECUTE_HANDLER) {
|
||||
|
||||
@@ -24,6 +24,8 @@ namespace GamePH {
|
||||
FreeCamera* ptr = reinterpret_cast<FreeCamera*>(*pg_FreeCamera);
|
||||
if (!Utils::Memory::IsValidPtrMod(ptr, "gamedll_ph_x64_rwdi.dll"))
|
||||
return nullptr;
|
||||
if (*reinterpret_cast<DWORD64**>(ptr) != Offsets::GetVT_FreeCamera())
|
||||
return nullptr;
|
||||
|
||||
return ptr;
|
||||
} __except (EXCEPTION_EXECUTE_HANDLER) {
|
||||
|
||||
@@ -36,6 +36,8 @@ namespace GamePH {
|
||||
GameDI_PH* ptr = pCGame->pGameDI_PH;
|
||||
if (!Utils::Memory::IsValidPtrMod(ptr, "gamedll_ph_x64_rwdi.dll"))
|
||||
return nullptr;
|
||||
if (*reinterpret_cast<DWORD64**>(ptr) != Offsets::GetVT_GameDI_PH())
|
||||
return nullptr;
|
||||
|
||||
return ptr;
|
||||
} __except (EXCEPTION_EXECUTE_HANDLER) {
|
||||
|
||||
@@ -9,11 +9,10 @@ namespace GamePH {
|
||||
public:
|
||||
union {
|
||||
buffer<0x130, SessionCooperativeDI*> pSessionCooperativeDI;
|
||||
buffer<0x880, bool> blockPauseGameOnPlayerAfk;
|
||||
buffer<0x908, bool> blockPauseGameOnPlayerAfk;
|
||||
};
|
||||
|
||||
float GetGameTimeDelta();
|
||||
DWORD64 GetCurrentGameVersion();
|
||||
void TogglePhotoMode(bool doNothing = false, bool setAsOptionalCamera = false);
|
||||
|
||||
static GameDI_PH* Get();
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
#include <pch.h>
|
||||
#include "..\offsets.h"
|
||||
#include "InventoryContainerDI.h"
|
||||
#include "InventoryMoney.h"
|
||||
|
||||
namespace GamePH {
|
||||
InventoryMoney* InventoryContainerDI::GetInventoryMoney(UINT indexMaybe) {
|
||||
__try {
|
||||
LPVOID(*pPlayerGetInventoryMoney)(LPVOID pPlayerDI_PH, UINT indexMaybe) = (decltype(pPlayerGetInventoryMoney))Offsets::Get_PlayerGetInventoryMoney();
|
||||
if (!pPlayerGetInventoryMoney)
|
||||
return nullptr;
|
||||
|
||||
InventoryMoney* ptr = reinterpret_cast<InventoryMoney*>(pPlayerGetInventoryMoney(this, indexMaybe));
|
||||
if (!Utils::Memory::IsValidPtrMod(ptr, "gamedll_ph_x64_rwdi.dll"))
|
||||
return nullptr;
|
||||
if (*reinterpret_cast<DWORD64**>(ptr) != Offsets::GetVT_InventoryMoney())
|
||||
return nullptr;
|
||||
|
||||
return ptr;
|
||||
} __except (EXCEPTION_EXECUTE_HANDLER) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
#include "..\buffer.h"
|
||||
#include "InventoryMoney.h"
|
||||
|
||||
namespace GamePH {
|
||||
class InventoryContainerDI {
|
||||
public:
|
||||
InventoryMoney* GetInventoryMoney(UINT indexMaybe);
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
#include <pch.h>
|
||||
#include "..\offsets.h"
|
||||
#include "InventoryItem.h"
|
||||
#include "ItemDescWithContext.h"
|
||||
|
||||
namespace GamePH {
|
||||
ItemDescWithContext* InventoryItem::GetItemDescCtx() {
|
||||
__try {
|
||||
ItemDescWithContext* ptr = reinterpret_cast<ItemDescWithContext*>(reinterpret_cast<DWORD64>(this) + 0x40);
|
||||
if (!Utils::Memory::IsValidPtrMod(ptr, "gamedll_ph_x64_rwdi.dll"))
|
||||
return nullptr;
|
||||
if (*reinterpret_cast<DWORD64**>(ptr) != Offsets::GetVT_ItemDescWithContext())
|
||||
return nullptr;
|
||||
|
||||
return ptr;
|
||||
} __except (EXCEPTION_EXECUTE_HANDLER) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
#include "..\buffer.h"
|
||||
#include "ItemDescWithContext.h"
|
||||
|
||||
namespace GamePH {
|
||||
class InventoryItem {
|
||||
public:
|
||||
ItemDescWithContext* GetItemDescCtx();
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
#include "..\buffer.h"
|
||||
|
||||
namespace GamePH {
|
||||
class InventoryMoney {
|
||||
public:
|
||||
buffer<0x38, int> oldWorldMoney;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
#include "..\buffer.h"
|
||||
|
||||
namespace GamePH {
|
||||
class ItemDescWithContext {
|
||||
public:
|
||||
union {
|
||||
buffer<0xA8, float> weaponDurability;
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1,7 +1,8 @@
|
||||
#include <pch.h>
|
||||
#include "..\Engine\CLevel.h"
|
||||
#include "..\offsets.h"
|
||||
#include "LevelDI.h"
|
||||
#include "PlayerObjProperties.h"
|
||||
#include "PlayerDI_PH.h"
|
||||
|
||||
namespace GamePH {
|
||||
bool LevelDI::IsLoading() {
|
||||
@@ -19,7 +20,7 @@ namespace GamePH {
|
||||
static Utils::Time::Timer loadTimer{ 7500 };
|
||||
static bool isStillLoading = false;
|
||||
|
||||
if (IsLoading() || !GamePH::PlayerObjProperties::Get()) {
|
||||
if (IsLoading() || !GamePH::PlayerDI_PH::Get()) {
|
||||
isStillLoading = true;
|
||||
return false;
|
||||
}
|
||||
@@ -139,6 +140,8 @@ namespace GamePH {
|
||||
LevelDI* ptr = pCLevel->pLevelDI;
|
||||
if (!Utils::Memory::IsValidPtrMod(ptr, "gamedll_ph_x64_rwdi.dll"))
|
||||
return nullptr;
|
||||
if (*reinterpret_cast<DWORD64**>(ptr) != Offsets::GetVT_LevelDI())
|
||||
return nullptr;
|
||||
|
||||
return ptr;
|
||||
} __except (EXCEPTION_EXECUTE_HANDLER) {
|
||||
|
||||
@@ -11,10 +11,6 @@ namespace GamePH {
|
||||
|
||||
class LevelDI {
|
||||
public:
|
||||
union {
|
||||
buffer<0x160, PlayerDI_PH*> pPlayerDI_PH;
|
||||
};
|
||||
|
||||
bool IsLoading();
|
||||
bool IsLoaded();
|
||||
LPVOID GetViewCamera();
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include <pch.h>
|
||||
#include "..\offsets.h"
|
||||
#include "LocalClientDI.h"
|
||||
#include "SessionCooperativeDI.h"
|
||||
|
||||
@@ -12,6 +13,8 @@ namespace GamePH {
|
||||
LocalClientDI* ptr = pSessionCooperativeDI->pLocalClientDI;
|
||||
if (!Utils::Memory::IsValidPtrMod(ptr, "gamedll_ph_x64_rwdi.dll"))
|
||||
return nullptr;
|
||||
if (*reinterpret_cast<DWORD64**>(ptr) != Offsets::GetVT_LocalClientDI())
|
||||
return nullptr;
|
||||
|
||||
return ptr;
|
||||
} __except (EXCEPTION_EXECUTE_HANDLER) {
|
||||
|
||||
@@ -2,12 +2,12 @@
|
||||
#include "..\buffer.h"
|
||||
|
||||
namespace GamePH {
|
||||
class gen_TPPModel;
|
||||
class PlayerDI_PH;
|
||||
|
||||
class LocalClientDI {
|
||||
public:
|
||||
union {
|
||||
buffer<0x90, gen_TPPModel*> pgen_TPPModel;
|
||||
buffer<0x90, PlayerDI_PH*> pPlayerDI_PH;
|
||||
};
|
||||
|
||||
static LocalClientDI* Get();
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include <pch.h>
|
||||
#include "..\Engine\CGSObject2.h"
|
||||
#include "..\offsets.h"
|
||||
#include "LogicalPlayer.h"
|
||||
|
||||
namespace GamePH {
|
||||
@@ -12,6 +13,8 @@ namespace GamePH {
|
||||
LogicalPlayer* ptr = pCGSObject2->pLogicalPlayer;
|
||||
if (!Utils::Memory::IsValidPtrMod(ptr, "gamedll_ph_x64_rwdi.dll"))
|
||||
return nullptr;
|
||||
if (*reinterpret_cast<DWORD64**>(ptr) != Offsets::GetVT_LogicalPlayer())
|
||||
return nullptr;
|
||||
|
||||
return ptr;
|
||||
} __except (EXCEPTION_EXECUTE_HANDLER) {
|
||||
|
||||
@@ -1,18 +1,53 @@
|
||||
#include <pch.h>
|
||||
#include "..\offsets.h"
|
||||
#include "LevelDI.h"
|
||||
#include "InventoryContainerDI.h"
|
||||
#include "InventoryItem.h"
|
||||
#include "LocalClientDI.h"
|
||||
#include "PlayerDI_PH.h"
|
||||
|
||||
namespace GamePH {
|
||||
PlayerDI_PH* PlayerDI_PH::Get() {
|
||||
__try {
|
||||
LevelDI* iLevel = LevelDI::Get();
|
||||
if (!iLevel)
|
||||
LocalClientDI* localClient = LocalClientDI::Get();
|
||||
if (!localClient)
|
||||
return nullptr;
|
||||
|
||||
PlayerDI_PH* ptr = iLevel->pPlayerDI_PH;
|
||||
PlayerDI_PH* ptr = localClient->pPlayerDI_PH;
|
||||
if (!Utils::Memory::IsValidPtrMod(ptr, "gamedll_ph_x64_rwdi.dll"))
|
||||
return nullptr;
|
||||
if (*reinterpret_cast<DWORD64**>(ptr) != Offsets::GetVT_PlayerDI_PH())
|
||||
return nullptr;
|
||||
|
||||
return ptr;
|
||||
} __except (EXCEPTION_EXECUTE_HANDLER) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
InventoryItem* PlayerDI_PH::GetCurrentWeapon(UINT indexMaybe) {
|
||||
__try {
|
||||
LPVOID(*pPlayerGetCurrentWeapon)(LPVOID pPlayerDI_PH, UINT indexMaybe) = (decltype(pPlayerGetCurrentWeapon))Offsets::Get_PlayerGetCurrentWeapon();
|
||||
if (!pPlayerGetCurrentWeapon)
|
||||
return nullptr;
|
||||
|
||||
InventoryItem* ptr = reinterpret_cast<InventoryItem*>(pPlayerGetCurrentWeapon(this, indexMaybe));
|
||||
if (!Utils::Memory::IsValidPtrMod(ptr, "gamedll_ph_x64_rwdi.dll"))
|
||||
return nullptr;
|
||||
if (*reinterpret_cast<DWORD64**>(ptr) != Offsets::GetVT_InventoryItem())
|
||||
return nullptr;
|
||||
|
||||
return ptr;
|
||||
} __except (EXCEPTION_EXECUTE_HANDLER) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
InventoryContainerDI* PlayerDI_PH::GetInventoryContainer() {
|
||||
__try {
|
||||
InventoryContainerDI* ptr = reinterpret_cast<InventoryContainerDI*>(*reinterpret_cast<DWORD64*>(reinterpret_cast<DWORD64>(this) + 0x470));
|
||||
if (!Utils::Memory::IsValidPtrMod(ptr, "gamedll_ph_x64_rwdi.dll"))
|
||||
return nullptr;
|
||||
if (*reinterpret_cast<DWORD64**>(ptr) != Offsets::GetVT_InventoryContainerDI())
|
||||
return nullptr;
|
||||
|
||||
return ptr;
|
||||
} __except (EXCEPTION_EXECUTE_HANDLER) {
|
||||
|
||||
@@ -1,9 +1,24 @@
|
||||
#pragma once
|
||||
#include "..\buffer.h"
|
||||
#include "InventoryItem.h"
|
||||
#include "InventoryContainerDI.h"
|
||||
|
||||
namespace Engine {
|
||||
class CoPhysicsProperty;
|
||||
}
|
||||
|
||||
namespace GamePH {
|
||||
class PlayerDI_PH {
|
||||
public:
|
||||
union {
|
||||
buffer<0xF0, Engine::CoPhysicsProperty*> pCoPhysicsProperty;
|
||||
buffer<0x35E9, bool> enableTPPModel1;
|
||||
buffer<0x35EA, bool> enableTPPModel2;
|
||||
};
|
||||
|
||||
static PlayerDI_PH* Get();
|
||||
|
||||
InventoryItem* GetCurrentWeapon(UINT indexMaybe);
|
||||
InventoryContainerDI* GetInventoryContainer();
|
||||
};
|
||||
}
|
||||
@@ -1,8 +1,11 @@
|
||||
#include <pch.h>
|
||||
#include "PlayerDI_PH.h"
|
||||
#include "PlayerHealthModule.h"
|
||||
|
||||
namespace GamePH {
|
||||
PlayerHealthModule* PlayerHealthModule::pPlayerHealthModule = nullptr;
|
||||
static PlayerHealthModule* pPlayerHealthModule = nullptr;
|
||||
std::vector<PlayerHealthModule*> PlayerHealthModule::playerHealthModulePtrList{};
|
||||
|
||||
PlayerHealthModule* PlayerHealthModule::Get() {
|
||||
__try {
|
||||
if (!pPlayerHealthModule)
|
||||
@@ -13,7 +16,25 @@ namespace GamePH {
|
||||
return pPlayerHealthModule;
|
||||
} __except (EXCEPTION_EXECUTE_HANDLER) {
|
||||
pPlayerHealthModule = nullptr;
|
||||
playerHealthModulePtrList.clear();
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
void PlayerHealthModule::Set(LPVOID instance) { pPlayerHealthModule = reinterpret_cast<PlayerHealthModule*>(instance); }
|
||||
|
||||
void PlayerHealthModule::UpdateClassAddr() {
|
||||
PlayerDI_PH* pPlayerDI_PH = PlayerDI_PH::Get();
|
||||
if (!pPlayerDI_PH)
|
||||
return;
|
||||
if (PlayerHealthModule::Get() && PlayerHealthModule::Get()->pPlayerDI_PH == pPlayerDI_PH)
|
||||
return;
|
||||
|
||||
for (auto& pPlayerHealthModule : PlayerHealthModule::playerHealthModulePtrList) {
|
||||
if (pPlayerHealthModule->pPlayerDI_PH == pPlayerDI_PH) {
|
||||
PlayerHealthModule::Set(pPlayerHealthModule);
|
||||
PlayerHealthModule::playerHealthModulePtrList.clear();
|
||||
PlayerHealthModule::playerHealthModulePtrList.emplace_back(pPlayerHealthModule);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12,7 +12,11 @@ namespace GamePH {
|
||||
buffer<0x3C, float> maxHealth;
|
||||
};
|
||||
|
||||
static PlayerHealthModule* pPlayerHealthModule;
|
||||
static std::vector<PlayerHealthModule*> playerHealthModulePtrList;
|
||||
|
||||
static PlayerHealthModule* Get();
|
||||
static void Set(LPVOID instance);
|
||||
|
||||
static void UpdateClassAddr();
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
#include <pch.h>
|
||||
#include "PlayerDI_PH.h"
|
||||
#include "PlayerInfectionModule.h"
|
||||
|
||||
namespace GamePH {
|
||||
static PlayerInfectionModule* pPlayerInfectionModule = nullptr;
|
||||
std::vector<PlayerInfectionModule*> PlayerInfectionModule::playerInfectionModulePtrList{};
|
||||
|
||||
PlayerInfectionModule* PlayerInfectionModule::Get() {
|
||||
__try {
|
||||
if (!pPlayerInfectionModule)
|
||||
return nullptr;
|
||||
if (!*reinterpret_cast<LPVOID*>(pPlayerInfectionModule))
|
||||
return nullptr;
|
||||
|
||||
return pPlayerInfectionModule;
|
||||
} __except (EXCEPTION_EXECUTE_HANDLER) {
|
||||
pPlayerInfectionModule = nullptr;
|
||||
playerInfectionModulePtrList.clear();
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
void PlayerInfectionModule::Set(LPVOID instance) { pPlayerInfectionModule = reinterpret_cast<PlayerInfectionModule*>(instance); }
|
||||
|
||||
void PlayerInfectionModule::UpdateClassAddr() {
|
||||
PlayerDI_PH* pPlayerDI_PH = PlayerDI_PH::Get();
|
||||
if (!pPlayerDI_PH)
|
||||
return;
|
||||
if (PlayerInfectionModule::Get() && PlayerInfectionModule::Get()->pPlayerDI_PH == pPlayerDI_PH)
|
||||
return;
|
||||
|
||||
for (auto& pPlayerInfectionModule : PlayerInfectionModule::playerInfectionModulePtrList) {
|
||||
if (pPlayerInfectionModule->pPlayerDI_PH == pPlayerDI_PH) {
|
||||
PlayerInfectionModule::Set(pPlayerInfectionModule);
|
||||
PlayerInfectionModule::playerInfectionModulePtrList.clear();
|
||||
PlayerInfectionModule::playerInfectionModulePtrList.emplace_back(pPlayerInfectionModule);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
#include "..\buffer.h"
|
||||
|
||||
namespace GamePH {
|
||||
class PlayerDI_PH;
|
||||
|
||||
class PlayerInfectionModule {
|
||||
public:
|
||||
union {
|
||||
buffer<0x8, PlayerDI_PH*> pPlayerDI_PH;
|
||||
buffer<0x20, float> maxImmunity;
|
||||
buffer<0x2C, float> immunity;
|
||||
};
|
||||
|
||||
static std::vector<PlayerInfectionModule*> playerInfectionModulePtrList;
|
||||
|
||||
static PlayerInfectionModule* Get();
|
||||
static void Set(LPVOID instance);
|
||||
|
||||
static void UpdateClassAddr();
|
||||
};
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
#include <pch.h>
|
||||
#include "..\offsets.h"
|
||||
#include "PlayerObjProperties.h"
|
||||
|
||||
namespace GamePH {
|
||||
PlayerObjProperties* PlayerObjProperties::Get() {
|
||||
__try {
|
||||
if (!Offsets::Get_g_PlayerObjProperties())
|
||||
return nullptr;
|
||||
|
||||
PlayerObjProperties* ptr = *reinterpret_cast<PlayerObjProperties**>(Offsets::Get_g_PlayerObjProperties());
|
||||
if (!Utils::Memory::IsValidPtrMod(ptr, "gamedll_ph_x64_rwdi.dll"))
|
||||
return nullptr;
|
||||
|
||||
return ptr;
|
||||
} __except (EXCEPTION_EXECUTE_HANDLER) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
#pragma once
|
||||
#include "..\buffer.h"
|
||||
|
||||
namespace Engine {
|
||||
class CoPhysicsProperty;
|
||||
}
|
||||
|
||||
namespace GamePH {
|
||||
class PlayerObjProperties {
|
||||
public:
|
||||
union {
|
||||
buffer<0xF0, Engine::CoPhysicsProperty*> pCoPhysicsProperty;
|
||||
//buffer<0x2E80, bool> isOutOfBounds;
|
||||
//buffer<0x2E84, float> outOfBoundsTimer;
|
||||
};
|
||||
|
||||
static PlayerObjProperties* Get();
|
||||
};
|
||||
}
|
||||
@@ -11,6 +11,8 @@ namespace GamePH {
|
||||
PlayerState* ptr = *reinterpret_cast<PlayerState**>(Offsets::Get_PlayerState());
|
||||
if (!Utils::Memory::IsValidPtrMod(ptr, "gamedll_ph_x64_rwdi.dll"))
|
||||
return nullptr;
|
||||
if (*reinterpret_cast<DWORD64**>(ptr) != Offsets::GetVT_PlayerState())
|
||||
return nullptr;
|
||||
|
||||
return ptr;
|
||||
} __except (EXCEPTION_EXECUTE_HANDLER) {
|
||||
|
||||
@@ -7,7 +7,7 @@ namespace GamePH {
|
||||
class PlayerState {
|
||||
public:
|
||||
union {
|
||||
buffer<0x2B0, PlayerVariables*> playerVars;
|
||||
buffer<0x300, PlayerVariables*> playerVars;
|
||||
};
|
||||
|
||||
static PlayerState* Get();
|
||||
|
||||
@@ -13,25 +13,7 @@ namespace GamePH {
|
||||
std::vector<std::pair<std::string, std::pair<std::any, std::string>>> PlayerVariables::playerVarsDefault;
|
||||
std::vector<std::pair<std::string, std::pair<std::any, std::string>>> PlayerVariables::playerCustomVarsDefault;
|
||||
bool PlayerVariables::gotPlayerVars = false;
|
||||
|
||||
static PDWORD64 getFloatPlayerVariableVT() {
|
||||
if (!Offsets::Get_InitializePlayerVariables())
|
||||
return nullptr;
|
||||
|
||||
const DWORD64 offsetToInstr = Offsets::Get_InitializePlayerVariables() + Offsets::Get_initPlayerFloatVarsInstr_offset() + 0x3; // 0x3 is instruction size
|
||||
const DWORD floatPlayerVariableVTOffset = *reinterpret_cast<DWORD*>(offsetToInstr);
|
||||
|
||||
return reinterpret_cast<PDWORD64>(offsetToInstr + sizeof(DWORD) + floatPlayerVariableVTOffset);
|
||||
}
|
||||
static PDWORD64 getBoolPlayerVariableVT() {
|
||||
if (!Offsets::Get_InitializePlayerVariables())
|
||||
return nullptr;
|
||||
|
||||
const DWORD64 offsetToInstr = Offsets::Get_InitializePlayerVariables() + Offsets::Get_initPlayerBoolVarsInstr_offset() + 0x3; // 0x3 is instruction size
|
||||
const DWORD boolPlayerVariableVTOffset = *reinterpret_cast<DWORD*>(offsetToInstr);
|
||||
|
||||
return reinterpret_cast<PDWORD64>(offsetToInstr + sizeof(DWORD) + boolPlayerVariableVTOffset);
|
||||
}
|
||||
static bool sortedPlayerVars = false;
|
||||
|
||||
template <typename T>
|
||||
static void updateDefaultVar(std::vector<std::pair<std::string, std::pair<std::any, std::string>>>& defaultVars, const std::string& varName, T varValue) {
|
||||
@@ -47,8 +29,8 @@ namespace GamePH {
|
||||
}
|
||||
static void processPlayerVar(PDWORD64*& playerVarsMem, std::pair<std::string, std::pair<LPVOID, std::string>>& var) {
|
||||
while (true) {
|
||||
const bool isFloatPlayerVar = *playerVarsMem == getFloatPlayerVariableVT();
|
||||
const bool isBoolPlayerVar = *playerVarsMem == getBoolPlayerVariableVT();
|
||||
const bool isFloatPlayerVar = *playerVarsMem == Offsets::GetVT_FloatPlayerVariable();
|
||||
const bool isBoolPlayerVar = *playerVarsMem == Offsets::GetVT_BoolPlayerVariable();
|
||||
|
||||
if (isFloatPlayerVar || isBoolPlayerVar) {
|
||||
var.second.first = playerVarsMem + VAR_LOC_OFFSET;
|
||||
@@ -77,54 +59,152 @@ namespace GamePH {
|
||||
void PlayerVariables::GetPlayerVars() {
|
||||
if (gotPlayerVars)
|
||||
return;
|
||||
if (!sortedPlayerVars)
|
||||
return;
|
||||
if (!Get())
|
||||
return;
|
||||
if (playerVars.empty())
|
||||
return;
|
||||
if (!getFloatPlayerVariableVT())
|
||||
return;
|
||||
if (!getBoolPlayerVariableVT())
|
||||
if (!Offsets::GetVT_FloatPlayerVariable() || !Offsets::GetVT_BoolPlayerVariable())
|
||||
return;
|
||||
|
||||
PDWORD64* playerVarsMem = reinterpret_cast<PDWORD64*>(Get());
|
||||
DWORD64** playerVarsMem = reinterpret_cast<DWORD64**>(Get());
|
||||
|
||||
for (auto& var : playerVars)
|
||||
processPlayerVar(playerVarsMem, var);
|
||||
|
||||
gotPlayerVars = true;
|
||||
}
|
||||
void PlayerVariables::SortPlayerVars() {
|
||||
if (!playerVars.empty())
|
||||
return;
|
||||
|
||||
std::stringstream ss(Config::playerVars);
|
||||
#pragma region Player Variables Sorting
|
||||
struct VarTypeFieldMeta {
|
||||
PlayerVariables::PlayerVarType type;
|
||||
LPVOID(*getFieldMetaVT)();
|
||||
};
|
||||
const std::vector<VarTypeFieldMeta> varTypeFields = {
|
||||
{ PlayerVariables::PlayerVarType::Float, Offsets::GetVT_TypedFieldMetaFloatPlayerVariable },
|
||||
{ PlayerVariables::PlayerVarType::Bool, Offsets::GetVT_TypedFieldMetaBoolPlayerVariable }
|
||||
};
|
||||
|
||||
while (ss.good()) {
|
||||
// separate the string by the , character to get each variable
|
||||
std::string pVar{};
|
||||
getline(ss, pVar, ',');
|
||||
bool isRetInstruction(BYTE* address) {
|
||||
return address[0] == 0xC3 && address[1] == 0xCC;
|
||||
}
|
||||
bool isLeaInstruction(BYTE* address, BYTE REX, BYTE ModRM) {
|
||||
return address[0] == REX && address[1] == 0x8D && address[2] == ModRM;
|
||||
}
|
||||
bool isCallInstruction(BYTE* address) {
|
||||
return address[0] == 0xE8 && address[4] != 0xE8;
|
||||
}
|
||||
bool isBelowFuncSizeLimit(BYTE* address, DWORD64 startOfFunc, size_t sizeLimit) {
|
||||
return (reinterpret_cast<DWORD64>(address) - startOfFunc) < sizeLimit;
|
||||
}
|
||||
|
||||
std::stringstream ssPVar(pVar);
|
||||
// to prevent infinite loops, assuming function is no longer than 500000 bytes LMAO Techland... why is your function even like 250000 bytes to begin with? bad code...
|
||||
static const size_t MAX_FUNC_SIZE = 500000;
|
||||
static const size_t MAX_LOAD_VAR_FUNC_SIZE = 2000;
|
||||
|
||||
std::string varName{};
|
||||
std::string varType{};
|
||||
|
||||
while (ssPVar.good()) {
|
||||
// seperate the string by the : character to get name and type of variable
|
||||
std::string subStr{};
|
||||
getline(ssPVar, subStr, ':');
|
||||
|
||||
if (subStr != "float" && subStr != "bool")
|
||||
varName = subStr;
|
||||
else
|
||||
varType = subStr;
|
||||
static const char* getPlayerVarName(BYTE*& funcAddress, DWORD64 startOfFunc) {
|
||||
const char* playerVarName = nullptr;
|
||||
while (!playerVarName && !isRetInstruction(funcAddress) && isBelowFuncSizeLimit(funcAddress, startOfFunc, MAX_FUNC_SIZE)) {
|
||||
// lea r8, varNameString
|
||||
if (!isLeaInstruction(funcAddress, 0x4C, 0x05)) {
|
||||
funcAddress++;
|
||||
continue;
|
||||
}
|
||||
|
||||
PlayerVariables::playerVars.emplace_back(varName, std::make_pair(nullptr, varType));
|
||||
PlayerVariables::playerVarsDefault.emplace_back(varName, std::make_pair(varType == "float" ? 0.0f : false, varType));
|
||||
PlayerVariables::playerCustomVarsDefault.emplace_back(varName, std::make_pair(varType == "float" ? 0.0f : false, varType));
|
||||
playerVarName = reinterpret_cast<const char*>(Utils::Memory::CalcTargetAddrOfRelInst(reinterpret_cast<DWORD64>(funcAddress), 3));
|
||||
if (!playerVarName) {
|
||||
funcAddress++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// add the size of the instruction, so we skip this instruction because this instruction is the name
|
||||
funcAddress += 0x7;
|
||||
}
|
||||
|
||||
return playerVarName;
|
||||
}
|
||||
PlayerVariables::PlayerVarType getPlayerVarType(BYTE*& funcAddress, DWORD64 startOfFunc) {
|
||||
PlayerVariables::PlayerVarType playerVarType = PlayerVariables::PlayerVarType::NONE;
|
||||
|
||||
while (!playerVarType && !isRetInstruction(funcAddress) && isBelowFuncSizeLimit(funcAddress, startOfFunc, MAX_FUNC_SIZE)) {
|
||||
// call LoadPlayerXVariable
|
||||
if (!isCallInstruction(funcAddress)) {
|
||||
funcAddress++;
|
||||
continue;
|
||||
}
|
||||
|
||||
DWORD64 startOfLoadVarFunc = Utils::Memory::CalcTargetAddrOfRelInst(reinterpret_cast<DWORD64>(funcAddress), 1);
|
||||
for (const auto& varType : varTypeFields) {
|
||||
DWORD64 metaVTAddr = reinterpret_cast<DWORD64>(varType.getFieldMetaVT());
|
||||
BYTE* loadVarFuncAddress = reinterpret_cast<BYTE*>(startOfLoadVarFunc);
|
||||
DWORD64 metaVTAddrFromFunc = 0;
|
||||
|
||||
while (!metaVTAddrFromFunc && !isRetInstruction(loadVarFuncAddress) && isBelowFuncSizeLimit(loadVarFuncAddress, startOfLoadVarFunc, MAX_LOAD_VAR_FUNC_SIZE)) {
|
||||
// lea rax, typedFieldMetaVT
|
||||
if (!isLeaInstruction(loadVarFuncAddress, 0x48, 0x05)) {
|
||||
loadVarFuncAddress++;
|
||||
continue;
|
||||
}
|
||||
|
||||
metaVTAddrFromFunc = Utils::Memory::CalcTargetAddrOfRelInst(reinterpret_cast<DWORD64>(loadVarFuncAddress), 3);
|
||||
if (metaVTAddrFromFunc != metaVTAddr) {
|
||||
metaVTAddrFromFunc = 0;
|
||||
loadVarFuncAddress++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (metaVTAddr == metaVTAddrFromFunc) {
|
||||
playerVarType = varType.type;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// if it's still NONE after seeing the function doesnt reference any of the variables, break so the loop stops
|
||||
if (playerVarType == PlayerVariables::PlayerVarType::NONE)
|
||||
break;
|
||||
}
|
||||
|
||||
return playerVarType;
|
||||
}
|
||||
|
||||
void PlayerVariables::SortPlayerVars() {
|
||||
DWORD64 startOfFunc = 0;
|
||||
while (!startOfFunc)
|
||||
startOfFunc = reinterpret_cast<DWORD64>(Offsets::Get_LoadPlayerVars());
|
||||
|
||||
BYTE* funcAddress = reinterpret_cast<BYTE*>(startOfFunc);
|
||||
while (!isRetInstruction(funcAddress) && (reinterpret_cast<DWORD64>(funcAddress) - startOfFunc) < MAX_FUNC_SIZE) {
|
||||
const char* playerVarName = getPlayerVarName(funcAddress, startOfFunc);
|
||||
if (!playerVarName)
|
||||
continue;
|
||||
|
||||
PlayerVarType playerVarType = getPlayerVarType(funcAddress, startOfFunc);
|
||||
if (!playerVarType)
|
||||
continue;
|
||||
|
||||
std::string varType{};
|
||||
switch (playerVarType) {
|
||||
case PlayerVarType::Float:
|
||||
varType = "float";
|
||||
break;
|
||||
case PlayerVarType::Bool:
|
||||
varType = "bool";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
PlayerVariables::playerVars.emplace_back(playerVarName, std::make_pair(nullptr, varType));
|
||||
PlayerVariables::playerVarsDefault.emplace_back(playerVarName, std::make_pair(varType == "float" ? 0.0f : false, varType));
|
||||
PlayerVariables::playerCustomVarsDefault.emplace_back(playerVarName, std::make_pair(varType == "float" ? 0.0f : false, varType));
|
||||
}
|
||||
|
||||
sortedPlayerVars = true;
|
||||
}
|
||||
#pragma endregion
|
||||
|
||||
std::unordered_map<std::string, std::any> PlayerVariables::prevPlayerVarValueMap{};
|
||||
std::unordered_map<std::string, bool> PlayerVariables::prevOptionValueMap{};
|
||||
|
||||
PlayerVariables* PlayerVariables::Get() {
|
||||
__try {
|
||||
|
||||
@@ -9,6 +9,13 @@
|
||||
namespace GamePH {
|
||||
class PlayerVariables {
|
||||
public:
|
||||
enum PlayerVarType {
|
||||
NONE = 0,
|
||||
String,
|
||||
Float,
|
||||
Bool
|
||||
};
|
||||
|
||||
static std::vector<std::pair<std::string, std::pair<LPVOID, std::string>>> playerVars;
|
||||
static std::vector<std::pair<std::string, std::pair<std::any, std::string>>> playerVarsDefault;
|
||||
static std::vector<std::pair<std::string, std::pair<std::any, std::string>>> playerCustomVarsDefault;
|
||||
@@ -30,6 +37,9 @@ namespace GamePH {
|
||||
template <typename T> static T GetPlayerVar(const std::string& playerVar) {
|
||||
static_assert(std::is_same<T, bool>::value || std::is_same<T, float>::value || std::is_same<T, std::string>::value, "Invalid type: value must be bool, float or string");
|
||||
|
||||
if (!gotPlayerVars)
|
||||
return getDefaultValue<T>();
|
||||
|
||||
auto it = std::find_if(PlayerVariables::playerVars.begin(), PlayerVariables::playerVars.end(), [&playerVar](const auto& pair) {
|
||||
return pair.first == playerVar;
|
||||
});
|
||||
@@ -74,21 +84,27 @@ namespace GamePH {
|
||||
*(varValue + 1) = value;
|
||||
}
|
||||
}
|
||||
static std::unordered_map<std::string, std::any> prevPlayerVarValueMap;
|
||||
static std::unordered_map<std::string, bool> prevOptionValueMap;
|
||||
|
||||
template <typename T> static void ManagePlayerVarOption(const std::string& playerVar, const T valueIfTrue, const T valueIfFalse, Option* option, const bool& usePreviousVal = true) {
|
||||
if (!gotPlayerVars)
|
||||
return;
|
||||
|
||||
static T previousPlayerVarValue = GamePH::PlayerVariables::GetPlayerVar<T>(playerVar);
|
||||
if (prevPlayerVarValueMap.find(playerVar) == prevPlayerVarValueMap.end())
|
||||
prevPlayerVarValueMap[playerVar] = GamePH::PlayerVariables::GetPlayerVar<T>(playerVar);
|
||||
if (prevOptionValueMap.find(playerVar) == prevOptionValueMap.end())
|
||||
prevOptionValueMap[playerVar] = false;
|
||||
|
||||
if (option->GetValue()) {
|
||||
if (!option->GetPrevValue())
|
||||
previousPlayerVarValue = GamePH::PlayerVariables::GetPlayerVar<T>(playerVar);
|
||||
if (!prevOptionValueMap[playerVar])
|
||||
prevPlayerVarValueMap[playerVar] = GamePH::PlayerVariables::GetPlayerVar<T>(playerVar);
|
||||
|
||||
GamePH::PlayerVariables::ChangePlayerVar(playerVar, valueIfTrue);
|
||||
option->SetPrevValue(true);
|
||||
} else if (option->GetPrevValue()) {
|
||||
option->SetPrevValue(false);
|
||||
GamePH::PlayerVariables::ChangePlayerVar(playerVar, usePreviousVal ? previousPlayerVarValue : valueIfFalse);
|
||||
prevOptionValueMap[playerVar] = true;
|
||||
} else if (prevOptionValueMap[playerVar]) {
|
||||
prevOptionValueMap[playerVar] = false;
|
||||
GamePH::PlayerVariables::ChangePlayerVar(playerVar, usePreviousVal ? std::any_cast<T>(prevPlayerVarValueMap[playerVar]) : valueIfFalse);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include <pch.h>
|
||||
#include "..\offsets.h"
|
||||
#include "GameDI_PH.h"
|
||||
#include "SessionCooperativeDI.h"
|
||||
|
||||
@@ -12,6 +13,8 @@ namespace GamePH {
|
||||
SessionCooperativeDI* ptr = pGameDI_PH->pSessionCooperativeDI;
|
||||
if (!Utils::Memory::IsValidPtrMod(ptr, "gamedll_ph_x64_rwdi.dll"))
|
||||
return nullptr;
|
||||
if (*reinterpret_cast<DWORD64**>(ptr) != Offsets::GetVT_SessionCooperativeDI())
|
||||
return nullptr;
|
||||
|
||||
return ptr;
|
||||
} __except (EXCEPTION_EXECUTE_HANDLER) {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include <pch.h>
|
||||
#include "..\offsets.h"
|
||||
#include "CoBaseCameraProxy.h"
|
||||
#include "FreeCamera.h"
|
||||
#include "TPPCameraDI.h"
|
||||
@@ -17,6 +18,8 @@ namespace GamePH {
|
||||
TPPCameraDI* ptr = pCoBaseCameraProxy->pTPPCameraDI;
|
||||
if (!Utils::Memory::IsValidPtrMod(ptr, "gamedll_ph_x64_rwdi.dll"))
|
||||
return nullptr;
|
||||
if (*reinterpret_cast<DWORD64**>(ptr) != Offsets::GetVT_TPPCameraDI())
|
||||
return nullptr;
|
||||
|
||||
return ptr;
|
||||
} __except (EXCEPTION_EXECUTE_HANDLER) {
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include "..\menu\camera.h"
|
||||
#include "..\menu\misc.h"
|
||||
#include "..\menu\player.h"
|
||||
#include "..\menu\teleport.h"
|
||||
#include "..\menu\world.h"
|
||||
#include "..\offsets.h"
|
||||
#include "FreeCamera.h"
|
||||
@@ -9,7 +10,8 @@
|
||||
#include "GameDI_PH2.h"
|
||||
#include "LevelDI.h"
|
||||
#include "PlayerHealthModule.h"
|
||||
#include "gen_TPPModel.h"
|
||||
#include "PlayerInfectionModule.h"
|
||||
#include "PlayerDI_PH.h"
|
||||
|
||||
namespace GamePH {
|
||||
namespace Hooks {
|
||||
@@ -18,11 +20,23 @@ namespace GamePH {
|
||||
static Utils::Hook::MHook<LPVOID, DWORD64(*)(DWORD64)> CreatePlayerHealthModuleHook{ "CreatePlayerHealthModule", &Offsets::Get_CreatePlayerHealthModule, &detourCreatePlayerHealthModule };
|
||||
|
||||
static DWORD64 detourCreatePlayerHealthModule(DWORD64 playerHealthModule) {
|
||||
PlayerHealthModule::pPlayerHealthModule = reinterpret_cast<PlayerHealthModule*>(playerHealthModule);
|
||||
PlayerHealthModule::playerHealthModulePtrList.emplace_back(reinterpret_cast<PlayerHealthModule*>(playerHealthModule));
|
||||
|
||||
return CreatePlayerHealthModuleHook.pOriginal(playerHealthModule);
|
||||
}
|
||||
#pragma endregion
|
||||
|
||||
#pragma region CreatePlayerInfectionModule
|
||||
static DWORD64 detourCreatePlayerInfectionModule(DWORD64 playerInfectionModule);
|
||||
static Utils::Hook::MHook<LPVOID, DWORD64(*)(DWORD64)> CreatePlayerInfectionModuleHook{ "CreatePlayerInfectionModule", &Offsets::Get_CreatePlayerInfectionModule, &detourCreatePlayerInfectionModule };
|
||||
|
||||
static DWORD64 detourCreatePlayerInfectionModule(DWORD64 playerInfectionModule) {
|
||||
PlayerInfectionModule::playerInfectionModulePtrList.emplace_back(reinterpret_cast<PlayerInfectionModule*>(playerInfectionModule));
|
||||
|
||||
return CreatePlayerInfectionModuleHook.pOriginal(playerInfectionModule);
|
||||
}
|
||||
#pragma endregion
|
||||
|
||||
#pragma region LifeSetHealth
|
||||
static void detourLifeSetHealth(float* pLifeHealth, float health);
|
||||
static Utils::Hook::MHook<LPVOID, void(*)(float*, float)> LifeSetHealthHook{ "LifeSetHealth", &Offsets::Get_LifeSetHealth, &detourLifeSetHealth };
|
||||
@@ -45,15 +59,45 @@ namespace GamePH {
|
||||
}
|
||||
#pragma endregion
|
||||
|
||||
#pragma region IsNotOutOfBounds
|
||||
static bool detourIsNotOutOfBounds(LPVOID pInstance, DWORD64 a2);
|
||||
static Utils::Hook::MHook<LPVOID, bool(*)(LPVOID, DWORD64)> IsNotOutOfBoundsHook{ "IsNotOutOfBounds", &Offsets::Get_IsNotOutOfBounds, &detourIsNotOutOfBounds };
|
||||
#pragma region PlayerHealthModuleKillPlayer
|
||||
static DWORD64 detourPlayerHealthModuleKillPlayer(LPVOID playerHealthModule);
|
||||
static Utils::Hook::MHook<LPVOID, DWORD64(*)(LPVOID)> PlayerHealthModuleKillPlayerHook{ "PlayerHealthModuleKillPlayer", &Offsets::Get_PlayerHealthModuleKillPlayer, &detourPlayerHealthModuleKillPlayer };
|
||||
|
||||
static bool detourIsNotOutOfBounds(LPVOID pInstance, DWORD64 a2) {
|
||||
static DWORD64 detourPlayerHealthModuleKillPlayer(LPVOID playerHealthModule) {
|
||||
if (!Menu::Player::godMode.GetValue() && !Menu::Camera::freeCam.GetValue())
|
||||
return PlayerHealthModuleKillPlayerHook.pOriginal(playerHealthModule);
|
||||
|
||||
PlayerHealthModule* pPlayerHealthModule = PlayerHealthModule::Get();
|
||||
if (!pPlayerHealthModule)
|
||||
return PlayerHealthModuleKillPlayerHook.pOriginal(playerHealthModule);
|
||||
if (pPlayerHealthModule == playerHealthModule)
|
||||
return 0;
|
||||
|
||||
return PlayerHealthModuleKillPlayerHook.pOriginal(playerHealthModule);
|
||||
}
|
||||
#pragma endregion
|
||||
|
||||
#pragma region IsNotOutOfMapBounds
|
||||
static bool detourIsNotOutOfMapBounds(LPVOID pInstance, DWORD64 a2);
|
||||
static Utils::Hook::MHook<LPVOID, bool(*)(LPVOID, DWORD64)> IsNotOutOfMapBoundsHook{ "IsNotOutOfMapBounds", &Offsets::Get_IsNotOutOfMapBounds, &detourIsNotOutOfMapBounds };
|
||||
|
||||
static bool detourIsNotOutOfMapBounds(LPVOID pInstance, DWORD64 a2) {
|
||||
if (Menu::Player::disableOutOfBoundsTimer.GetValue())
|
||||
return true;
|
||||
|
||||
return IsNotOutOfBoundsHook.pOriginal(pInstance, a2);
|
||||
return IsNotOutOfMapBoundsHook.pOriginal(pInstance, a2);
|
||||
}
|
||||
#pragma endregion
|
||||
|
||||
#pragma region IsNotOutOfMissionBounds
|
||||
static bool detourIsNotOutOfMissionBounds(LPVOID pInstance, DWORD64 a2);
|
||||
static Utils::Hook::MHook<LPVOID, bool(*)(LPVOID, DWORD64)> IsNotOutOfMissionBoundsHook{ "IsNotOutOfMissionBounds", &Offsets::Get_IsNotOutOfMissionBounds, &detourIsNotOutOfMissionBounds };
|
||||
|
||||
static bool detourIsNotOutOfMissionBounds(LPVOID pInstance, DWORD64 a2) {
|
||||
if (Menu::Player::disableOutOfBoundsTimer.GetValue())
|
||||
return true;
|
||||
|
||||
return IsNotOutOfMissionBoundsHook.pOriginal(pInstance, a2);
|
||||
}
|
||||
#pragma endregion
|
||||
|
||||
@@ -117,20 +161,20 @@ namespace GamePH {
|
||||
static Utils::Hook::MHook<LPVOID, void(*)(DWORD64, bool)> ShowTPPModelFunc3Hook{ "ShowTPPModelFunc3", &Offsets::Get_ShowTPPModelFunc3, &detourShowTPPModelFunc3 };
|
||||
|
||||
static void detourShowTPPModelFunc3(DWORD64 tppFunc2Addr, bool showTPPModel) {
|
||||
gen_TPPModel* pgen_TPPModel = gen_TPPModel::Get();
|
||||
if (!pgen_TPPModel) {
|
||||
PlayerDI_PH* pPlayerDI_PH = PlayerDI_PH::Get();
|
||||
if (!pPlayerDI_PH) {
|
||||
ShowTPPModelFunc3Hook.pOriginal(tppFunc2Addr, showTPPModel);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!showTPPModel && prevUseTPPModel) {
|
||||
pgen_TPPModel->enableTPPModel2 = true;
|
||||
pgen_TPPModel->enableTPPModel1 = true;
|
||||
pPlayerDI_PH->enableTPPModel2 = true;
|
||||
pPlayerDI_PH->enableTPPModel1 = true;
|
||||
}
|
||||
ShowTPPModelFunc3Hook.pOriginal(tppFunc2Addr, showTPPModel);
|
||||
if (showTPPModel && prevUseTPPModel) {
|
||||
pgen_TPPModel->enableTPPModel2 = false;
|
||||
pgen_TPPModel->enableTPPModel1 = false;
|
||||
pPlayerDI_PH->enableTPPModel2 = false;
|
||||
pPlayerDI_PH->enableTPPModel1 = false;
|
||||
} else
|
||||
prevUseTPPModel = showTPPModel;
|
||||
}
|
||||
@@ -171,12 +215,115 @@ namespace GamePH {
|
||||
static bool prevFreeCam = Menu::Camera::freeCam.GetPrevValue();
|
||||
prevFreeCam = Menu::Camera::freeCam.GetPrevValue();
|
||||
if (!Menu::Camera::freeCam.GetValue() && prevFreeCam) {
|
||||
Menu::Camera::freeCam.SetPrevValue(false);
|
||||
prevFreeCam = false;
|
||||
return 0;
|
||||
}
|
||||
if (Menu::Teleport::waypointIsSet && !*Menu::Teleport::waypointIsSet && Menu::Teleport::justTeleportedToWaypoint) {
|
||||
Menu::Teleport::justTeleportedToWaypoint = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (Menu::Player::godMode.GetValue())
|
||||
return 0;
|
||||
|
||||
return CalculateFallHeightHook.pOriginal(pInstance, height);
|
||||
}
|
||||
#pragma endregion
|
||||
|
||||
#pragma region CanUseGrappleHook
|
||||
static bool detourCanUseGrappleHook(LPVOID pInstance, bool a2);
|
||||
static Utils::Hook::MHook<LPVOID, bool(*)(LPVOID, bool)> CanUseGrappleHookHook{ "CanUseGrappleHook", &Offsets::Get_CanUseGrappleHook, &detourCanUseGrappleHook };
|
||||
|
||||
static bool detourCanUseGrappleHook(LPVOID pInstance, bool a2) {
|
||||
if (Menu::Player::allowGrappleHookInSafezone.GetValue())
|
||||
return true;
|
||||
|
||||
return CanUseGrappleHookHook.pOriginal(pInstance, a2);
|
||||
}
|
||||
#pragma endregion
|
||||
|
||||
#pragma region ReadPlayerJumpParams
|
||||
static DWORD64 detourReadPlayerJumpParams(DWORD64 a1, DWORD64 a2, DWORD64 a3, char a4, DWORD64* a5);
|
||||
static Utils::Hook::MHook<LPVOID, DWORD64(*)(DWORD64, DWORD64, DWORD64, char, DWORD64*)> ReadPlayerJumpParamsHook{ "ReadPlayerJumpParams", &Offsets::Get_ReadPlayerJumpParams, &detourReadPlayerJumpParams };
|
||||
|
||||
static DWORD64 detourReadPlayerJumpParams(DWORD64 a1, DWORD64 a2, DWORD64 a3, char a4, DWORD64* a5) {
|
||||
DWORD64 result = ReadPlayerJumpParamsHook.pOriginal(a1, a2, a3, a4, a5);
|
||||
|
||||
if (Menu::Player::disableAirControl.GetValue())
|
||||
*reinterpret_cast<bool*>(a1 + Offsets::Get_allowVelocityMod_offset()) = false;
|
||||
if (Menu::Camera::disableHeadCorrection.GetValue() || Menu::Camera::goProMode.GetValue())
|
||||
*reinterpret_cast<bool*>(a1 + Offsets::Get_disableHeadCorrection_offset()) = true;
|
||||
|
||||
return result;
|
||||
}
|
||||
#pragma endregion
|
||||
|
||||
#pragma region HandleInventoryItemsAmount
|
||||
static void detourHandleInventoryItemsAmount(int* pInventoryItem_0x10, UINT amount);
|
||||
static Utils::Hook::MHook<LPVOID, void(*)(int*, UINT)> HandleInventoryItemsAmountHook{ "HandleInventoryItemsAmount", &Offsets::Get_HandleInventoryItemsAmount, &detourHandleInventoryItemsAmount };
|
||||
|
||||
static void detourHandleInventoryItemsAmount(int* pInventoryItem_0x10, UINT amount) {
|
||||
int previousValue = *pInventoryItem_0x10;
|
||||
HandleInventoryItemsAmountHook.pOriginal(pInventoryItem_0x10, amount);
|
||||
if (!LevelDI::Get() || !LevelDI::Get()->IsLoaded())
|
||||
return;
|
||||
|
||||
if (*pInventoryItem_0x10 < previousValue && *pInventoryItem_0x10 == amount && Menu::Player::unlimitedItems.GetValue())
|
||||
*pInventoryItem_0x10 = previousValue;
|
||||
}
|
||||
#pragma endregion
|
||||
|
||||
#pragma region SetNewWaypointLocation
|
||||
static DWORD64 detourSetNewWaypointLocation(DWORD64 pLogicalPlayer, int a2, Vector3* newWaypointLoc);
|
||||
static Utils::Hook::MHook<LPVOID, DWORD64(*)(DWORD64, int, Vector3*)> SetNewWaypointLocationHook{ "SetNewWaypointLocation", &Offsets::Get_SetNewWaypointLocation, &detourSetNewWaypointLocation };
|
||||
|
||||
static DWORD64 detourSetNewWaypointLocation(DWORD64 pLogicalPlayer, int a2, Vector3* newWaypointLoc) {
|
||||
DWORD64 result = SetNewWaypointLocationHook.pOriginal(pLogicalPlayer, a2, newWaypointLoc);
|
||||
Menu::Teleport::waypointCoords = *newWaypointLoc;
|
||||
if (Offsets::Get_SetNewWaypointLocationWaypointIsSetBoolInstr()) {
|
||||
const DWORD offset = *Offsets::Get_SetNewWaypointLocationWaypointIsSetBoolInstr();
|
||||
Menu::Teleport::waypointIsSet = reinterpret_cast<bool*>(pLogicalPlayer + offset);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
#pragma endregion
|
||||
|
||||
/*#pragma region HandleHeadBob
|
||||
static bool isHandleHeadBobRunning = false;
|
||||
|
||||
static void detourHandleHeadBob(DWORD64 a1, DWORD64 a2, DWORD64 a3, DWORD64 a4);
|
||||
static Utils::Hook::MHook<LPVOID, void(*)(DWORD64, DWORD64, DWORD64, DWORD64)> HandleHeadBobHook{ "HandleHeadBob", &Offsets::Get_HandleHeadBob, &detourHandleHeadBob };
|
||||
|
||||
static void detourHandleHeadBob(DWORD64 a1, DWORD64 a2, DWORD64 a3, DWORD64 a4) {
|
||||
isHandleHeadBobRunning = true;
|
||||
HandleHeadBobHook.pOriginal(a1, a2, a3, a4);
|
||||
isHandleHeadBobRunning = false;
|
||||
}
|
||||
#pragma endregion
|
||||
|
||||
#pragma region SomeFloatCalcFunc
|
||||
static DWORD64 detourSomeFloatCalcFunc(float* a1, float* a2, float a3, DWORD64 a4, DWORD64 a5, DWORD64 a6);
|
||||
static Utils::Hook::MHook<LPVOID, DWORD64(*)(float*, float*, float, DWORD64, DWORD64, DWORD64)> SomeFloatCalcFuncHook{ "SomeFloatCalcFunc", &Offsets::Get_SomeFloatCalcFunc, &detourSomeFloatCalcFunc };
|
||||
|
||||
static DWORD64 detourSomeFloatCalcFunc(float* a1, float* a2, float a3, DWORD64 a4, DWORD64 a5, DWORD64 a6) {
|
||||
if (isHandleHeadBobRunning) {
|
||||
static int i = 1;
|
||||
if (*a1 < 0.002f && i >= 2 && i <= 3) {
|
||||
*a1 *= 2.0f;
|
||||
a3 *= 2.0f;
|
||||
}
|
||||
i++;
|
||||
if (i > 3)
|
||||
i = 1;
|
||||
}
|
||||
return SomeFloatCalcFuncHook.pOriginal(a1, a2, a3, a4, a5, a6);
|
||||
}
|
||||
#pragma endregion*/
|
||||
|
||||
#pragma region ByteHooks
|
||||
static unsigned char SaveGameCRCBoolCheckBytes[3] = { 0xB3, 0x01, 0x90 }; // mov bl, 01
|
||||
Utils::Hook::ByteHook<LPVOID> SaveGameCRCBoolCheckHook{ "SaveGameCRCBoolCheck", &Offsets::Get_SaveGameCRCBoolCheck, SaveGameCRCBoolCheckBytes, sizeof(SaveGameCRCBoolCheckBytes), &Menu::Misc::disableSavegameCRCCheck }; // and bl, dil
|
||||
#pragma endregion
|
||||
}
|
||||
}
|
||||
+3
-3
@@ -1,7 +1,7 @@
|
||||
#include <pch.h>
|
||||
#include "..\offsets.h"
|
||||
#include "GameDI_PH.h"
|
||||
#include "gen_TPPModel.h"
|
||||
#include "PlayerDI_PH.h"
|
||||
|
||||
namespace GamePH {
|
||||
const DWORD GetCurrentGameVersion() {
|
||||
@@ -59,8 +59,8 @@ namespace GamePH {
|
||||
void(*pShowTPPModelFunc3)(DWORD64 tppFunc2Addr, bool showTPPModel) = (decltype(pShowTPPModelFunc3))Offsets::Get_ShowTPPModelFunc3();
|
||||
if (!pShowTPPModelFunc3)
|
||||
return;
|
||||
gen_TPPModel* pgen_TPPModel = gen_TPPModel::Get();
|
||||
if (!pgen_TPPModel)
|
||||
PlayerDI_PH* pPlayerDI_PH = PlayerDI_PH::Get();
|
||||
if (!pPlayerDI_PH)
|
||||
return;
|
||||
|
||||
pShowTPPModelFunc3(tppFunc2Addr, showTPPModel);
|
||||
@@ -1,21 +0,0 @@
|
||||
#include <pch.h>
|
||||
#include "LocalClientDI.h"
|
||||
#include "gen_TPPModel.h"
|
||||
|
||||
namespace GamePH {
|
||||
gen_TPPModel* gen_TPPModel::Get() {
|
||||
__try {
|
||||
LocalClientDI* pLocalClientDI = LocalClientDI::Get();
|
||||
if (!pLocalClientDI)
|
||||
return nullptr;
|
||||
|
||||
gen_TPPModel* ptr = pLocalClientDI->pgen_TPPModel;
|
||||
if (!Utils::Memory::IsValidPtrMod(ptr, "gamedll_ph_x64_rwdi.dll"))
|
||||
return nullptr;
|
||||
|
||||
return ptr;
|
||||
} __except (EXCEPTION_EXECUTE_HANDLER) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
#pragma once
|
||||
#include "..\buffer.h"
|
||||
|
||||
namespace GamePH {
|
||||
class gen_TPPModel {
|
||||
public:
|
||||
union {
|
||||
buffer<0x2DB9, bool> enableTPPModel1;
|
||||
buffer<0x2DBA, bool> enableTPPModel2;
|
||||
};
|
||||
|
||||
static gen_TPPModel* Get();
|
||||
};
|
||||
}
|
||||
@@ -39,6 +39,13 @@ Vector3 Vector3::cross(const Vector3& v) const {
|
||||
X * v.Y - Y * v.X
|
||||
};
|
||||
}
|
||||
Vector3 Vector3::round() {
|
||||
return { std::roundf(X), std::roundf(Y), std::roundf(Z) };
|
||||
}
|
||||
Vector3 Vector3::round(int decimals) {
|
||||
float power = std::powf(10.0f, static_cast<float>(decimals));
|
||||
return { std::roundf(X * power) / power, std::roundf(Y * power) / power, std::roundf(Z * power) / power };
|
||||
}
|
||||
|
||||
bool Vector3::isDefault() const {
|
||||
return Utils::Values::are_samef(X, 0.0f) && Utils::Values::are_samef(Y, 0.0f) && Utils::Values::are_samef(Z, 0.0f);
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#pragma once
|
||||
struct Vector3 {
|
||||
float X, Y, Z;
|
||||
float X = 0.0f;
|
||||
float Y = 0.0f;
|
||||
float Z = 0.0f;
|
||||
|
||||
bool operator==(const Vector3& v) const;
|
||||
Vector3& operator+=(const Vector3& v);
|
||||
@@ -12,6 +14,8 @@ struct Vector3 {
|
||||
|
||||
Vector3 normalize();
|
||||
Vector3 cross(const Vector3& v) const;
|
||||
Vector3 round();
|
||||
Vector3 round(int decimals);
|
||||
|
||||
bool isDefault() const;
|
||||
};
|
||||
@@ -3,10 +3,16 @@
|
||||
|
||||
template<size_t size, typename T> class buffer {
|
||||
char buffer[size];
|
||||
T data;
|
||||
public:
|
||||
T data;
|
||||
|
||||
operator T() { return data; }
|
||||
T operator->() { return data; }
|
||||
|
||||
DWORD64 operator&(const DWORD64 other) const { return reinterpret_cast<DWORD64>(data) & other; }
|
||||
DWORD64 operator>>(const int shift) const { return reinterpret_cast<DWORD64>(data) >> shift; }
|
||||
DWORD64 operator<<(const int shift) const { return reinterpret_cast<DWORD64>(data) << shift; }
|
||||
|
||||
T& operator=(const T& other) { data = other; return data; }
|
||||
T& operator*=(const T& other) { data *= other; return data; }
|
||||
T operator*(const T& other) const { return data * other; }
|
||||
|
||||
@@ -0,0 +1,935 @@
|
||||
#include "memscan.h"
|
||||
|
||||
#include <memory.h> // memcmp
|
||||
#include <string.h> // strlen
|
||||
|
||||
/* Types */
|
||||
|
||||
typedef struct {
|
||||
/* example: {0x55, 0x8B, 0xEC} */
|
||||
const ms_ubyte_t* m_data;
|
||||
|
||||
/* the former will result in '3' */
|
||||
ms_usize_t m_size;
|
||||
|
||||
/* the n-th instance of a pattern within range, 0 - first */
|
||||
ms_usize_t m_match;
|
||||
} ms_bytes_t;
|
||||
|
||||
typedef struct {
|
||||
/* "55 8B EC" => ms_bytes_t({0x55, 0x8B, 0xEC}, 3, match)
|
||||
* must be null terminated */
|
||||
const char* m_data;
|
||||
|
||||
/* the n-th instance of a pattern within range, 0 - first */
|
||||
ms_usize_t m_match;
|
||||
} ms_bytes_str_t;
|
||||
|
||||
typedef struct {
|
||||
/* example: {0x8B, 0x0D} */
|
||||
const ms_ubyte_t* m_data;
|
||||
|
||||
/* the former will result in '3' */
|
||||
ms_usize_t m_size;
|
||||
|
||||
/* the n-th instance of a match within range, 0 - first */
|
||||
ms_usize_t m_match;
|
||||
|
||||
ms_follow_direction_t m_direction;
|
||||
} ms_find_bytes_t;
|
||||
|
||||
typedef struct {
|
||||
/* "8B 0C" => ms_find_bytes_t({0x8B, 0x0C}, 2, match, direction)
|
||||
* must be null terminated */
|
||||
const char* m_data;
|
||||
|
||||
/* the n-th instance of a match within range, 0 - first */
|
||||
ms_usize_t m_match;
|
||||
|
||||
ms_follow_direction_t m_direction;
|
||||
} ms_find_str_t;
|
||||
|
||||
typedef struct {
|
||||
/* numerical form of pointer to look for */
|
||||
ms_uptr_t m_pointer;
|
||||
|
||||
/* the n-th instance of a match within range, 0 - first */
|
||||
ms_usize_t m_match;
|
||||
|
||||
bool m_swap_endianness;
|
||||
} ms_xref_t;
|
||||
|
||||
typedef struct {
|
||||
/* the string to look for */
|
||||
const char* m_data;
|
||||
|
||||
/* string size */
|
||||
ms_usize_t m_size;
|
||||
|
||||
/* the n-th instance of the reversed endianness address to the first
|
||||
* character of the string, 0 - first */
|
||||
ms_usize_t m_match;
|
||||
} ms_string_xref_t;
|
||||
|
||||
typedef enum {
|
||||
/* won't be reached if MEMSCAN_UNSAFE_OPTIMIZATIONS are on */
|
||||
|
||||
MS_FOLLOW_STATUS_NO_VALID_FOLLOW_INFO = 0,
|
||||
|
||||
/* */
|
||||
|
||||
/* overbounds on start */
|
||||
MS_FOLLOW_STATUS_FAIL_LHS,
|
||||
|
||||
/* overbounds on end */
|
||||
MS_FOLLOW_STATUS_FAIL_RHS,
|
||||
|
||||
/* broke before reaching match */
|
||||
MS_FOLLOW_STATUS_INCOMPLETE,
|
||||
|
||||
/* follow has succeeded, state was set to OK */
|
||||
MS_FOLLOW_STATUS_OK
|
||||
} ms_follow_status_t;
|
||||
|
||||
typedef struct {
|
||||
ms_uptr_t m_address;
|
||||
ms_follow_status_t m_status;
|
||||
} ms_follow_t;
|
||||
|
||||
/* Methods */
|
||||
|
||||
/* Static */
|
||||
|
||||
static ms_follow_t
|
||||
follow_until(const ms_uptr_t copy, const ms_uptr_t start, const ms_uptr_t end,
|
||||
const ms_find_bytes_t* restrict find_bytes)
|
||||
{
|
||||
/* data */
|
||||
|
||||
ms_follow_t result = {0};
|
||||
|
||||
ms_uptr_t address = copy;
|
||||
|
||||
#if !MEMSCAN_UNSAFE_OPTIMIZATIONS
|
||||
if (find_bytes == NULL ||
|
||||
(find_bytes != NULL &&
|
||||
(find_bytes->m_data == NULL || find_bytes->m_size == 0))) {
|
||||
result.m_address = 0;
|
||||
result.m_status = MS_FOLLOW_STATUS_NO_VALID_FOLLOW_INFO;
|
||||
|
||||
goto return_label;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* the following will run at least once, so you can follow regardless of
|
||||
* current address. it will break upon a NULL address, or after the first
|
||||
* overbounds byte, or upon a match in memory. */
|
||||
|
||||
ms_usize_t match = MEMSCAN_FIRST_MATCH;
|
||||
|
||||
int status;
|
||||
|
||||
retry_label:
|
||||
status = memcmp((void*)address, find_bytes->m_data, find_bytes->m_size);
|
||||
|
||||
while ((void*)address != NULL && address >= (start - 1) &&
|
||||
address <= (end + 1) && status != 0) {
|
||||
address +=
|
||||
find_bytes->m_direction == MS_FOLLOW_DIRECTION_BACKWARDS ? -1 : 1;
|
||||
|
||||
status = memcmp((void*)address, find_bytes->m_data, find_bytes->m_size);
|
||||
}
|
||||
|
||||
result.m_address = address;
|
||||
|
||||
/* if the address is smaller than start, then it is overbounds on the lhs,
|
||||
* otherwise, if it is smaller than end, it is overbounds no the rhs,
|
||||
* otherwise, if status is != 0, it is OK, otherwise, it is an incomplete
|
||||
* follow */
|
||||
|
||||
result.m_status = (result.m_address < start
|
||||
? MS_FOLLOW_STATUS_FAIL_LHS
|
||||
: (result.m_address > end
|
||||
? MS_FOLLOW_STATUS_FAIL_RHS
|
||||
: (status != 0 ? MS_FOLLOW_STATUS_INCOMPLETE
|
||||
: MS_FOLLOW_STATUS_OK)));
|
||||
|
||||
/* verify match */
|
||||
|
||||
if (match != find_bytes->m_match &&
|
||||
result.m_status == MS_FOLLOW_STATUS_OK) {
|
||||
++match;
|
||||
address +=
|
||||
find_bytes->m_direction == MS_FOLLOW_DIRECTION_BACKWARDS ? -1 : 1;
|
||||
goto retry_label;
|
||||
}
|
||||
|
||||
return_label:
|
||||
return result;
|
||||
}
|
||||
|
||||
/* */
|
||||
|
||||
static ms_result_t
|
||||
memscan_find_pattern_bb_impl(const ms_uptr_t start, const ms_uptr_t end,
|
||||
const ms_bytes_t* restrict bytes,
|
||||
const ms_find_bytes_t* restrict find_bytes)
|
||||
{
|
||||
ms_result_t result = {0};
|
||||
|
||||
result.m_address = 0;
|
||||
|
||||
#if !MEMSCAN_UNSAFE_OPTIMIZATIONS
|
||||
if (bytes == NULL || (bytes && bytes->m_data == NULL)) {
|
||||
result.m_status = MS_RESULT_NO_VALID_BYTES_INFO;
|
||||
|
||||
goto return_label;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* data */
|
||||
|
||||
/* this value is meant to be used to deduce how many actual bytes were input
|
||||
* to the formation, scaling to every platform's sizeof(unsigned char) */
|
||||
|
||||
const ms_usize_t bytes_len = bytes->m_size / sizeof *bytes->m_data;
|
||||
|
||||
/* here, bytes->m_size is used because we're doing pointer arithmetic */
|
||||
|
||||
const ms_ubyte_t* finish = (ms_ubyte_t*)(end - bytes->m_size);
|
||||
|
||||
ms_usize_t match = MEMSCAN_FIRST_MATCH;
|
||||
|
||||
#if !MEMSCAN_UNSAFE_OPTIMIZATIONS
|
||||
if (start >= (ms_uptr_t)finish) {
|
||||
result.m_status = MS_RESULT_NO_VALID_SPAN;
|
||||
|
||||
goto return_label;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* loop over every byte from start to end */
|
||||
|
||||
for (ms_ubyte_t* current = (ms_ubyte_t*)start; current < finish;
|
||||
++current) {
|
||||
ms_result_status_t status = MS_RESULT_STATUS_FOUND;
|
||||
|
||||
/* run a scan from current byte to current byte + bytes_len to verify if
|
||||
* we have a match */
|
||||
|
||||
for (ms_usize_t walker = 0; walker < bytes_len; ++walker) {
|
||||
/* if the current byte at walker indice isn't equal to the current
|
||||
* signature byte if it isn't our wildcard */
|
||||
|
||||
if (current[walker] != bytes->m_data[walker] &&
|
||||
bytes->m_data[walker] != k_memscan_wildcard) {
|
||||
/* declare the state as not found for the current iteration
|
||||
* and go to the next one */
|
||||
|
||||
status = MS_RESULT_STATUS_NOT_FOUND;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* if the state wasn't altered (as in, the checks have passed and the
|
||||
* current byte matches our signature) */
|
||||
|
||||
if (status == MS_RESULT_STATUS_FOUND) {
|
||||
/* verify n-th match */
|
||||
|
||||
if (match != bytes->m_match) {
|
||||
++match;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* pass our address and status to result */
|
||||
|
||||
result.m_address = (ms_uptr_t)current;
|
||||
result.m_status = status;
|
||||
|
||||
/* attempt a follow */
|
||||
|
||||
const ms_follow_t follow =
|
||||
follow_until(result.m_address, start, end, find_bytes);
|
||||
|
||||
switch (follow.m_status) {
|
||||
case MS_FOLLOW_STATUS_OK: {
|
||||
/* change the result address to the follow result,
|
||||
* started from the original one */
|
||||
|
||||
result.m_address = follow.m_address;
|
||||
} break;
|
||||
|
||||
case MS_FOLLOW_STATUS_FAIL_LHS:
|
||||
case MS_FOLLOW_STATUS_FAIL_RHS: {
|
||||
/* this is prioritized over MS_FOLLOW_STATUS_INCOMPLETE */
|
||||
|
||||
/* deduce if it was either a left side overbounds
|
||||
* failure or right side overbounds failure for the
|
||||
* possibility of still allowing a result depending on
|
||||
* user response */
|
||||
|
||||
result.m_status =
|
||||
follow.m_status == MS_FOLLOW_STATUS_FAIL_LHS
|
||||
? MS_RESULT_STATUS_FOUND_FOLLOW_FAIL_LHS
|
||||
: MS_RESULT_STATUS_FOUND_FOLLOW_FAIL_RHS;
|
||||
} break;
|
||||
|
||||
case MS_FOLLOW_STATUS_INCOMPLETE: {
|
||||
/* a condition to break the follow was met before there was
|
||||
* a match in memory between the seeked byte-code and the
|
||||
* byte-code at from it's current address for the seeked
|
||||
* byte-code length */
|
||||
|
||||
result.m_status =
|
||||
MS_RESULT_STATUS_FOUND_FOLLOW_FAIL_INCOMPLETE;
|
||||
} break;
|
||||
}
|
||||
|
||||
goto return_label;
|
||||
}
|
||||
}
|
||||
|
||||
/* we haven't found an address for our signature, so we will set result
|
||||
* state to NOT FOUND */
|
||||
|
||||
result.m_status = MS_RESULT_STATUS_NOT_FOUND;
|
||||
|
||||
return_label:
|
||||
return result;
|
||||
}
|
||||
|
||||
/* */
|
||||
|
||||
static ms_result_t
|
||||
memscan_find_pattern_bs_impl(const ms_uptr_t start, const ms_uptr_t end,
|
||||
const ms_bytes_t* restrict bytes,
|
||||
const ms_find_str_t* restrict find_bytes)
|
||||
{
|
||||
ms_result_t result = {0};
|
||||
result.m_address = 0;
|
||||
|
||||
if (find_bytes == NULL)
|
||||
result = memscan_find_pattern_bb_impl(start, end, bytes, NULL);
|
||||
else {
|
||||
/* data */
|
||||
|
||||
ms_pattern_t pattern =
|
||||
util_build_pattern(find_bytes->m_data, strlen(find_bytes->m_data));
|
||||
|
||||
ms_find_bytes_t find_bytes_from_str = {0};
|
||||
find_bytes_from_str.m_data = pattern.m_data;
|
||||
find_bytes_from_str.m_size = pattern.m_size;
|
||||
find_bytes_from_str.m_match = find_bytes->m_match;
|
||||
find_bytes_from_str.m_direction = find_bytes->m_direction;
|
||||
|
||||
/* pass converted data to base implementation */
|
||||
|
||||
result = memscan_find_pattern_bb_impl(start, end, bytes,
|
||||
&find_bytes_from_str);
|
||||
|
||||
util_free_pattern(&pattern);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* */
|
||||
|
||||
static ms_result_t
|
||||
memscan_find_pattern_sb_impl(const ms_uptr_t start, const ms_uptr_t end,
|
||||
const ms_bytes_str_t* restrict bytes,
|
||||
const ms_find_bytes_t* restrict find_bytes)
|
||||
{
|
||||
ms_result_t result = {0};
|
||||
result.m_address = 0;
|
||||
|
||||
if (bytes == NULL || (bytes && bytes->m_data == NULL))
|
||||
result = memscan_find_pattern_bb_impl(start, end, NULL, find_bytes);
|
||||
else {
|
||||
/* data */
|
||||
|
||||
ms_pattern_t pattern =
|
||||
util_build_pattern(bytes->m_data, strlen(bytes->m_data));
|
||||
|
||||
ms_bytes_t bytes_from_str = {0};
|
||||
bytes_from_str.m_data = pattern.m_data;
|
||||
bytes_from_str.m_size = pattern.m_size;
|
||||
bytes_from_str.m_match = bytes->m_match;
|
||||
|
||||
/* pass converted data to base implementation */
|
||||
|
||||
result = memscan_find_pattern_bb_impl(start, end, &bytes_from_str,
|
||||
find_bytes);
|
||||
|
||||
util_free_pattern(&pattern);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* */
|
||||
|
||||
static ms_result_t
|
||||
memscan_find_pattern_ss_impl(const ms_uptr_t start, const ms_uptr_t end,
|
||||
const ms_bytes_str_t* restrict bytes,
|
||||
const ms_find_str_t* restrict find_bytes)
|
||||
{
|
||||
|
||||
ms_result_t result = {0};
|
||||
result.m_address = 0;
|
||||
|
||||
if (find_bytes == NULL)
|
||||
result = memscan_find_pattern_sb_impl(start, end, bytes, NULL);
|
||||
else {
|
||||
/* data */
|
||||
|
||||
ms_pattern_t find_pattern =
|
||||
util_build_pattern(find_bytes->m_data, strlen(find_bytes->m_data));
|
||||
|
||||
ms_find_bytes_t find_bytes_from_str = {0};
|
||||
find_bytes_from_str.m_data = find_pattern.m_data;
|
||||
find_bytes_from_str.m_size = find_pattern.m_size;
|
||||
find_bytes_from_str.m_match = find_bytes->m_match;
|
||||
find_bytes_from_str.m_direction = find_bytes->m_direction;
|
||||
|
||||
/* pass data to our string, bytes wrapper */
|
||||
|
||||
result = memscan_find_pattern_sb_impl(start, end, bytes,
|
||||
&find_bytes_from_str);
|
||||
|
||||
util_free_pattern(&find_pattern);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* */
|
||||
|
||||
static ms_result_t
|
||||
memscan_find_pattern_nfb_impl(const ms_uptr_t start, const ms_uptr_t end,
|
||||
const ms_bytes_t* restrict bytes)
|
||||
{
|
||||
/* pass data to our base implementation. the data being NULL
|
||||
* will prevent a follow from happening */
|
||||
|
||||
return memscan_find_pattern_bb_impl(start, end, bytes, NULL);
|
||||
}
|
||||
|
||||
/* */
|
||||
|
||||
static ms_result_t
|
||||
memscan_find_pattern_nfs_impl(const ms_uptr_t start, const ms_uptr_t end,
|
||||
const ms_bytes_str_t* restrict bytes)
|
||||
{
|
||||
/* pass data to our string, bytes wrapper. the data being NULL
|
||||
* will prevent a follow from happening */
|
||||
|
||||
return memscan_find_pattern_sb_impl(start, end, bytes, NULL);
|
||||
}
|
||||
|
||||
/* */
|
||||
|
||||
static ms_result_t
|
||||
memscan_find_xref_b_impl(const ms_uptr_t start, const ms_uptr_t end,
|
||||
const ms_xref_t* restrict xref,
|
||||
const ms_find_bytes_t* restrict find_bytes)
|
||||
{
|
||||
ms_result_t result = {0};
|
||||
|
||||
result.m_address = 0;
|
||||
|
||||
#if !MEMSCAN_UNSAFE_OPTIMIZATIONS
|
||||
if (xref == NULL /* data is handled in the pattern finder */) {
|
||||
result.m_status = MS_RESULT_NO_VALID_BYTES_INFO;
|
||||
goto return_label;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* data */
|
||||
|
||||
ms_bytes_t from_xref = {0};
|
||||
|
||||
from_xref.m_data =
|
||||
util_ptr_to_byteset(xref->m_pointer, xref->m_swap_endianness);
|
||||
from_xref.m_size = MEMSCAN_BYTESET_SIZE;
|
||||
from_xref.m_match = xref->m_match;
|
||||
|
||||
/* pass data to our no follow, bytes wrapper */
|
||||
|
||||
result = memscan_find_pattern_bb_impl(start, end, &from_xref, find_bytes);
|
||||
|
||||
return_label:
|
||||
return result;
|
||||
}
|
||||
|
||||
/* */
|
||||
|
||||
static ms_result_t
|
||||
memscan_find_xref_s_impl(const ms_uptr_t start, const ms_uptr_t end,
|
||||
const ms_xref_t* restrict xref,
|
||||
const ms_find_str_t* restrict find_bytes)
|
||||
{
|
||||
ms_result_t result = {0};
|
||||
result.m_address = 0;
|
||||
|
||||
if (find_bytes == NULL)
|
||||
result = memscan_find_xref_b_impl(start, end, xref, NULL);
|
||||
else {
|
||||
/* data */
|
||||
|
||||
ms_pattern_t pattern =
|
||||
util_build_pattern(find_bytes->m_data, strlen(find_bytes->m_data));
|
||||
|
||||
ms_find_bytes_t find_bytes_from_str = {0};
|
||||
find_bytes_from_str.m_data = pattern.m_data;
|
||||
find_bytes_from_str.m_size = pattern.m_size;
|
||||
find_bytes_from_str.m_match = find_bytes->m_match;
|
||||
find_bytes_from_str.m_direction = find_bytes->m_direction;
|
||||
|
||||
result =
|
||||
memscan_find_xref_b_impl(start, end, xref, &find_bytes_from_str);
|
||||
|
||||
util_free_pattern(&pattern);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* */
|
||||
|
||||
static ms_result_t
|
||||
memscan_find_xref_nf_impl(const ms_uptr_t start, const ms_uptr_t end,
|
||||
const ms_xref_t* restrict xref)
|
||||
{
|
||||
return memscan_find_xref_b_impl(start, end, xref, NULL);
|
||||
}
|
||||
|
||||
/* */
|
||||
|
||||
static ms_result_t
|
||||
memscan_find_string_b_impl(const ms_uptr_t start, const ms_uptr_t end,
|
||||
const ms_string_xref_t* restrict string,
|
||||
const ms_find_bytes_t* restrict find_bytes)
|
||||
{
|
||||
ms_result_t result = {0};
|
||||
|
||||
result.m_address = 0;
|
||||
|
||||
#if !MEMSCAN_UNSAFE_OPTIMIZATIONS
|
||||
if (string == NULL /* data is handled in the pattern finder */) {
|
||||
result.m_status = MS_RESULT_NO_VALID_BYTES_INFO;
|
||||
goto return_label;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* data */
|
||||
|
||||
ms_bytes_t bytes = {0};
|
||||
|
||||
bytes.m_data = (const ms_ubyte_t*)string->m_data;
|
||||
bytes.m_size = string->m_size;
|
||||
bytes.m_match = 0;
|
||||
|
||||
ms_result_t string_find = memscan_find_pattern_nfb_impl(start, end, &bytes);
|
||||
|
||||
if (string_find.m_status != MS_RESULT_STATUS_FOUND) {
|
||||
result.m_status = string_find.m_status;
|
||||
goto return_label;
|
||||
}
|
||||
|
||||
ms_xref_t xref = {0};
|
||||
|
||||
xref.m_pointer = string_find.m_address;
|
||||
xref.m_match = string->m_match;
|
||||
xref.m_swap_endianness = true;
|
||||
|
||||
result = memscan_find_xref_b_impl(start, end, &xref, find_bytes);
|
||||
|
||||
return_label:
|
||||
return result;
|
||||
}
|
||||
|
||||
static ms_result_t
|
||||
memscan_find_string_s_impl(const ms_uptr_t start, const ms_uptr_t end,
|
||||
const ms_string_xref_t* restrict string,
|
||||
const ms_find_str_t* restrict find_bytes)
|
||||
{
|
||||
ms_result_t result = {0};
|
||||
result.m_address = 0;
|
||||
|
||||
if (find_bytes == NULL)
|
||||
result = memscan_find_string_b_impl(start, end, string, NULL);
|
||||
else {
|
||||
/* data */
|
||||
|
||||
ms_pattern_t pattern =
|
||||
util_build_pattern(find_bytes->m_data, strlen(find_bytes->m_data));
|
||||
|
||||
ms_find_bytes_t find_bytes_from_str = {0};
|
||||
find_bytes_from_str.m_data = pattern.m_data;
|
||||
find_bytes_from_str.m_size = pattern.m_size;
|
||||
find_bytes_from_str.m_match = find_bytes->m_match;
|
||||
find_bytes_from_str.m_direction = find_bytes->m_direction;
|
||||
|
||||
result = memscan_find_string_b_impl(start, end, string,
|
||||
&find_bytes_from_str);
|
||||
|
||||
util_free_pattern(&pattern);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static ms_result_t
|
||||
memscan_find_string_nf_impl(const ms_uptr_t start, const ms_uptr_t end,
|
||||
const ms_string_xref_t* restrict string)
|
||||
{
|
||||
return memscan_find_string_b_impl(start, end, string, NULL);
|
||||
}
|
||||
|
||||
/* Prototype Bodies */
|
||||
|
||||
ms_result_t
|
||||
memscan_find_pattern_bb(const ms_uptr_t start, const ms_uptr_t end,
|
||||
const ms_ubyte_t* pattern,
|
||||
const ms_usize_t pattern_size,
|
||||
const ms_usize_t pattern_nth_match,
|
||||
const ms_ubyte_t* follow_pattern,
|
||||
const ms_usize_t follow_pattern_size,
|
||||
const ms_usize_t follow_nth_match,
|
||||
const ms_follow_direction_t follow_direction)
|
||||
{
|
||||
/* data */
|
||||
|
||||
ms_bytes_t bytes = {0};
|
||||
bytes.m_data = pattern;
|
||||
bytes.m_size = pattern_size;
|
||||
bytes.m_match = pattern_nth_match;
|
||||
|
||||
ms_find_bytes_t find = {0};
|
||||
find.m_data = follow_pattern;
|
||||
find.m_size = follow_pattern_size;
|
||||
find.m_match = follow_nth_match;
|
||||
find.m_direction = follow_direction;
|
||||
|
||||
/* pass structured data to manager */
|
||||
|
||||
return memscan_find_pattern_bb_impl(start, end, &bytes, &find);
|
||||
}
|
||||
|
||||
/* */
|
||||
|
||||
ms_result_t
|
||||
memscan_find_pattern_bs(const ms_uptr_t start, const ms_uptr_t end,
|
||||
const ms_ubyte_t* pattern,
|
||||
const ms_usize_t pattern_size,
|
||||
const ms_usize_t pattern_nth_match,
|
||||
const char* follow_pattern,
|
||||
const ms_usize_t follow_nth_match,
|
||||
const ms_follow_direction_t follow_direction)
|
||||
{
|
||||
/* data */
|
||||
|
||||
ms_bytes_t bytes = {0};
|
||||
bytes.m_data = pattern;
|
||||
bytes.m_size = pattern_size;
|
||||
bytes.m_match = pattern_nth_match;
|
||||
|
||||
ms_find_str_t find = {0};
|
||||
find.m_data = follow_pattern;
|
||||
find.m_match = follow_nth_match;
|
||||
find.m_direction = follow_direction;
|
||||
|
||||
/* pass structured data to manager */
|
||||
|
||||
return memscan_find_pattern_bs_impl(start, end, &bytes, &find);
|
||||
}
|
||||
|
||||
/* */
|
||||
|
||||
ms_result_t
|
||||
memscan_find_pattern_sb(const ms_uptr_t start, const ms_uptr_t end,
|
||||
const char* pattern, const ms_usize_t pattern_nth_match,
|
||||
const ms_ubyte_t* follow_pattern,
|
||||
const ms_usize_t follow_pattern_size,
|
||||
const ms_usize_t follow_nth_match,
|
||||
const ms_follow_direction_t follow_direction)
|
||||
{
|
||||
/* data */
|
||||
|
||||
ms_bytes_str_t bytes = {0};
|
||||
bytes.m_data = pattern;
|
||||
bytes.m_match = pattern_nth_match;
|
||||
|
||||
ms_find_bytes_t find = {0};
|
||||
find.m_data = follow_pattern;
|
||||
find.m_size = follow_pattern_size;
|
||||
find.m_match = follow_nth_match;
|
||||
find.m_direction = follow_direction;
|
||||
|
||||
/* pass structured data to manager */
|
||||
|
||||
return memscan_find_pattern_sb_impl(start, end, &bytes, &find);
|
||||
}
|
||||
|
||||
/* */
|
||||
|
||||
ms_result_t
|
||||
memscan_find_pattern_ss(const ms_uptr_t start, const ms_uptr_t end,
|
||||
const char* pattern, const ms_usize_t pattern_nth_match,
|
||||
const char* follow_pattern,
|
||||
const ms_usize_t follow_nth_match,
|
||||
const ms_follow_direction_t follow_direction)
|
||||
{
|
||||
/* data */
|
||||
|
||||
ms_bytes_str_t bytes = {0};
|
||||
bytes.m_data = pattern;
|
||||
bytes.m_match = pattern_nth_match;
|
||||
|
||||
ms_find_str_t find = {0};
|
||||
find.m_data = follow_pattern;
|
||||
find.m_match = follow_nth_match;
|
||||
find.m_direction = follow_direction;
|
||||
|
||||
/* pass structured data to manager */
|
||||
|
||||
return memscan_find_pattern_ss_impl(start, end, &bytes, &find);
|
||||
}
|
||||
|
||||
/* */
|
||||
|
||||
ms_result_t
|
||||
memscan_find_pattern_nfb(const ms_uptr_t start, const ms_uptr_t end,
|
||||
const ms_ubyte_t* pattern,
|
||||
const ms_usize_t pattern_size,
|
||||
const ms_usize_t pattern_nth_match)
|
||||
{
|
||||
/* data */
|
||||
|
||||
ms_bytes_t bytes = {0};
|
||||
bytes.m_data = pattern;
|
||||
bytes.m_size = pattern_size;
|
||||
bytes.m_match = pattern_nth_match;
|
||||
|
||||
/* pass structured data to manager */
|
||||
|
||||
return memscan_find_pattern_nfb_impl(start, end, &bytes);
|
||||
}
|
||||
|
||||
/* */
|
||||
|
||||
ms_result_t
|
||||
memscan_find_pattern_nfs(const ms_uptr_t start, const ms_uptr_t end,
|
||||
const char* pattern,
|
||||
const ms_usize_t pattern_nth_match)
|
||||
{
|
||||
/* data */
|
||||
|
||||
ms_bytes_str_t bytes = {0};
|
||||
bytes.m_data = pattern;
|
||||
bytes.m_match = pattern_nth_match;
|
||||
|
||||
/* pass structured data to manager */
|
||||
|
||||
return memscan_find_pattern_nfs_impl(start, end, &bytes);
|
||||
}
|
||||
|
||||
/* */
|
||||
|
||||
ms_result_t
|
||||
memscan_find_xref_b(const ms_uptr_t start, const ms_uptr_t end,
|
||||
const ms_uptr_t content, const ms_usize_t content_nth_match,
|
||||
bool swap_endianness, const ms_ubyte_t* follow_pattern,
|
||||
const ms_usize_t follow_pattern_size,
|
||||
const ms_usize_t follow_nth_match,
|
||||
const ms_follow_direction_t follow_direction)
|
||||
{
|
||||
/* data */
|
||||
|
||||
ms_xref_t xref = {0};
|
||||
|
||||
xref.m_pointer = content;
|
||||
xref.m_match = content_nth_match;
|
||||
xref.m_swap_endianness = swap_endianness;
|
||||
|
||||
ms_find_bytes_t find_bytes = {0};
|
||||
|
||||
find_bytes.m_data = follow_pattern;
|
||||
find_bytes.m_size = follow_pattern_size;
|
||||
find_bytes.m_match = follow_nth_match;
|
||||
find_bytes.m_direction = follow_direction;
|
||||
|
||||
/* pass structured data to manager */
|
||||
|
||||
return memscan_find_xref_b_impl(start, end, &xref, &find_bytes);
|
||||
}
|
||||
|
||||
/* */
|
||||
|
||||
ms_result_t
|
||||
memscan_find_xref_at_b(const ms_uptr_t start, const ms_uptr_t end,
|
||||
const ms_uptr_t address, const ms_usize_t nth_match,
|
||||
bool swap_endianness, const ms_ubyte_t* follow_pattern,
|
||||
const ms_usize_t follow_pattern_size,
|
||||
const ms_usize_t follow_nth_match,
|
||||
const ms_follow_direction_t follow_direction)
|
||||
{
|
||||
return memscan_find_xref_b(start, end, *(ms_uptr_t*)address, nth_match,
|
||||
swap_endianness, follow_pattern,
|
||||
follow_pattern_size, follow_nth_match,
|
||||
follow_direction);
|
||||
}
|
||||
|
||||
/* */
|
||||
|
||||
ms_result_t
|
||||
memscan_find_xref_s(const ms_uptr_t start, const ms_uptr_t end,
|
||||
const ms_uptr_t content, const ms_usize_t content_nth_match,
|
||||
bool swap_endianness, const char* follow_pattern,
|
||||
const ms_usize_t follow_nth_match,
|
||||
const ms_follow_direction_t follow_direction)
|
||||
{
|
||||
/* data */
|
||||
|
||||
ms_xref_t xref = {0};
|
||||
|
||||
xref.m_pointer = content;
|
||||
xref.m_match = content_nth_match;
|
||||
xref.m_swap_endianness = swap_endianness;
|
||||
|
||||
ms_find_str_t find = {0};
|
||||
|
||||
find.m_data = follow_pattern;
|
||||
find.m_match = follow_nth_match;
|
||||
find.m_direction = follow_direction;
|
||||
|
||||
/* pass structured data to manager */
|
||||
|
||||
return memscan_find_xref_s_impl(start, end, &xref, &find);
|
||||
}
|
||||
|
||||
/* */
|
||||
|
||||
ms_result_t
|
||||
memscan_find_xref_at_s(const ms_uptr_t start, const ms_uptr_t end,
|
||||
const ms_uptr_t address, const ms_usize_t nth_match,
|
||||
bool swap_endianness, const char* follow_pattern,
|
||||
const ms_usize_t follow_nth_match,
|
||||
const ms_follow_direction_t follow_direction)
|
||||
{
|
||||
return memscan_find_xref_s(start, end, *(ms_uptr_t*)address, nth_match,
|
||||
swap_endianness, follow_pattern,
|
||||
follow_nth_match, follow_direction);
|
||||
}
|
||||
|
||||
/* */
|
||||
|
||||
ms_result_t
|
||||
memscan_find_xref_nf(const ms_uptr_t start, const ms_uptr_t end,
|
||||
const ms_uptr_t content,
|
||||
const ms_usize_t content_nth_match, bool swap_endianness)
|
||||
{
|
||||
/* data */
|
||||
|
||||
ms_xref_t xref = {0};
|
||||
|
||||
xref.m_pointer = content;
|
||||
xref.m_match = content_nth_match;
|
||||
xref.m_swap_endianness = swap_endianness;
|
||||
|
||||
/* pass structured data to manager */
|
||||
|
||||
return memscan_find_xref_nf_impl(start, end, &xref);
|
||||
}
|
||||
|
||||
/* */
|
||||
|
||||
ms_result_t
|
||||
memscan_find_xref_at_nf(const ms_uptr_t start, const ms_uptr_t end,
|
||||
const ms_uptr_t address, const ms_usize_t nth_match,
|
||||
bool swap_endianness)
|
||||
{
|
||||
return memscan_find_xref_nf(start, end, *(ms_uptr_t*)address, nth_match,
|
||||
swap_endianness);
|
||||
}
|
||||
|
||||
/* */
|
||||
|
||||
extern ms_result_t
|
||||
memscan_find_string_b(const ms_uptr_t start, const ms_uptr_t end,
|
||||
const char* text, const ms_usize_t text_size,
|
||||
const ms_usize_t nth_match,
|
||||
const ms_ubyte_t* follow_pattern,
|
||||
const ms_usize_t follow_pattern_size,
|
||||
const ms_usize_t follow_nth_match,
|
||||
const ms_follow_direction_t follow_direction)
|
||||
{
|
||||
/* data */
|
||||
|
||||
ms_string_xref_t xref = {0};
|
||||
|
||||
xref.m_data = text;
|
||||
xref.m_size = text_size;
|
||||
xref.m_match = nth_match;
|
||||
|
||||
ms_find_bytes_t find_bytes = {0};
|
||||
|
||||
find_bytes.m_data = follow_pattern;
|
||||
find_bytes.m_size = follow_pattern_size;
|
||||
find_bytes.m_match = follow_nth_match;
|
||||
find_bytes.m_direction = follow_direction;
|
||||
|
||||
/* pass structured data to manager */
|
||||
|
||||
return memscan_find_string_b_impl(start, end, &xref, &find_bytes);
|
||||
}
|
||||
|
||||
/* */
|
||||
|
||||
ms_result_t
|
||||
memscan_find_string_s(const ms_uptr_t start, const ms_uptr_t end,
|
||||
const char* text, const ms_usize_t text_size,
|
||||
const ms_usize_t nth_match, const char* follow_pattern,
|
||||
const ms_usize_t follow_nth_match,
|
||||
const ms_follow_direction_t follow_direction)
|
||||
{
|
||||
/* data */
|
||||
|
||||
ms_string_xref_t xref = {0};
|
||||
|
||||
xref.m_data = text;
|
||||
xref.m_size = text_size;
|
||||
xref.m_match = nth_match;
|
||||
|
||||
ms_find_str_t find = {0};
|
||||
|
||||
find.m_data = follow_pattern;
|
||||
find.m_match = follow_nth_match;
|
||||
find.m_direction = follow_direction;
|
||||
|
||||
/* pass structured data to manager */
|
||||
|
||||
return memscan_find_string_s_impl(start, end, &xref, &find);
|
||||
}
|
||||
|
||||
/* */
|
||||
|
||||
ms_result_t
|
||||
memscan_find_string_nf(const ms_uptr_t start, const ms_uptr_t end,
|
||||
const char* text, const ms_usize_t text_size,
|
||||
const ms_usize_t nth_match)
|
||||
{
|
||||
/* data */
|
||||
|
||||
ms_string_xref_t xref = {0};
|
||||
|
||||
xref.m_data = text;
|
||||
xref.m_size = text_size;
|
||||
xref.m_match = nth_match;
|
||||
|
||||
/* pass structured data to manager */
|
||||
|
||||
return memscan_find_string_nf_impl(start, end, &xref);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,102 @@
|
||||
#include "util.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
ms_pattern_t
|
||||
util_build_pattern(const char* data, const ms_usize_t data_size)
|
||||
{
|
||||
ms_pattern_t result = {0};
|
||||
|
||||
result.m_data = NULL;
|
||||
result.m_size = 0;
|
||||
|
||||
#if !UTIL_UNSAFE_OPTIMIZATIONS
|
||||
if (data == NULL) {
|
||||
result.m_status = MS_BUILD_STATUS_NO_DATA;
|
||||
|
||||
goto leave;
|
||||
}
|
||||
#endif
|
||||
|
||||
size_t len = data_size;
|
||||
|
||||
#if !UTIL_UNSAFE_OPTIMIZATIONS
|
||||
if (len == 0) {
|
||||
result.m_status = MS_BUILD_STATUS_SHORT_DATA;
|
||||
goto leave;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* data */
|
||||
|
||||
char* start = (char*)data;
|
||||
char* end = (char*)(data + len);
|
||||
|
||||
/* precompute allocation size */
|
||||
|
||||
ms_usize_t size = 0;
|
||||
|
||||
for (char* current = start; current < end; ++current)
|
||||
++size;
|
||||
|
||||
ms_ubyte_t* bytes = (ms_ubyte_t*)malloc(size * sizeof *bytes);
|
||||
|
||||
/* prefetched */
|
||||
|
||||
ms_usize_t indice = 0;
|
||||
|
||||
for (char* current = start; current < end; ++current) {
|
||||
/* hex substring conversion */
|
||||
|
||||
bytes[indice++] = (ms_ubyte_t)strtoul(current, ¤t, 16);
|
||||
}
|
||||
|
||||
result.m_data = bytes;
|
||||
result.m_size = indice;
|
||||
result.m_status = MS_BUILD_STATUS_OK;
|
||||
|
||||
leave:
|
||||
return result;
|
||||
}
|
||||
|
||||
/* */
|
||||
|
||||
ms_free_t
|
||||
util_free_pattern(ms_pattern_t* pattern)
|
||||
{
|
||||
#if !UTIL_UNSAFE_OPTIMIZATIONS
|
||||
if (pattern == NULL) {
|
||||
return MS_FREE_NO;
|
||||
}
|
||||
#endif
|
||||
|
||||
ms_free_t result = MS_FREE_NO;
|
||||
|
||||
if (pattern->m_status == MS_BUILD_STATUS_OK) {
|
||||
free(pattern->m_data);
|
||||
pattern->m_data = NULL;
|
||||
|
||||
result = MS_FREE_YES;
|
||||
}
|
||||
|
||||
pattern->m_size = 0;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
ms_ubyte_t*
|
||||
util_ptr_to_byteset(const ms_uptr_t num, bool swap_endianness)
|
||||
{
|
||||
/* data */
|
||||
|
||||
static ms_ubyte_t bytes[MEMSCAN_BYTESET_SIZE] = {0};
|
||||
|
||||
for (ms_usize_t i = 0; i < MEMSCAN_BYTESET_SIZE; ++i) {
|
||||
/* shift formation to get current indice */
|
||||
|
||||
bytes[swap_endianness ? i : MEMSCAN_BYTESET_SIZE - i - 1] =
|
||||
(ms_ubyte_t)(num >> (i * CHAR_BIT));
|
||||
}
|
||||
|
||||
return bytes;
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
#pragma once
|
||||
|
||||
/* Includes */
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/* Types */
|
||||
|
||||
typedef uint8_t ms_ubyte_t;
|
||||
typedef uintptr_t ms_uptr_t;
|
||||
typedef size_t ms_usize_t;
|
||||
|
||||
/* Extern */
|
||||
|
||||
#if __cplusplus
|
||||
#define MEMSCAN_EXTERN extern "C"
|
||||
#else
|
||||
#define MEMSCAN_EXTERN extern
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
/* nothing to free, or there's a condition preventing the process */
|
||||
MS_FREE_NO = 0,
|
||||
|
||||
/* the data was found present and then freed */
|
||||
MS_FREE_YES
|
||||
} ms_free_t;
|
||||
|
||||
typedef enum {
|
||||
/* won't be reached unless UTIL_UNSAFE_OPTIMIZATIONS is off */
|
||||
|
||||
/* passed data was NULL */
|
||||
MS_BUILD_STATUS_NO_DATA = 0,
|
||||
|
||||
/* data len was 0 */
|
||||
MS_BUILD_STATUS_SHORT_DATA,
|
||||
|
||||
/* */
|
||||
|
||||
/* generation has succeeded, status was set to OK */
|
||||
MS_BUILD_STATUS_OK
|
||||
} ms_build_status_t;
|
||||
|
||||
typedef struct {
|
||||
ms_ubyte_t* m_data;
|
||||
ms_usize_t m_size;
|
||||
ms_build_status_t m_status;
|
||||
} ms_pattern_t;
|
||||
|
||||
/* Methods */
|
||||
|
||||
/**
|
||||
* @brief Generate byte code array from byte-code style string
|
||||
*
|
||||
* @param data Example: "AA BB CC DD EE FF", equivalent to
|
||||
* (ms_ubyte_t*)"\xAA\xBB\xCC\xDD\xEE\xFF"
|
||||
* @param data_size Size of 'data'
|
||||
* @return Refer to ms_pattern_t for documentation
|
||||
*/
|
||||
MEMSCAN_EXTERN ms_pattern_t
|
||||
util_build_pattern(const char* data, const ms_usize_t data_size);
|
||||
|
||||
/**
|
||||
* @brief Deallocate pattern array after usage
|
||||
*
|
||||
* @param pattern Reference to the pattern construct
|
||||
* @return Refer to ms_free_t for documentation
|
||||
*/
|
||||
MEMSCAN_EXTERN ms_free_t
|
||||
util_free_pattern(ms_pattern_t* pattern);
|
||||
|
||||
/**
|
||||
* @brief Convert pointer in numerical form to byteset of MEMSCAN_BYTESET_SIZE
|
||||
* bytes
|
||||
*
|
||||
* @param num Value to convert
|
||||
* @param swap_endianness Whether to swap endianness or not
|
||||
* @return Value as a MEMSCAN_BYTESET_SIZE bytes array
|
||||
*/
|
||||
MEMSCAN_EXTERN ms_ubyte_t*
|
||||
util_ptr_to_byteset(const ms_uptr_t num, bool swap_endianness);
|
||||
|
||||
/* Constants */
|
||||
|
||||
#define MEMSCAN_BYTESET_SIZE (sizeof(ms_uptr_t) / sizeof(ms_ubyte_t))
|
||||
#define MEMSCAN_POINTER_BITS (sizeof(ms_uptr_t) * CHAR_BIT)
|
||||
@@ -5,9 +5,9 @@
|
||||
#include "..\game\GamePH\FreeCamera.h"
|
||||
#include "..\game\GamePH\GameDI_PH.h"
|
||||
#include "..\game\GamePH\LevelDI.h"
|
||||
#include "..\game\GamePH\Other.h"
|
||||
#include "..\game\GamePH\PlayerVariables.h"
|
||||
#include "..\game\GamePH\gen_TPPModel.h"
|
||||
#include "..\game\GamePH\PlayerDI_PH.h"
|
||||
#include "..\game\GamePH\gameph_misc.h"
|
||||
#include "..\offsets.h"
|
||||
#include "camera.h"
|
||||
#include "menu.h"
|
||||
@@ -28,18 +28,45 @@ namespace Menu {
|
||||
float tpHeightAbovePlayer = 1.35f;
|
||||
float tpHorizontalDistanceFromPlayer = 0.0f;
|
||||
|
||||
KeyBindOption disablePhotoModeLimits{ VK_NONE };
|
||||
float lensDistortion = 20.0f;
|
||||
static float altLensDistortion = 20.0f;
|
||||
KeyBindOption goProMode{ VK_NONE };
|
||||
KeyBindOption disableSafezoneFOVReduction{ VK_NONE };
|
||||
KeyBindOption disablePhotoModeLimits{ VK_NONE };
|
||||
KeyBindOption disableHeadCorrection{ VK_NONE };
|
||||
|
||||
static constexpr int baseFOV = 57;
|
||||
static constexpr float baseSafezoneFOVReduction = -10.0f;
|
||||
static constexpr float baseSprintHeadCorrectionFactor = 0.55f;
|
||||
|
||||
static void UpdateFOV() {
|
||||
if (menuToggle.GetValue())
|
||||
GamePH::LevelDI* iLevel = GamePH::LevelDI::Get();
|
||||
Engine::CBaseCamera* viewCam = nullptr;
|
||||
if (iLevel)
|
||||
viewCam = reinterpret_cast<Engine::CBaseCamera*>(iLevel->GetViewCamera());
|
||||
|
||||
static int previousFOV = FOV;
|
||||
|
||||
if (goProMode.GetValue()) {
|
||||
if (goProMode.HasChangedTo(true)) {
|
||||
previousFOV = FOV;
|
||||
goProMode.SetPrevValue(true);
|
||||
}
|
||||
|
||||
if (iLevel && viewCam)
|
||||
viewCam->SetFOV(110.0f);
|
||||
FOV = 110;
|
||||
return;
|
||||
} else if (goProMode.HasChangedTo(false)) {
|
||||
FOV = previousFOV;
|
||||
goProMode.SetPrevValue(false);
|
||||
|
||||
if (iLevel && viewCam)
|
||||
viewCam->SetFOV(static_cast<float>(FOV));
|
||||
}
|
||||
|
||||
Engine::CVideoSettings* videoSettings = Engine::CVideoSettings::Get();
|
||||
if (!videoSettings)
|
||||
if (!videoSettings || goProMode.GetValue() || menuToggle.GetValue())
|
||||
return;
|
||||
|
||||
FOV = static_cast<int>(videoSettings->extraFOV) + baseFOV;
|
||||
@@ -122,8 +149,8 @@ namespace Menu {
|
||||
if (!iLevel || !iLevel->IsLoaded())
|
||||
return;
|
||||
|
||||
GamePH::gen_TPPModel* pgen_TPPModel = GamePH::gen_TPPModel::Get();
|
||||
if (pgen_TPPModel) {
|
||||
GamePH::PlayerDI_PH* pPlayerDI_PH = GamePH::PlayerDI_PH::Get();
|
||||
if (pPlayerDI_PH) {
|
||||
if (Menu::Camera::freeCam.GetValue() && !iLevel->IsTimerFrozen())
|
||||
GamePH::ShowTPPModel(true);
|
||||
else if (Menu::Camera::freeCam.GetValue() && iLevel->IsTimerFrozen() && !photoMode.GetValue())
|
||||
@@ -138,15 +165,40 @@ namespace Menu {
|
||||
if (!GamePH::PlayerVariables::gotPlayerVars)
|
||||
return;
|
||||
|
||||
GamePH::PlayerVariables::ManagePlayerVarOption("CameraDefaultFOVReduction", 0.0f, baseSafezoneFOVReduction, &disableSafezoneFOVReduction);
|
||||
GamePH::PlayerVariables::ManagePlayerVarOption("CameraDefaultFOVReduction", 0.0f, baseSafezoneFOVReduction, &disableSafezoneFOVReduction, true);
|
||||
|
||||
static float prevLensDistortion = lensDistortion;
|
||||
static bool lensDistortionJustEnabled = false;
|
||||
if (goProMode.GetValue()) {
|
||||
if (!lensDistortionJustEnabled) {
|
||||
prevLensDistortion = lensDistortion;
|
||||
lensDistortionJustEnabled = true;
|
||||
}
|
||||
altLensDistortion = 100.0f;
|
||||
} else if (lensDistortionJustEnabled) {
|
||||
altLensDistortion = prevLensDistortion;
|
||||
lensDistortionJustEnabled = false;
|
||||
}
|
||||
GamePH::PlayerVariables::ChangePlayerVar("FOVCorrection", goProMode.GetValue() ? (altLensDistortion / 100.0f) : (lensDistortion / 100.0f));
|
||||
|
||||
GamePH::PlayerVariables::ManagePlayerVarOption("SprintHeadCorrectionFactor", 0.0f, baseSprintHeadCorrectionFactor, goProMode.GetValue() ? &goProMode : &disableHeadCorrection, true);
|
||||
}
|
||||
static void UpdateDisabledOptions() {
|
||||
GamePH::LevelDI* iLevel = GamePH::LevelDI::Get();
|
||||
freeCam.SetChangesAreDisabled(!iLevel || !iLevel->IsLoaded() || photoMode.GetValue());
|
||||
teleportPlayerToCamera.SetChangesAreDisabled(!iLevel || !iLevel->IsLoaded());
|
||||
thirdPersonCamera.SetChangesAreDisabled(freeCam.GetValue() || photoMode.GetValue());
|
||||
tpUseTPPModel.SetChangesAreDisabled(freeCam.GetValue() || photoMode.GetValue());
|
||||
}
|
||||
static void HandleToggles() {
|
||||
if (goProMode.HasChanged()) {
|
||||
goProMode.SetPrevValue(goProMode.GetValue());
|
||||
GamePH::ReloadJumps();
|
||||
}
|
||||
if (disableHeadCorrection.HasChanged()) {
|
||||
disableHeadCorrection.SetPrevValue(disableHeadCorrection.GetValue());
|
||||
GamePH::ReloadJumps();
|
||||
}
|
||||
}
|
||||
|
||||
Tab Tab::instance{};
|
||||
void Tab::Update() {
|
||||
@@ -155,26 +207,29 @@ namespace Menu {
|
||||
UpdateTPPModel();
|
||||
UpdatePlayerVars();
|
||||
UpdateDisabledOptions();
|
||||
HandleToggles();
|
||||
}
|
||||
void Tab::Render() {
|
||||
ImGui::SeparatorText("Free Camera");
|
||||
ImGui::BeginDisabled(freeCam.GetChangesAreDisabled() || photoMode.GetValue()); {
|
||||
ImGui::CheckboxHotkey("Enabled##FreeCam", &freeCam);
|
||||
ImGui::CheckboxHotkey("Enabled##FreeCam", &freeCam, "Enables free camera which allows you to travel anywhere with the camera");
|
||||
ImGui::EndDisabled();
|
||||
}
|
||||
ImGui::SameLine();
|
||||
ImGui::BeginDisabled(teleportPlayerToCamera.GetChangesAreDisabled()); {
|
||||
ImGui::CheckboxHotkey("Teleport Player to Camera", &teleportPlayerToCamera, "Teleports the player to the camera while Free Camera is activated");
|
||||
ImGui::EndDisabled();
|
||||
}
|
||||
ImGui::SliderFloat("Speed##FreeCam", &freeCamSpeed, 0.1f, 200.0f, "%.2fx", ImGuiSliderFlags_AlwaysClamp);
|
||||
ImGui::BeginDisabled(teleportPlayerToCamera.GetChangesAreDisabled()); {
|
||||
ImGui::CheckboxHotkey("Teleport Player to Camera", &teleportPlayerToCamera);
|
||||
ImGui::EndDisabled();
|
||||
}
|
||||
|
||||
ImGui::SeparatorText("Third Person Camera");
|
||||
ImGui::BeginDisabled(thirdPersonCamera.GetChangesAreDisabled()); {
|
||||
ImGui::CheckboxHotkey("Enabled##ThirdPerson", &thirdPersonCamera);
|
||||
ImGui::CheckboxHotkey("Enabled##ThirdPerson", &thirdPersonCamera, "Enables the third person camera");
|
||||
ImGui::EndDisabled();
|
||||
}
|
||||
ImGui::SameLine();
|
||||
ImGui::BeginDisabled(tpUseTPPModel.GetChangesAreDisabled()); {
|
||||
ImGui::CheckboxHotkey("Use Third Person Player (TPP) Model", &tpUseTPPModel);
|
||||
ImGui::CheckboxHotkey("Use Third Person Player (TPP) Model", &tpUseTPPModel, "Uses Aiden's TPP (Third Person Player) model while the third person camera is enabled");
|
||||
ImGui::EndDisabled();
|
||||
}
|
||||
ImGui::SliderFloat("Distance behind player", &tpDistanceBehindPlayer, 1.0f, 10.0f, "%.2fm");
|
||||
@@ -183,15 +238,27 @@ namespace Menu {
|
||||
|
||||
ImGui::SeparatorText("Misc");
|
||||
Engine::CVideoSettings* pCVideoSettings = Engine::CVideoSettings::Get();
|
||||
ImGui::BeginDisabled(!pCVideoSettings); {
|
||||
if (ImGui::SliderInt("FOV", &FOV, 20, 160) && pCVideoSettings)
|
||||
ImGui::BeginDisabled(!pCVideoSettings || goProMode.GetValue()); {
|
||||
if (ImGui::SliderInt("FOV", "Camera Field of View", &FOV, 20, 160) && pCVideoSettings)
|
||||
pCVideoSettings->extraFOV = static_cast<float>(FOV - baseFOV);
|
||||
else if (pCVideoSettings)
|
||||
else if (pCVideoSettings && !goProMode.GetValue()) {
|
||||
FOV = static_cast<int>(pCVideoSettings->extraFOV) + baseFOV;
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
}
|
||||
ImGui::CheckboxHotkey("Disable Photo Mode Limits", &disablePhotoModeLimits);
|
||||
ImGui::CheckboxHotkey("Disable Safezone FOV Reduction", &disableSafezoneFOVReduction);
|
||||
ImGui::BeginDisabled(goProMode.GetValue()); {
|
||||
ImGui::SliderFloat("Lens Distortion", "Default game value is 20%", goProMode.GetValue() ? &altLensDistortion : &lensDistortion, 0.0f, 100.0f, "%.1f%%");
|
||||
ImGui::EndDisabled();
|
||||
}
|
||||
ImGui::CheckboxHotkey("GoPro Mode *", &goProMode, "Makes the camera behave similar to a GoPro mounted on the forehead");
|
||||
ImGui::SameLine();
|
||||
ImGui::CheckboxHotkey("Disable Safezone FOV Reduction", &disableSafezoneFOVReduction, "Disables the FOV reduction that happens while you're in a safezone");
|
||||
ImGui::CheckboxHotkey("Disable Photo Mode Limits", &disablePhotoModeLimits, "Disables the invisible box while in Photo Mode");
|
||||
ImGui::SameLine();
|
||||
ImGui::CheckboxHotkey("Disable Head Correction", &disableHeadCorrection, "Disables centering of the player's hands to the center of the camera");
|
||||
|
||||
ImGui::Separator();
|
||||
ImGui::TextColored(ImGui::ColorConvertU32ToFloat4(IM_COL32(200, 0, 0, 255)), "* GoPro Mode is best used with Head Bob Reduction set to 0 and Player FOV\nCorrection set to 0 in game options");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -18,12 +18,15 @@ namespace Menu {
|
||||
extern float tpHeightAbovePlayer;
|
||||
extern float tpHorizontalDistanceFromPlayer;
|
||||
|
||||
extern KeyBindOption disablePhotoModeLimits;
|
||||
extern float lensDistortion;
|
||||
extern KeyBindOption goProMode;
|
||||
extern KeyBindOption disableSafezoneFOVReduction;
|
||||
extern KeyBindOption disablePhotoModeLimits;
|
||||
extern KeyBindOption disableHeadCorrection;
|
||||
|
||||
class Tab : MenuTab {
|
||||
public:
|
||||
Tab() : MenuTab("Camera", 1) {}
|
||||
Tab() : MenuTab("Camera", 2) {}
|
||||
void Update() override;
|
||||
void Render() override;
|
||||
|
||||
|
||||
@@ -10,13 +10,11 @@
|
||||
#include "..\game\GamePH\LogicalPlayer.h"
|
||||
#include "..\game\GamePH\PlayerDI_PH.h"
|
||||
#include "..\game\GamePH\PlayerHealthModule.h"
|
||||
#include "..\game\GamePH\PlayerObjProperties.h"
|
||||
#include "..\game\GamePH\PlayerState.h"
|
||||
#include "..\game\GamePH\PlayerVariables.h"
|
||||
#include "..\game\GamePH\SessionCooperativeDI.h"
|
||||
#include "..\game\GamePH\TPPCameraDI.h"
|
||||
#include "..\game\GamePH\TimeWeather\CSystem.h"
|
||||
#include "..\game\GamePH\gen_TPPModel.h"
|
||||
|
||||
#include "..\game\Engine\CBulletPhysicsCharacter.h"
|
||||
#include "..\game\Engine\CGSObject.h"
|
||||
@@ -37,13 +35,11 @@ namespace Menu {
|
||||
{ "FreeCamera", reinterpret_cast<LPVOID(*)()>(&GamePH::FreeCamera::Get) },
|
||||
{ "GameDI_PH", reinterpret_cast<LPVOID(*)()>(&GamePH::GameDI_PH::Get) },
|
||||
{ "GameDI_PH2", reinterpret_cast<LPVOID(*)()>(&GamePH::GameDI_PH2::Get) },
|
||||
{ "gen_TPPModel", reinterpret_cast<LPVOID(*)()>(&GamePH::gen_TPPModel::Get) },
|
||||
{ "LevelDI", reinterpret_cast<LPVOID(*)()>(&GamePH::LevelDI::Get) },
|
||||
{ "LocalClientDI", reinterpret_cast<LPVOID(*)()>(&GamePH::LocalClientDI::Get) },
|
||||
{ "LogicalPlayer", reinterpret_cast<LPVOID(*)()>(&GamePH::LogicalPlayer::Get) },
|
||||
{ "PlayerDI_PH", reinterpret_cast<LPVOID(*)()>(&GamePH::PlayerDI_PH::Get) },
|
||||
{ "PlayerHealthModule", reinterpret_cast<LPVOID(*)()>(&GamePH::PlayerHealthModule::Get) },
|
||||
{ "PlayerObjProperties", reinterpret_cast<LPVOID(*)()>(&GamePH::PlayerObjProperties::Get) },
|
||||
{ "PlayerState", reinterpret_cast<LPVOID(*)()>(&GamePH::PlayerState::Get) },
|
||||
{ "PlayerVariables", reinterpret_cast<LPVOID(*)()>(&GamePH::PlayerVariables::Get) },
|
||||
{ "SessionCooperativeDI", reinterpret_cast<LPVOID(*)()>(&GamePH::SessionCooperativeDI::Get) },
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace Menu {
|
||||
namespace Debug {
|
||||
class Tab : MenuTab {
|
||||
public:
|
||||
Tab() : MenuTab("Debug", 4) {}
|
||||
Tab() : MenuTab("Debug", 6) {}
|
||||
void Update() override;
|
||||
void Render() override;
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include <pch.h>
|
||||
#include "..\changelog.h"
|
||||
#include "..\game\GamePH\Other.h"
|
||||
#include "..\game\GamePH\gameph_misc.h"
|
||||
#include "menu.h"
|
||||
|
||||
namespace Menu {
|
||||
@@ -81,14 +81,17 @@ namespace Menu {
|
||||
ImGui::SeparatorTextColored("Custom File Loading", IM_COL32(200, 0, 0, 255));
|
||||
ImGui::NewLine();
|
||||
ImGui::TextCentered("The mod always creates a folder \"EGameTools\\UserModFiles\" inside the same folder as the game executable (exe) or in the same folder as the mod file.");
|
||||
ImGui::TextCentered("This folder is used for custom file loading. This has only been tested with a few mods that change some .scr files, gpufx files, and other files included inside .pak game archives, or files like .rpack files.");
|
||||
ImGui::TextCentered("Files in this folder must have the same names as the ones from the game files, otherwise the game won't know it should load those files. Files in subfolders of the \"EGameTools\\UserModFiles\" folder will automatically be detected, so you can sort all your mods in different folders!");
|
||||
ImGui::TextCentered("This folder is used for custom file loading. It can load .PAKs and it can also load files extracted from these .PAKs. The latter has only been tested with a few mods that change some .scr files, .gpufx files, and other files included inside .PAK game archives, or files such as .rpack files.");
|
||||
ImGui::TextCentered("If you put .PAKs inside this folder, they can be named whatever. If you put any other kind of files, they must have the same names as the ones from the game files, otherwise the game won't know it should load those files. Files in subfolders of the \"EGameTools\\UserModFiles\" folder will automatically be detected, so you can sort all your mods in different folders!");
|
||||
ImGui::Spacing(ImVec2(0.0f, 5.0f));
|
||||
ImGui::TextCentered("The game will reload a lot of the files upon a load of your savegame, so if you want to edit those files and reload them without having to restart the game, just reload your savegame and the game should automatically reload most of those files!");
|
||||
ImGui::TextCentered("Just make sure that if you add new, additional files while you're in-game, please wait AT LEAST 5 seconds before reloading your savegame, otherwise additional files will not get detected.");
|
||||
ImGui::TextCentered("Also, if there are multiple files of the same exact name, the game will pick the first instance of that file it finds in the folder.");
|
||||
ImGui::Spacing(ImVec2(0.0f, 5.0f));
|
||||
ImGui::TextCentered("The gist of it is, you now don't have to use dataX.pak mods anymore! You can open the pak files, extract their files in the \"EGameTools\\UserModFiles\" folder and start the game!");
|
||||
ImGui::TextCentered("The gist of it is, you now don't have to use dataX.PAK mods anymore! Or if you do, you can now name them whatever you want! You can also open the PAK files, extract their files in the \"EGameTools\\UserModFiles\" folder and start the game.");
|
||||
ImGui::TextCentered("Any files put inside this folder will also bypass any of the game file checks, so you can use these mods in co-op too!");
|
||||
ImGui::Spacing(ImVec2(0.0f, 5.0f));
|
||||
ImGui::TextCentered("NOTE: Any mods that are put inside \"EGameTools\\UserModFiles\" as a regular file (.scr or any other file that is usually present in .PAK mods) and NOT a .PAK file, will make the game ignore the same files that are present in any of the .PAK mods inside \"EGameTools\\UserModFiles\". I recommend using .PAK for most mods. If you run into issues, try extracting the files inside the PAK into the folder directly.");
|
||||
ImGui::Spacing(ImVec2(0.0f, 5.0f));
|
||||
ImGui::TextCenteredColored("FOR MOD DEVELOPERS", IM_COL32(200, 0, 0, 255));
|
||||
ImGui::TextCentered("If you want to make mods for EGameTools to load, please try to use as few folders as you possibly can. For example, your mod should only have one folder, something like \"EGameTools\\UserModFiles\\2019 Weather Mod\".");
|
||||
@@ -150,7 +153,7 @@ namespace Menu {
|
||||
ImGui::SetNextWindowSizeConstraints(minWndSize, maxWndSize);
|
||||
if (ImGui::BeginPopupModal(changelogTitle.c_str(), nullptr, welcomeWindowFlags)) {
|
||||
const std::string subTitle = "This is what the " + std::string(MOD_VERSION_STR) + " update brings:";
|
||||
ImGui::TextCenteredColored(subTitle.c_str(), IM_COL32(230, 0, 0, 255), false);
|
||||
ImGui::TextCenteredColored(subTitle.c_str(), IM_COL32(230, 0, 0, 255), true);
|
||||
ImGui::Spacing(ImVec2(0.0f, 5.0f));
|
||||
|
||||
std::istringstream iss(Changelog::changelogs[MOD_VERSION_STR]);
|
||||
@@ -160,7 +163,7 @@ namespace Menu {
|
||||
ImGui::NewLine();
|
||||
continue;
|
||||
}
|
||||
ImGui::TextCentered(line.c_str(), false);
|
||||
ImGui::TextCentered(line.c_str(), true);
|
||||
}
|
||||
|
||||
if (ImGui::ButtonCentered("Close", ImVec2(0.0f, 30.0f) * scale)) {
|
||||
@@ -215,12 +218,12 @@ namespace Menu {
|
||||
ImGuiStyle* style = &ImGui::GetStyle();
|
||||
|
||||
style->WindowTitleAlign = ImVec2(0.5f, 0.5f);
|
||||
style->WindowPadding = ImVec2(15, 15);
|
||||
style->WindowPadding = ImVec2(13, 13);
|
||||
style->WindowRounding = 5.0f;
|
||||
style->ChildRounding = 4.0f;
|
||||
style->FramePadding = ImVec2(5, 5);
|
||||
style->FramePadding = ImVec2(4, 4);
|
||||
style->FrameRounding = 4.0f;
|
||||
style->ItemSpacing = ImVec2(12, 8);
|
||||
style->ItemSpacing = ImVec2(10, 6);
|
||||
style->ItemInnerSpacing = ImVec2(8, 6);
|
||||
style->IndentSpacing = 25.0f;
|
||||
style->ScrollbarSize = 15.0f;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#include <pch.h>
|
||||
#include "..\game\GamePH\Other.h"
|
||||
#include "..\game\GamePH\gameph_misc.h"
|
||||
#include "menu.h"
|
||||
|
||||
namespace Menu {
|
||||
@@ -10,7 +10,7 @@ namespace Menu {
|
||||
static ImVec2 EGTLogoSize = defEGTLogoSize;
|
||||
|
||||
static constexpr ImGuiWindowFlags windowFlags = ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoScrollbar;
|
||||
static constexpr ImVec2 defMinWndSize = ImVec2(425.0f, 725.0f);
|
||||
static constexpr ImVec2 defMinWndSize = ImVec2(575.0f, 725.0f);
|
||||
static ImVec2 minWndSize = defMinWndSize;
|
||||
static constexpr ImVec2 defMaxWndSize = ImVec2(900.0f, 725.0f);
|
||||
static ImVec2 maxWndSize = defMaxWndSize;
|
||||
@@ -22,6 +22,8 @@ namespace Menu {
|
||||
Option firstTimeRunning{};
|
||||
Option hasSeenChangelog{};
|
||||
|
||||
int currentTabIndex = 0;
|
||||
|
||||
void Render() {
|
||||
ImGui::StyleScaleAllSizes(&ImGui::GetStyle(), scale, &defStyle);
|
||||
ImGui::GetIO().FontGlobalScale = scale;
|
||||
@@ -47,6 +49,7 @@ namespace Menu {
|
||||
ImGui::SetNextWindowBgAlpha(static_cast<float>(opacity) / 100.0f);
|
||||
ImGui::SetNextWindowSizeConstraints(ImVec2(std::fmax(minWndSize.x - GImGui->Style.WindowPadding.x * 2.0f, ImGui::CalcTextSize(Core::gameVer > GAME_VER_COMPAT ? "Please wait for a new mod update." : "Upgrade your game version to one that the mod supports.").x), remainingHeight), ImVec2(maxWndSize.x - GImGui->Style.WindowPadding.x * 2.0f, remainingHeight));
|
||||
if (ImGui::BeginChild("##TabChild", ImVec2(0.0f, 0.0f), ImGuiChildFlags_AlwaysAutoResize | ImGuiChildFlags_AutoResizeX | ImGuiChildFlags_Border)) {
|
||||
currentTabIndex = tab.first;
|
||||
childWidth = ImGui::GetItemRectSize().x;
|
||||
tab.second->Render();
|
||||
ImGui::EndChild();
|
||||
@@ -62,7 +65,7 @@ namespace Menu {
|
||||
ImGui::SliderFloat("Menu Scale", &scale, 1.0f, 2.5f, "%.1f%%", ImGuiSliderFlags_AlwaysClamp);
|
||||
if (Core::gameVer != GAME_VER_COMPAT) {
|
||||
ImGui::TextColored(ImGui::ColorConvertU32ToFloat4(IM_COL32(200, 0, 0, 255)), "Incompatible game version detected!");
|
||||
ImGui::TextColored(ImGui::ColorConvertU32ToFloat4(IM_COL32(200, 0, 0, 255)), "Compatible game version: v%s", GamePH::GameVerToStr(GAME_VER_COMPAT));
|
||||
ImGui::TextColored(ImGui::ColorConvertU32ToFloat4(IM_COL32(200, 0, 0, 255)), "Compatible game version: v%s", GamePH::GameVerToStr(GAME_VER_COMPAT).c_str());
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
@@ -12,7 +12,6 @@ namespace Menu {
|
||||
virtual void Update() {};
|
||||
|
||||
std::string_view tabName{};
|
||||
private:
|
||||
int tabIndex{};
|
||||
};
|
||||
|
||||
@@ -27,5 +26,7 @@ namespace Menu {
|
||||
extern Option firstTimeRunning;
|
||||
extern Option hasSeenChangelog;
|
||||
|
||||
extern int currentTabIndex;
|
||||
|
||||
extern void Render();
|
||||
}
|
||||
@@ -3,10 +3,17 @@
|
||||
#include "..\game\GamePH\LevelDI.h"
|
||||
#include "misc.h"
|
||||
|
||||
namespace GamePH::Hooks {
|
||||
extern Utils::Hook::ByteHook<LPVOID> SaveGameCRCBoolCheckHook;
|
||||
}
|
||||
|
||||
namespace Menu {
|
||||
namespace Misc {
|
||||
KeyBindOption disableGamePauseWhileAFK{ VK_NONE };
|
||||
KeyBindOption disableHUD{ VK_F8 };
|
||||
Option disableSavegameCRCCheck{};
|
||||
Option disableDataPAKsCRCCheck{};
|
||||
Option increaseDataPAKsLimit{};
|
||||
|
||||
static void UpdateDisabledOptions() {
|
||||
GamePH::LevelDI* iLevel = GamePH::LevelDI::Get();
|
||||
@@ -39,11 +46,20 @@ namespace Menu {
|
||||
}
|
||||
void Tab::Render() {
|
||||
ImGui::SeparatorText("Misc##Misc");
|
||||
ImGui::CheckboxHotkey("Disable Game Pause While AFK", &disableGamePauseWhileAFK);
|
||||
ImGui::CheckboxHotkey("Disable Game Pause While AFK", &disableGamePauseWhileAFK, "Prevents the game from pausing while you're afk");
|
||||
ImGui::SameLine();
|
||||
ImGui::BeginDisabled(disableHUD.GetChangesAreDisabled()); {
|
||||
ImGui::CheckboxHotkey("Disable HUD", &disableHUD);
|
||||
ImGui::CheckboxHotkey("Disable HUD", &disableHUD, "Disables the entire HUD, including any sort of menus like the pause menu");
|
||||
ImGui::EndDisabled();
|
||||
}
|
||||
ImGui::SeparatorText("Game Checks##Misc");
|
||||
if (ImGui::Checkbox("Disable Savegame CRC Check *", &disableSavegameCRCCheck, "Stops the game from falsely saying your savegame is corrupt whenever you modify it outside of the game using a save editor"))
|
||||
GamePH::Hooks::SaveGameCRCBoolCheckHook.Toggle();
|
||||
ImGui::SameLine();
|
||||
ImGui::Checkbox("Disable Data PAKs CRC Check *", &disableDataPAKsCRCCheck, "Stops the game from scanning data PAKs, which allows you to use data PAK mods in multiplayer as well");
|
||||
ImGui::Checkbox("Increase Data PAKs Limit *", &increaseDataPAKsLimit, "Allows you to add more than 8 data PAKs, e.g. data8.pak, data9.pak, data10.pak, etc, up to 200 PAKs in total");
|
||||
ImGui::Separator();
|
||||
ImGui::TextColored(ImGui::ColorConvertU32ToFloat4(IM_COL32(200, 0, 0, 255)), "* Option requires game restart to apply");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,10 +5,13 @@ namespace Menu {
|
||||
namespace Misc {
|
||||
extern KeyBindOption disableGamePauseWhileAFK;
|
||||
extern KeyBindOption disableHUD;
|
||||
extern Option disableSavegameCRCCheck;
|
||||
extern Option disableDataPAKsCRCCheck;
|
||||
extern Option increaseDataPAKsLimit;
|
||||
|
||||
class Tab : MenuTab {
|
||||
public:
|
||||
Tab() : MenuTab("Misc", 2) {}
|
||||
Tab() : MenuTab("Misc", 4) {}
|
||||
void Update() override;
|
||||
void Render() override;
|
||||
|
||||
|
||||
+6174
-5630
File diff suppressed because it is too large
Load Diff
@@ -6,11 +6,21 @@ namespace Menu {
|
||||
namespace Player {
|
||||
extern float playerHealth;
|
||||
extern float playerMaxHealth;
|
||||
extern float playerImmunity;
|
||||
extern float playerMaxImmunity;
|
||||
extern int oldWorldMoney;
|
||||
extern KeyBindOption godMode;
|
||||
extern KeyBindOption freezePlayer;
|
||||
extern KeyBindOption unlimitedImmunity;
|
||||
extern KeyBindOption unlimitedStamina;
|
||||
extern KeyBindOption unlimitedItems;
|
||||
extern KeyBindOption oneHitKill;
|
||||
extern KeyBindOption invisibleToEnemies;
|
||||
extern KeyBindOption disableOutOfBoundsTimer;
|
||||
extern KeyBindOption nightrunnerMode;
|
||||
extern KeyBindOption oneHandedMode;
|
||||
extern KeyBindOption allowGrappleHookInSafezone;
|
||||
extern KeyBindOption disableAirControl;
|
||||
extern Option playerVariables;
|
||||
|
||||
extern std::string saveSCRPath;
|
||||
|
||||
@@ -0,0 +1,406 @@
|
||||
#include <pch.h>
|
||||
#include "..\game\Engine\CBulletPhysicsCharacter.h"
|
||||
#include "..\game\GamePH\FreeCamera.h"
|
||||
#include "..\game\GamePH\LevelDI.h"
|
||||
#include "camera.h"
|
||||
#include "player.h"
|
||||
#include "teleport.h"
|
||||
|
||||
namespace Menu {
|
||||
namespace Teleport {
|
||||
std::vector<TeleportLocation> savedTeleportLocations;
|
||||
static std::vector<std::string> savedTeleportLocationNames;
|
||||
static std::vector<const char*> savedTeleportLocationNamesPtrs;
|
||||
static int selectedTPLocation = -1;
|
||||
static char newLocationName[125]{};
|
||||
|
||||
Vector3 waypointCoords{};
|
||||
bool* waypointIsSet = nullptr;
|
||||
bool justTeleportedToWaypoint = false;
|
||||
static Vector3 teleportCoords{};
|
||||
|
||||
KeyBindOption teleportToSelectedLocation{ VK_F9 };
|
||||
KeyBindOption teleportToCoords{ VK_NONE };
|
||||
KeyBindOption teleportToWaypoint{ VK_F10 };
|
||||
|
||||
void UpdateTeleportLocationVisualNames() {
|
||||
savedTeleportLocationNames.clear();
|
||||
savedTeleportLocationNamesPtrs.clear();
|
||||
for (const auto& loc : savedTeleportLocations) {
|
||||
std::string completeName = loc.name + " (X: " + std::format("{:.1f}", loc.pos.X) + ", Y: " + std::format("{:.1f}", loc.pos.Y) + ", Z: " + std::format("{:.1f}", loc.pos.Z) + ")";
|
||||
savedTeleportLocationNames.emplace_back(completeName);
|
||||
}
|
||||
for (const auto& name : savedTeleportLocationNames)
|
||||
savedTeleportLocationNamesPtrs.emplace_back(name.c_str());
|
||||
}
|
||||
std::vector<TeleportLocation> ParseTeleportLocations(const std::string& input) {
|
||||
if (input.empty())
|
||||
return {};
|
||||
|
||||
std::vector<TeleportLocation> teleportLocations{};
|
||||
std::stringstream ss(input);
|
||||
std::string item{};
|
||||
|
||||
while (std::getline(ss, item, ';')) {
|
||||
size_t colonPos = item.rfind(':');
|
||||
if (colonPos != std::string::npos) {
|
||||
std::string tpLocName = item.substr(0, colonPos);
|
||||
std::string tpLocCoords = item.substr(colonPos + 1);
|
||||
|
||||
std::stringstream coordStream(tpLocCoords);
|
||||
std::string coordItem{};
|
||||
std::vector<float> coordValues{};
|
||||
while (std::getline(coordStream, coordItem, ',')) {
|
||||
try {
|
||||
coordValues.push_back(std::stof(coordItem));
|
||||
} catch (const std::invalid_argument& e) {
|
||||
UNREFERENCED_PARAMETER(e);
|
||||
spdlog::error("ParseTeleportLocations: Invalid coordinate value: {}, for location: {}", coordItem, tpLocName);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Vector3 tpLocPos{};
|
||||
if (coordValues.size() == 3) {
|
||||
tpLocPos.X = coordValues[0];
|
||||
tpLocPos.Y = coordValues[1];
|
||||
tpLocPos.Z = coordValues[2];
|
||||
teleportLocations.push_back({ tpLocName, tpLocPos });
|
||||
} else
|
||||
spdlog::error("ParseTeleportLocations: Invalid number of coordinates ({}) for location: {}", coordValues.size(), tpLocName);
|
||||
} else
|
||||
spdlog::error("ParseTeleportLocations: Invalid format for TP location: {}", item);
|
||||
}
|
||||
|
||||
spdlog::info("Successfully parsed teleport locations:");
|
||||
int tpLocIndex = 1;
|
||||
for (const auto& loc : teleportLocations) {
|
||||
spdlog::info("{}. \"{}\" (X: {}, Y: {}, Z: {})", tpLocIndex, loc.name, loc.pos.X, loc.pos.Y, loc.pos.Z);
|
||||
tpLocIndex++;
|
||||
}
|
||||
|
||||
return teleportLocations;
|
||||
}
|
||||
std::string ConvertTeleportLocationsToStr(const std::vector<TeleportLocation>& teleportLocations) {
|
||||
std::stringstream ss{};
|
||||
|
||||
for (size_t i = 0; i < teleportLocations.size(); ++i) {
|
||||
const TeleportLocation& loc = teleportLocations[i];
|
||||
|
||||
ss << loc.name << ":" << loc.pos.X << "," << loc.pos.Y << "," << loc.pos.Z;
|
||||
if (i < teleportLocations.size() - 1)
|
||||
ss << ";";
|
||||
}
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
static bool isTeleportationDisabled() {
|
||||
GamePH::LevelDI* iLevel = GamePH::LevelDI::Get();
|
||||
if (!iLevel || !iLevel->IsLoaded())
|
||||
return true;
|
||||
if (!Camera::freeCam.GetValue() && !Engine::CBulletPhysicsCharacter::Get())
|
||||
return true;
|
||||
else if (Camera::freeCam.GetValue() && !GamePH::FreeCamera::Get())
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void SyncTPCoordsToPlayer() {
|
||||
if (isTeleportationDisabled())
|
||||
return;
|
||||
|
||||
if (Camera::freeCam.GetValue()) {
|
||||
GamePH::FreeCamera* freeCam = GamePH::FreeCamera::Get();
|
||||
if (!freeCam)
|
||||
return;
|
||||
|
||||
Vector3 camPos{};
|
||||
freeCam->GetPosition(&camPos);
|
||||
if (camPos.isDefault())
|
||||
return;
|
||||
|
||||
teleportCoords = camPos;
|
||||
} else {
|
||||
Engine::CBulletPhysicsCharacter* playerCharacter = Engine::CBulletPhysicsCharacter::Get();
|
||||
if (!playerCharacter)
|
||||
return;
|
||||
|
||||
teleportCoords = playerCharacter->playerPos;
|
||||
}
|
||||
}
|
||||
static bool TeleportPlayerTo(const Vector3& pos) {
|
||||
if (isTeleportationDisabled())
|
||||
return false;
|
||||
|
||||
if (pos.isDefault())
|
||||
return false;
|
||||
|
||||
if (Camera::freeCam.GetValue()) {
|
||||
GamePH::FreeCamera* freeCam = GamePH::FreeCamera::Get();
|
||||
if (!freeCam)
|
||||
return false;
|
||||
|
||||
freeCam->SetPosition(&pos);
|
||||
} else {
|
||||
Engine::CBulletPhysicsCharacter* playerCharacter = Engine::CBulletPhysicsCharacter::Get();
|
||||
if (!playerCharacter)
|
||||
return false;
|
||||
|
||||
if (Player::freezePlayer.GetValue())
|
||||
playerCharacter->posBeforeFreeze = pos;
|
||||
playerCharacter->MoveCharacter(pos);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void UpdateTeleportPos() {
|
||||
if (isTeleportationDisabled()) {
|
||||
if (!teleportCoords.isDefault())
|
||||
teleportCoords = Vector3();
|
||||
return;
|
||||
}
|
||||
if (!teleportCoords.isDefault())
|
||||
return;
|
||||
|
||||
if (Camera::freeCam.GetValue()) {
|
||||
GamePH::FreeCamera* freeCam = GamePH::FreeCamera::Get();
|
||||
if (!freeCam)
|
||||
return;
|
||||
|
||||
Vector3 camPos{};
|
||||
freeCam->GetPosition(&camPos);
|
||||
if (camPos.isDefault())
|
||||
return;
|
||||
|
||||
teleportCoords = camPos;
|
||||
} else {
|
||||
Engine::CBulletPhysicsCharacter* playerCharacter = Engine::CBulletPhysicsCharacter::Get();
|
||||
if (!playerCharacter)
|
||||
return;
|
||||
|
||||
teleportCoords = playerCharacter->playerPos;
|
||||
}
|
||||
}
|
||||
static void HotkeysUpdate() {
|
||||
teleportToSelectedLocation.SetChangesAreDisabled(selectedTPLocation < 0 || selectedTPLocation >= savedTeleportLocations.size());
|
||||
teleportToWaypoint.SetChangesAreDisabled(isTeleportationDisabled() || !waypointIsSet || !*waypointIsSet);
|
||||
teleportToCoords.SetChangesAreDisabled(isTeleportationDisabled());
|
||||
|
||||
if (teleportToSelectedLocation.HasChanged()) {
|
||||
TeleportPlayerTo(savedTeleportLocations[selectedTPLocation].pos);
|
||||
teleportToSelectedLocation.SetPrevValue(teleportToSelectedLocation.GetValue());
|
||||
}
|
||||
if (teleportToWaypoint.HasChanged()) {
|
||||
justTeleportedToWaypoint = TeleportPlayerTo(waypointCoords);
|
||||
teleportToWaypoint.SetPrevValue(teleportToWaypoint.GetValue());
|
||||
}
|
||||
if (teleportToCoords.HasChanged()) {
|
||||
TeleportPlayerTo(teleportCoords);
|
||||
teleportToCoords.SetPrevValue(teleportToCoords.GetValue());
|
||||
}
|
||||
}
|
||||
|
||||
static bool SaveTeleportLocation(const char* locationName) {
|
||||
if (isTeleportationDisabled()) {
|
||||
ImGui::CloseCurrentPopup();
|
||||
ImGui::EndPopup();
|
||||
ImGui::OpenPopup("Couldn't add location");
|
||||
return false;
|
||||
}
|
||||
|
||||
auto savedLocIt = std::find_if(savedTeleportLocations.begin(), savedTeleportLocations.end(), [&locationName](const auto& loc) {
|
||||
return loc.name == locationName;
|
||||
});
|
||||
if (savedLocIt != savedTeleportLocations.end()) {
|
||||
ImGui::CloseCurrentPopup();
|
||||
ImGui::EndPopup();
|
||||
ImGui::OpenPopup("Location already exists");
|
||||
return false;
|
||||
}
|
||||
|
||||
Vector3 playerPos{};
|
||||
|
||||
if (Camera::freeCam.GetValue()) {
|
||||
GamePH::FreeCamera* freeCam = GamePH::FreeCamera::Get();
|
||||
if (!freeCam) {
|
||||
ImGui::CloseCurrentPopup();
|
||||
ImGui::EndPopup();
|
||||
ImGui::OpenPopup("Couldn't add location");
|
||||
return false;
|
||||
}
|
||||
|
||||
Vector3 camPos{};
|
||||
freeCam->GetPosition(&camPos);
|
||||
if (camPos.isDefault()) {
|
||||
ImGui::CloseCurrentPopup();
|
||||
ImGui::EndPopup();
|
||||
ImGui::OpenPopup("Couldn't add location");
|
||||
return false;
|
||||
}
|
||||
|
||||
playerPos = camPos;
|
||||
} else {
|
||||
Engine::CBulletPhysicsCharacter* playerCharacter = Engine::CBulletPhysicsCharacter::Get();
|
||||
if (!playerCharacter) {
|
||||
ImGui::CloseCurrentPopup();
|
||||
ImGui::EndPopup();
|
||||
ImGui::OpenPopup("Couldn't add location");
|
||||
return false;
|
||||
}
|
||||
|
||||
playerPos = playerCharacter->playerPos;
|
||||
}
|
||||
playerPos = playerPos.round(1);
|
||||
|
||||
savedLocIt = std::find_if(savedTeleportLocations.begin(), savedTeleportLocations.end(), [&playerPos](const auto& loc) {
|
||||
return loc.pos == playerPos;
|
||||
});
|
||||
if (savedLocIt != savedTeleportLocations.end() && savedLocIt->pos == playerPos) {
|
||||
ImGui::CloseCurrentPopup();
|
||||
ImGui::EndPopup();
|
||||
ImGui::OpenPopup("Location already exists");
|
||||
return false;
|
||||
}
|
||||
|
||||
savedTeleportLocations.emplace_back(std::string(locationName), playerPos);
|
||||
UpdateTeleportLocationVisualNames();
|
||||
|
||||
ImGui::CloseCurrentPopup();
|
||||
return true;
|
||||
}
|
||||
static void HandleDialogs() {
|
||||
ImGui::SetNextWindowPos(ImGui::GetMainViewport()->GetCenter(), 0, ImVec2(0.5f, 0.5f));
|
||||
if (ImGui::BeginPopupModal("Give the location a name", nullptr, ImGuiWindowFlags_AlwaysAutoResize)) {
|
||||
bool tpSaveResult = true;
|
||||
ImGui::PushItemWidth(510.0f * Menu::scale);
|
||||
if (ImGui::InputTextWithHint("##TPLocationNameInputText", "Location name", newLocationName, IM_ARRAYSIZE(newLocationName), ImGuiInputTextFlags_EnterReturnsTrue) || ImGui::Button("OK", ImVec2(250.0f, 0.0f) * Menu::scale) && newLocationName[0]) {
|
||||
ImGui::PopItemWidth();
|
||||
tpSaveResult = SaveTeleportLocation(newLocationName);
|
||||
newLocationName[0] = 0;
|
||||
} else if (ImGui::SameLine(); ImGui::Button("Cancel", ImVec2(250.0f, 0.0f) * Menu::scale))
|
||||
ImGui::CloseCurrentPopup();
|
||||
if (tpSaveResult)
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
ImGui::SetNextWindowPos(ImGui::GetMainViewport()->GetCenter(), 0, ImVec2(0.5f, 0.5f));
|
||||
if (ImGui::BeginPopupModal("Location already exists", nullptr, ImGuiWindowFlags_AlwaysAutoResize)) {
|
||||
ImGui::PushItemWidth(500.0f * Menu::scale);
|
||||
ImGui::TextCentered("The location you have entered already exists. Either the name of the location, or the position of the location is already inside the list. If you want to change it then please remove it and add it again.", false);
|
||||
if (ImGui::Button("OK", ImVec2(500.0f, 0.0f) * Menu::scale)) {
|
||||
ImGui::PopItemWidth();
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
ImGui::SetNextWindowPos(ImGui::GetMainViewport()->GetCenter(), 0, ImVec2(0.5f, 0.5f));
|
||||
if (ImGui::BeginPopupModal("Couldn't add location", nullptr, ImGuiWindowFlags_AlwaysAutoResize)) {
|
||||
ImGui::PushItemWidth(500.0f * Menu::scale);
|
||||
ImGui::TextCentered("Something went wrong trying to add a location. Either the player class or camera class are not found, or you're in a place in the game where the character or camera isn't properly loaded. If this happens, even though you know it should work fine, please contact @EricPlayZ on NexusMods, GitHub or Discord.");
|
||||
if (ImGui::Button("OK", ImVec2(500.0f, 0.0f) * Menu::scale)) {
|
||||
ImGui::PopItemWidth();
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
}
|
||||
|
||||
Tab Tab::instance{};
|
||||
void Tab::Update() {
|
||||
UpdateTeleportPos();
|
||||
HotkeysUpdate();
|
||||
}
|
||||
void Tab::Render() {
|
||||
ImGui::SeparatorText("Saved Locations##Teleport");
|
||||
ImGui::PushItemWidth(672.0f * Menu::scale);
|
||||
ImGui::ListBox("##SavedTPLocationsListBox", &selectedTPLocation, savedTeleportLocationNamesPtrs.data(), static_cast<int>(savedTeleportLocationNamesPtrs.size()), 5);
|
||||
ImGui::PopItemWidth();
|
||||
|
||||
ImGui::BeginDisabled(isTeleportationDisabled() || selectedTPLocation < 0 || selectedTPLocation >= savedTeleportLocations.size()); {
|
||||
if (ImGui::ButtonHotkey("Teleport to Selected Location", &teleportToSelectedLocation, "Teleports player to selected location from the saved locations list"))
|
||||
TeleportPlayerTo(savedTeleportLocations[selectedTPLocation].pos);
|
||||
ImGui::EndDisabled();
|
||||
}
|
||||
ImGui::SameLine();
|
||||
ImGui::BeginDisabled(selectedTPLocation < 0 || selectedTPLocation >= savedTeleportLocations.size()); {
|
||||
if (ImGui::Button("Remove Selected Location")) {
|
||||
savedTeleportLocations.erase(savedTeleportLocations.begin() + selectedTPLocation);
|
||||
UpdateTeleportLocationVisualNames();
|
||||
selectedTPLocation = -1;
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
}
|
||||
ImGui::BeginDisabled(isTeleportationDisabled()); {
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Save Current Location"))
|
||||
ImGui::OpenPopup("Give the location a name");
|
||||
|
||||
ImGui::EndDisabled();
|
||||
}
|
||||
|
||||
ImGui::SeparatorText("Custom##Teleport");
|
||||
ImGui::BeginDisabled(isTeleportationDisabled()); {
|
||||
static std::string playerPos = "Player Position = X: 0.00, Y: 0.00, Z: 0.00";
|
||||
Engine::CBulletPhysicsCharacter* playerCharacter = Engine::CBulletPhysicsCharacter::Get();
|
||||
if (!playerCharacter)
|
||||
playerPos = "Player Position -- X: 0.00, Y: 0.00, Z: 0.00";
|
||||
else {
|
||||
playerPos = "Player Position -- X: " + std::format("{:.2f}", playerCharacter->playerPos.data.X) + ", Y: " + std::format("{:.2f}", playerCharacter->playerPos.data.Y) + ", Z: " + std::format("{:.2f}", playerCharacter->playerPos.data.Z);
|
||||
}
|
||||
|
||||
static std::string cameraPos = "Free Camera Position -- X: 0.00, Y: 0.00, Z: 0.00";
|
||||
GamePH::FreeCamera* freeCam = GamePH::FreeCamera::Get();
|
||||
if (!Camera::freeCam.GetValue() || !freeCam)
|
||||
cameraPos = "Free Camera Position -- X: 0.00, Y: 0.00, Z: 0.00";
|
||||
else {
|
||||
Vector3 camPos{};
|
||||
freeCam->GetPosition(&camPos);
|
||||
if (camPos.isDefault())
|
||||
cameraPos = "Free Camera Position -- X: 0.00, Y: 0.00, Z: 0.00";
|
||||
else
|
||||
cameraPos = "Free Camera Position -- X: " + std::format("{:.2f}", camPos.X) + ", Y: " + std::format("{:.2f}", camPos.Y) + ", Z: " + std::format("{:.2f}", camPos.Z);
|
||||
}
|
||||
|
||||
static std::string waypointPos = "Waypoint Position = X: 0.00, Y: 0.00, Z: 0.00";
|
||||
if (!waypointIsSet || !*waypointIsSet || waypointCoords.isDefault())
|
||||
waypointPos = "Waypoint Position -- X: 0.00, Y: 0.00, Z: 0.00";
|
||||
else {
|
||||
waypointPos = "Waypoint Position -- X: " + std::format("{:.2f}", waypointCoords.X) + ", Y: " + std::format("{:.2f}", waypointCoords.Y) + ", Z: " + std::format("{:.2f}", waypointCoords.Z);
|
||||
}
|
||||
|
||||
ImGui::Text(playerPos.data());
|
||||
ImGui::Text(cameraPos.data());
|
||||
ImGui::Text(waypointPos.data());
|
||||
|
||||
ImGui::PushItemWidth(200.0f * Menu::scale);
|
||||
ImGui::InputFloat("X", &teleportCoords.X, 1.0f, 10.0f, "%.2f");
|
||||
ImGui::SameLine();
|
||||
ImGui::InputFloat("Y", &teleportCoords.Y, 1.0f, 10.0f, "%.2f");
|
||||
ImGui::SameLine();
|
||||
ImGui::InputFloat("Z", &teleportCoords.Z, 1.0f, 10.0f, "%.2f");
|
||||
ImGui::PopItemWidth();
|
||||
|
||||
ImGui::EndDisabled();
|
||||
}
|
||||
ImGui::BeginDisabled(isTeleportationDisabled() || !waypointIsSet || !*waypointIsSet); {
|
||||
if (ImGui::ButtonHotkey("Teleport to Waypoint", &teleportToWaypoint, "Teleports player to waypoint.\nWARNING: If the waypoint is selected to track an object/item on the map, Teleport to Waypoint will not work, if so just set the waypoint nearby instead.\nWARNING: Your player height won't change when teleporting, so make sure you catch yourself if you fall under the map because of the teleportation"))
|
||||
justTeleportedToWaypoint = TeleportPlayerTo(waypointCoords);
|
||||
ImGui::EndDisabled();
|
||||
}
|
||||
|
||||
ImGui::BeginDisabled(isTeleportationDisabled()); {
|
||||
ImGui::SameLine();
|
||||
if (ImGui::ButtonHotkey("Teleport to Coords", &teleportToCoords, "Teleports player to the coords specified in the input boxes above"))
|
||||
TeleportPlayerTo(teleportCoords);
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Get Player Coords"))
|
||||
SyncTPCoordsToPlayer();
|
||||
ImGui::EndDisabled();
|
||||
}
|
||||
|
||||
HandleDialogs();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
#pragma once
|
||||
#include "menu.h"
|
||||
|
||||
namespace Menu {
|
||||
namespace Teleport {
|
||||
struct TeleportLocation {
|
||||
std::string name;
|
||||
Vector3 pos;
|
||||
};
|
||||
|
||||
extern std::vector<TeleportLocation> savedTeleportLocations;
|
||||
|
||||
extern Vector3 waypointCoords;
|
||||
extern bool* waypointIsSet;
|
||||
extern bool justTeleportedToWaypoint;
|
||||
|
||||
extern KeyBindOption teleportToSelectedLocation;
|
||||
extern KeyBindOption teleportToCoords;
|
||||
extern KeyBindOption teleportToWaypoint;
|
||||
|
||||
extern void UpdateTeleportLocationVisualNames();
|
||||
extern std::vector<TeleportLocation> ParseTeleportLocations(const std::string& input);
|
||||
extern std::string ConvertTeleportLocationsToStr(const std::vector<TeleportLocation>& teleportLocations);
|
||||
|
||||
class Tab : MenuTab {
|
||||
public:
|
||||
Tab() : MenuTab("Teleport", 3) {}
|
||||
void Update() override;
|
||||
void Render() override;
|
||||
|
||||
static Tab instance;
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
#include <pch.h>
|
||||
#include "..\core.h"
|
||||
#include "..\game\GamePH\LevelDI.h"
|
||||
#include "..\game\GamePH\PlayerDI_PH.h"
|
||||
#include "..\game\GamePH\PlayerVariables.h"
|
||||
#include "menu.h"
|
||||
#include "weapon.h"
|
||||
|
||||
namespace Menu {
|
||||
namespace Weapon {
|
||||
float currentWeaponDurability = 0.0f;
|
||||
KeyBindOption unlimitedDurability{ VK_NONE };
|
||||
KeyBindOption unlimitedAmmo{ VK_NONE };
|
||||
KeyBindOption noSpread{ VK_NONE };
|
||||
KeyBindOption noRecoil{ VK_NONE };
|
||||
KeyBindOption instantReload{ VK_NONE };
|
||||
|
||||
static constexpr float baseWeaponDurabilityMul = 1.0f;
|
||||
static constexpr float baseWeaponAccuracyMul = 1.0f;
|
||||
static constexpr float baseBowAccuracyMul = 0.1f;
|
||||
static constexpr float baseWeaponRecoilMul = 1.0f;
|
||||
static constexpr float baseWeaponReloadMul = 1.0f;
|
||||
|
||||
static void UpdatePlayerVars() {
|
||||
if (!GamePH::PlayerVariables::gotPlayerVars)
|
||||
return;
|
||||
|
||||
GamePH::PlayerVariables::ManagePlayerVarOption("MeleeWpnDurabilityMulReduce", 0.0f, baseWeaponDurabilityMul, &unlimitedDurability, true);
|
||||
|
||||
GamePH::PlayerVariables::ManagePlayerVarOption("FirearmsPistolInfiniteAmmo", true, false, &unlimitedAmmo);
|
||||
GamePH::PlayerVariables::ManagePlayerVarOption("FirearmsRevolverInfiniteAmmo", true, false, &unlimitedAmmo);
|
||||
GamePH::PlayerVariables::ManagePlayerVarOption("FirearmsRifleInfiniteAmmo", true, false, &unlimitedAmmo);
|
||||
GamePH::PlayerVariables::ManagePlayerVarOption("FirearmsShotgunInfiniteAmmo", true, false, &unlimitedAmmo);
|
||||
GamePH::PlayerVariables::ManagePlayerVarOption("FirearmsSMGInfiniteAmmo", true, false, &unlimitedAmmo);
|
||||
GamePH::PlayerVariables::ManagePlayerVarOption("InfiniteArrows", true, false, &unlimitedAmmo);
|
||||
|
||||
GamePH::PlayerVariables::ManagePlayerVarOption("BulletAccuracyFactor", 0.0f, baseWeaponAccuracyMul, &noSpread, true);
|
||||
GamePH::PlayerVariables::ManagePlayerVarOption("FirearmsMoveAccuracyReduce", 0.0f, baseWeaponAccuracyMul, &noSpread, true);
|
||||
GamePH::PlayerVariables::ManagePlayerVarOption("FirearmsPistolAccuracyFactor", 0.0f, baseWeaponAccuracyMul, &noSpread, true);
|
||||
GamePH::PlayerVariables::ManagePlayerVarOption("FirearmsRevolverAccuracyFactor", 0.0f, baseWeaponAccuracyMul, &noSpread, true);
|
||||
GamePH::PlayerVariables::ManagePlayerVarOption("FirearmsRifleAccuracyFactor", 0.0f, baseWeaponAccuracyMul, &noSpread, true);
|
||||
GamePH::PlayerVariables::ManagePlayerVarOption("FirearmsShotgunAccuracyFactor", 0.0f, baseWeaponAccuracyMul, &noSpread, true);
|
||||
GamePH::PlayerVariables::ManagePlayerVarOption("FirearmsCrossbowAccuracyFactor", 0.0f, baseBowAccuracyMul, &noSpread, true);
|
||||
GamePH::PlayerVariables::ManagePlayerVarOption("FirearmsHarpoonAccuracyFactor", 0.0f, baseBowAccuracyMul, &noSpread, true);
|
||||
GamePH::PlayerVariables::ManagePlayerVarOption("BowAccuracyFactor", 0.0f, baseBowAccuracyMul, &noSpread, true);
|
||||
GamePH::PlayerVariables::ManagePlayerVarOption("BowMaxThrowFactor", 99999.0f, 1.0f, &noSpread, true);
|
||||
GamePH::PlayerVariables::ManagePlayerVarOption("BowSlowMoAccuracyMul", 0.0f, 0.25f, &noSpread, true);
|
||||
|
||||
GamePH::PlayerVariables::ManagePlayerVarOption("BulletRecoilFactor", 0.0f, baseWeaponRecoilMul, &noRecoil, true);
|
||||
GamePH::PlayerVariables::ManagePlayerVarOption("FirearmsPistolRecoilFactor", 0.0f, baseWeaponRecoilMul, &noRecoil, true);
|
||||
GamePH::PlayerVariables::ManagePlayerVarOption("FirearmsRevolverRecoilFactor", 0.0f, baseWeaponRecoilMul, &noRecoil, true);
|
||||
GamePH::PlayerVariables::ManagePlayerVarOption("FirearmsRifleRecoilFactor", 0.0f, baseWeaponRecoilMul, &noRecoil, true);
|
||||
GamePH::PlayerVariables::ManagePlayerVarOption("FirearmsShotgunRecoilFactor", 0.0f, baseWeaponRecoilMul, &noRecoil, true);
|
||||
|
||||
GamePH::PlayerVariables::ManagePlayerVarOption("BulletReloadSpeed", 1000.0f, 0.0f, &instantReload, true);
|
||||
GamePH::PlayerVariables::ManagePlayerVarOption("FirearmsPistolReloadTimeMul", 1000.0f, baseWeaponReloadMul, &instantReload, true);
|
||||
GamePH::PlayerVariables::ManagePlayerVarOption("FirearmsRevolverReloadTimeMul", 1000.0f, baseWeaponReloadMul, &instantReload, true);
|
||||
GamePH::PlayerVariables::ManagePlayerVarOption("FirearmsRifleReloadTimeMul", 1000.0f, baseWeaponReloadMul, &instantReload, true);
|
||||
GamePH::PlayerVariables::ManagePlayerVarOption("FirearmsShotgunReloadTimeMul", 1000.0f, baseWeaponReloadMul, &instantReload, true);
|
||||
GamePH::PlayerVariables::ManagePlayerVarOption("BowPutArrowDuration", 0.0f, 0.137f, &instantReload, true);
|
||||
}
|
||||
static void UpdateWeaponDurability(bool updateSlider) {
|
||||
GamePH::LevelDI* iLevel = GamePH::LevelDI::Get();
|
||||
if (!iLevel || !iLevel->IsLoaded())
|
||||
return;
|
||||
GamePH::PlayerDI_PH* player = GamePH::PlayerDI_PH::Get();
|
||||
if (!player)
|
||||
return;
|
||||
GamePH::InventoryItem* weaponItem = player->GetCurrentWeapon(0);
|
||||
if (!weaponItem)
|
||||
return;
|
||||
GamePH::ItemDescWithContext* weaponItemCtx = weaponItem->GetItemDescCtx();
|
||||
if (!weaponItemCtx)
|
||||
return;
|
||||
|
||||
updateSlider ? (currentWeaponDurability = weaponItemCtx->weaponDurability) : (weaponItemCtx->weaponDurability = currentWeaponDurability);
|
||||
}
|
||||
|
||||
static bool isWeaponInteractionDisabled() {
|
||||
GamePH::LevelDI* iLevel = GamePH::LevelDI::Get();
|
||||
if (!iLevel || !iLevel->IsLoaded())
|
||||
return true;
|
||||
GamePH::PlayerDI_PH* player = GamePH::PlayerDI_PH::Get();
|
||||
if (!player)
|
||||
return true;
|
||||
GamePH::InventoryItem* weaponItem = player->GetCurrentWeapon(0);
|
||||
if (!weaponItem || !weaponItem->GetItemDescCtx())
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Tab Tab::instance{};
|
||||
void Tab::Update() {
|
||||
if (!Menu::menuToggle.GetValue())
|
||||
UpdateWeaponDurability(true);
|
||||
UpdatePlayerVars();
|
||||
}
|
||||
void Tab::Render() {
|
||||
ImGui::SeparatorText("Current Weapon##Weapon");
|
||||
ImGui::BeginDisabled(isWeaponInteractionDisabled() || currentWeaponDurability <= 0.0f); {
|
||||
if (ImGui::SliderFloat("Weapon Durability", "Currently only works while your weapon is physically equipped in your hand", ¤tWeaponDurability, 0.1f, 999.0f, "%.2f", ImGuiSliderFlags_AlwaysClamp))
|
||||
UpdateWeaponDurability(false);
|
||||
else
|
||||
UpdateWeaponDurability(true);
|
||||
ImGui::EndDisabled();
|
||||
}
|
||||
|
||||
ImGui::SeparatorText("Misc##Weapon");
|
||||
ImGui::CheckboxHotkey("Unlimited Durability", &unlimitedDurability, "Enables unlimited durability for all weapons");
|
||||
ImGui::SameLine();
|
||||
ImGui::CheckboxHotkey("Unlimited Ammo", &unlimitedAmmo, "Enables unlimited ammo for all firearms and bows");
|
||||
ImGui::CheckboxHotkey("No Spread", &noSpread, "Disables random bullet spread for all firearms and bows (doesn't completely remove spread for bows)");
|
||||
ImGui::SameLine();
|
||||
ImGui::CheckboxHotkey("No Recoil", &noRecoil, "Disables weapon recoil for all firearms");
|
||||
ImGui::CheckboxHotkey("Instant Reload", &instantReload, "Makes reloading firearms and bows (almost) instant");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
#include "..\core.h"
|
||||
#include "menu.h"
|
||||
|
||||
namespace Menu {
|
||||
namespace Weapon {
|
||||
extern KeyBindOption unlimitedDurability;
|
||||
extern KeyBindOption unlimitedAmmo;
|
||||
extern KeyBindOption noSpread;
|
||||
extern KeyBindOption noRecoil;
|
||||
extern KeyBindOption instantReload;
|
||||
|
||||
class Tab : MenuTab {
|
||||
public:
|
||||
Tab() : MenuTab("Weapon", 1) {}
|
||||
void Update() override;
|
||||
void Render() override;
|
||||
|
||||
static Tab instance;
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
#include <pch.h>
|
||||
#include "..\game\GamePH\DayNightCycle.h"
|
||||
#include "..\game\GamePH\LevelDI.h"
|
||||
#include "..\game\GamePH\PlayerVariables.h"
|
||||
#include "..\game\GamePH\TimeWeather\CSystem.h"
|
||||
#include "..\game\GamePH\TimeWeather\EWeather.h"
|
||||
#include "world.h"
|
||||
@@ -9,8 +10,9 @@ namespace Menu {
|
||||
namespace World {
|
||||
float time = 0.0f;
|
||||
static float timeBeforeFreeze = 0.0f;
|
||||
float worldSpeed = 1.0f;
|
||||
float gameSpeed = 1.0f;
|
||||
static bool isModifyingGameSpeed = false;
|
||||
static float actualGameSpeed = gameSpeed;
|
||||
static float gameSpeedBeforeSlowMo = gameSpeed;
|
||||
KeyBindOption freezeTime{ VK_NONE };
|
||||
KeyBindOption slowMotion{ '4' };
|
||||
@@ -57,13 +59,13 @@ namespace Menu {
|
||||
if (slowMotion.HasChangedTo(false)) {
|
||||
static float gameSpeedAfterChange = 0.0f;
|
||||
if (slowMoHasChanged)
|
||||
gameSpeedAfterChange = gameSpeed;
|
||||
gameSpeedAfterChange = actualGameSpeed;
|
||||
|
||||
slowMotionSpeedLerp = ImGui::AnimateLerp("slowMotionSpeedLerp", gameSpeedAfterChange, gameSpeedBeforeSlowMo, slowMotionTransitionTime, slowMoHasChanged, &ImGui::AnimEaseInOutSine);
|
||||
iLevel->TimerSetSpeedUp(slowMotionSpeedLerp);
|
||||
slowMoHasChanged = false;
|
||||
|
||||
if (Utils::Values::are_samef(gameSpeed, gameSpeedBeforeSlowMo)) {
|
||||
if (Utils::Values::are_samef(actualGameSpeed, gameSpeedBeforeSlowMo)) {
|
||||
slowMoHasChanged = true;
|
||||
slowMotion.SetPrevValue(false);
|
||||
}
|
||||
@@ -71,8 +73,8 @@ namespace Menu {
|
||||
static float gameSpeedAfterChange = 0.0f;
|
||||
if (slowMotion.HasChanged()) {
|
||||
if (slowMoHasChanged)
|
||||
gameSpeedBeforeSlowMo = gameSpeed;
|
||||
gameSpeedAfterChange = gameSpeed;
|
||||
gameSpeedBeforeSlowMo = actualGameSpeed;
|
||||
gameSpeedAfterChange = actualGameSpeed;
|
||||
}
|
||||
|
||||
slowMotionSpeedLerp = ImGui::AnimateLerp("slowMotionSpeedLerp", gameSpeedAfterChange, slowMotionSpeed, slowMotionTransitionTime, slowMotion.HasChanged(), &ImGui::AnimEaseInOutSine);
|
||||
@@ -84,14 +86,14 @@ namespace Menu {
|
||||
}
|
||||
}
|
||||
|
||||
if (!menuToggle.GetValue()) {
|
||||
time = dayNightCycle->time1 * 24.0f;
|
||||
if (freezeTime.GetValue() && !Utils::Values::are_samef(time, timeBeforeFreeze, 0.009999f))
|
||||
dayNightCycle->SetDaytime(timeBeforeFreeze);
|
||||
time = dayNightCycle->time1 * 24.0f;
|
||||
if (freezeTime.GetValue() && !Utils::Values::are_samef(time, timeBeforeFreeze, 0.0095f))
|
||||
dayNightCycle->SetDaytime(timeBeforeFreeze);
|
||||
|
||||
if (!isModifyingGameSpeed) {
|
||||
if (!slowMotion.GetValue() && !slowMotion.HasChanged() && !Utils::Values::are_samef(gameSpeed, 1.0f))
|
||||
iLevel->TimerSetSpeedUp(gameSpeed);
|
||||
gameSpeed = iLevel->TimerGetSpeedUp();
|
||||
actualGameSpeed = iLevel->TimerGetSpeedUp();
|
||||
}
|
||||
}
|
||||
void Tab::Render() {
|
||||
@@ -99,34 +101,33 @@ namespace Menu {
|
||||
GamePH::LevelDI* iLevel = GamePH::LevelDI::Get();
|
||||
ImGui::SeparatorText("Time##World");
|
||||
ImGui::BeginDisabled(!iLevel || !iLevel->IsLoaded() || !dayNightCycle); {
|
||||
static bool timeSliderBeingPressed = false;
|
||||
if (ImGui::SliderFloat("Time", &time, 0.01f, 24.0f, "%.2f", ImGuiSliderFlags_AlwaysClamp))
|
||||
timeSliderBeingPressed = true;
|
||||
else if (iLevel && iLevel->IsLoaded() && dayNightCycle) {
|
||||
if (timeSliderBeingPressed) {
|
||||
timeSliderBeingPressed = false;
|
||||
timeBeforeFreeze = time;
|
||||
dayNightCycle->SetDaytime(time);
|
||||
static bool previousAntizinDrainBlocked = false;
|
||||
static bool haveResetAntizinDrainBlocked = true;
|
||||
if (ImGui::SliderFloat("Time", &time, 0.01f, 24.0f, "%.2f", ImGuiSliderFlags_AlwaysClamp)) {
|
||||
if (haveResetAntizinDrainBlocked)
|
||||
previousAntizinDrainBlocked = GamePH::PlayerVariables::GetPlayerVar<bool>("AntizinDrainBlocked");
|
||||
GamePH::PlayerVariables::ChangePlayerVar("AntizinDrainBlocked", true);
|
||||
haveResetAntizinDrainBlocked = false;
|
||||
|
||||
timeBeforeFreeze = time;
|
||||
dayNightCycle->SetDaytime(time);
|
||||
} else if (iLevel && iLevel->IsLoaded() && dayNightCycle) {
|
||||
if (!haveResetAntizinDrainBlocked) {
|
||||
GamePH::PlayerVariables::ChangePlayerVar("AntizinDrainBlocked", previousAntizinDrainBlocked);
|
||||
haveResetAntizinDrainBlocked = true;
|
||||
}
|
||||
time = dayNightCycle->time1 * 24.0f;
|
||||
if (freezeTime.GetValue() && !Utils::Values::are_samef(time, timeBeforeFreeze, 0.009999f))
|
||||
dayNightCycle->SetDaytime(timeBeforeFreeze);
|
||||
}
|
||||
|
||||
ImGui::BeginDisabled(slowMotion.GetValue()); {
|
||||
if (ImGui::SliderFloat("Game Speed", &gameSpeed, 0.0f, 2.0f, "%.2fx"))
|
||||
isModifyingGameSpeed = ImGui::SliderFloat("Game Speed", &gameSpeed, 0.0f, 2.0f, "%.2fx");
|
||||
if (isModifyingGameSpeed)
|
||||
iLevel->TimerSetSpeedUp(gameSpeed);
|
||||
else if (iLevel && iLevel->IsLoaded()) {
|
||||
if (!slowMotion.GetValue() && !slowMotion.HasChanged() && !Utils::Values::are_samef(gameSpeed, 1.0f))
|
||||
iLevel->TimerSetSpeedUp(gameSpeed);
|
||||
gameSpeed = iLevel->TimerGetSpeedUp();
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
}
|
||||
|
||||
ImGui::CheckboxHotkey("Freeze Time", &freezeTime);
|
||||
ImGui::CheckboxHotkey("Freeze Time", &freezeTime, "Freezes time");
|
||||
ImGui::SameLine();
|
||||
ImGui::CheckboxHotkey("Slow Motion", &slowMotion);
|
||||
ImGui::CheckboxHotkey("Slow Motion", &slowMotion, "Slows the game down to the speed specified on the \"Slow Motion Speed\" slider");
|
||||
|
||||
ImGui::EndDisabled();
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace Menu {
|
||||
|
||||
class Tab : MenuTab {
|
||||
public:
|
||||
Tab() : MenuTab("World", 3) {}
|
||||
Tab() : MenuTab("World", 5) {}
|
||||
void Update() override;
|
||||
void Render() override;
|
||||
|
||||
|
||||
+65
-19
@@ -5,7 +5,9 @@
|
||||
#define AddOffset(name, moduleName, pattern, type, retType)\
|
||||
static retType Get_## name () {\
|
||||
static retType name = NULL;\
|
||||
if (Utils::Memory::IsValidPtr(name)) return name;\
|
||||
static int i = 0;\
|
||||
if (Utils::Memory::IsValidPtr(name) || !GetModuleHandleA(moduleName) || i >= 10) return name;\
|
||||
i++;\
|
||||
return name=reinterpret_cast<retType>(Utils::SigScan::PatternScanner::FindPattern(moduleName, {pattern, type}));\
|
||||
}
|
||||
#define AddStaticOffset(name, off)\
|
||||
@@ -18,42 +20,72 @@ static DWORD64 Get_## name () {\
|
||||
static DWORD64 Get_## name () {\
|
||||
static DWORD64 name = 0;\
|
||||
if (Utils::Memory::IsValidPtr(name)) return name;\
|
||||
return name=reinterpret_cast<DWORD64>(GetModuleHandle(moduleName)) + static_cast<DWORD64>(off);\
|
||||
return name=reinterpret_cast<DWORD64>(GetModuleHandleA(moduleName)) + static_cast<DWORD64>(off);\
|
||||
}
|
||||
|
||||
#define AddVTOffset(name, moduleName, rttiName, retType)\
|
||||
static retType GetVT_## name () {\
|
||||
static retType VT_## name = NULL;\
|
||||
static int i = 0;\
|
||||
if (Utils::Memory::IsValidPtr(VT_## name)|| !GetModuleHandleA(moduleName) || i >= 10) return VT_## name;\
|
||||
i++;\
|
||||
return VT_## name=reinterpret_cast<retType>(Utils::RTTI::GetVTablePtr(moduleName, rttiName));\
|
||||
}
|
||||
|
||||
struct Offsets {
|
||||
// ntdll.dll
|
||||
//AddOffset(LdrpCallInitRoutine, "ntdll.dll", "[48 89 5C 24 08 44 89 44 24 18 48", PatternType::Address, PDWORD64)
|
||||
//AddOffset(LdrpRunInitializeRoutines, "ntdll.dll", "[48 89 4C 24 08 53 56 57 41 54 41 55 41 56 41 57 48 81 EC 90", PatternType::Address, PDWORD64) // for win7
|
||||
|
||||
// Input related
|
||||
AddOffset(g_CInput, "engine_x64_rwdi.dll", "48 8B 0D [?? ?? ?? ?? 48 85 C9 74 ?? 48 8B 01 84 D2", Utils::SigScan::PatternType::RelativePointer, PDWORD64*)
|
||||
//AddOffset(WndProc, "engine_x64_rwdi.dll", "40 55 56 57 41 54 41 56 48 83 EC ?? 49 8B E9", PatternType::Address, LPVOID)
|
||||
AddOffset(g_CInput, "engine_x64_rwdi.dll", "48 8B 0D [?? ?? ?? ?? 48 85 C9 74 ?? 48 8B 01 84 D2", Utils::SigScan::PatternType::RelativePointer, DWORD64**)
|
||||
|
||||
// Player vars related
|
||||
AddStaticOffset(LoadPlayerVariableFunc_size, 0x14E)
|
||||
//AddOffset(LoadPlayerFloatVariable, "gamedll_ph_x64_rwdi.dll", "E8 [?? ?? ?? ?? 48 8B D0 48 8D 8C 24 ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 8D 94 24 ?? ?? ?? ?? 48 8B 8C 24 ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 8D 8C 24 ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 8D 8C 24 ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 8B 84 24 ?? ?? ?? ??", PatternType::RelativePointer, PDWORD64);
|
||||
AddOffset(InitializePlayerVariables, "gamedll_ph_x64_rwdi.dll", "E8 [?? ?? ?? ?? 48 8B F0 48 8B CF", Utils::SigScan::PatternType::RelativePointer, DWORD64)
|
||||
AddStaticOffset(initPlayerFloatVarsInstr_offset, 0x99);
|
||||
AddStaticOffset(initPlayerBoolVarsInstr_offset, 0x2E7);
|
||||
AddOffset(PlayerState, "gamedll_ph_x64_rwdi.dll", "4C 8B 35 [?? ?? ?? ?? 4C 8B E2", Utils::SigScan::PatternType::RelativePointer, LPVOID)
|
||||
AddVTOffset(FloatPlayerVariable, "gamedll_ph_x64_rwdi.dll", "FloatPlayerVariable", LPVOID)
|
||||
AddVTOffset(BoolPlayerVariable, "gamedll_ph_x64_rwdi.dll", "BoolPlayerVariable", LPVOID)
|
||||
AddVTOffset(TypedFieldMetaFloatPlayerVariable, "gamedll_ph_x64_rwdi.dll", "?$TypedFieldMeta@VFloatPlayerVariable@@@?$FieldsCollection@VPlayerVariables@@@constds", LPVOID)
|
||||
AddVTOffset(TypedFieldMetaBoolPlayerVariable, "gamedll_ph_x64_rwdi.dll", "?$TypedFieldMeta@VBoolPlayerVariable@@@?$FieldsCollection@VPlayerVariables@@@constds", LPVOID)
|
||||
AddOffset(LoadPlayerVars, "gamedll_ph_x64_rwdi.dll", "48 89 4C 24 ?? B8 ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 2B E0 48 8B 8C 24", Utils::SigScan::PatternType::Address, LPVOID)
|
||||
AddOffset(PlayerState, "gamedll_ph_x64_rwdi.dll", "48 8B 35 [?? ?? ?? ?? 4C 8B F2 48 8B F9", Utils::SigScan::PatternType::RelativePointer, LPVOID)
|
||||
|
||||
// Game related
|
||||
AddVTOffset(CBulletPhysicsCharacter, "engine_x64_rwdi.dll", "CBulletPhysicsCharacter", LPVOID)
|
||||
AddVTOffset(CGSObject, "engine_x64_rwdi.dll", "CGSObject", LPVOID)
|
||||
AddVTOffset(CInput, "engine_x64_rwdi.dll", "CInput", LPVOID)
|
||||
AddVTOffset(CLevel, "engine_x64_rwdi.dll", "CLevel", LPVOID)
|
||||
AddVTOffset(CLobbySteam, "engine_x64_rwdi.dll", "CLobbySteam", LPVOID)
|
||||
AddVTOffset(CVideoSettings, "engine_x64_rwdi.dll", "CVideoSettings", LPVOID)
|
||||
|
||||
AddVTOffset(DayNightCycle, "gamedll_ph_x64_rwdi.dll", "DayNightCycle", LPVOID)
|
||||
AddVTOffset(FreeCamera, "gamedll_ph_x64_rwdi.dll", "FreeCamera", LPVOID)
|
||||
AddVTOffset(GameDI_PH, "gamedll_ph_x64_rwdi.dll", "GameDI_PH", LPVOID)
|
||||
AddVTOffset(InventoryContainerDI, "gamedll_ph_x64_rwdi.dll", "InventoryContainerDI", LPVOID)
|
||||
AddVTOffset(InventoryItem, "gamedll_ph_x64_rwdi.dll", "InventoryItem", LPVOID)
|
||||
AddVTOffset(InventoryMoney, "gamedll_ph_x64_rwdi.dll", "InventoryMoney", LPVOID)
|
||||
AddVTOffset(ItemDescWithContext, "gamedll_ph_x64_rwdi.dll", "ItemDescWithContext", LPVOID)
|
||||
AddVTOffset(LevelDI, "gamedll_ph_x64_rwdi.dll", "LevelDI", LPVOID)
|
||||
AddVTOffset(LocalClientDI, "gamedll_ph_x64_rwdi.dll", "LocalClientDI", LPVOID)
|
||||
AddVTOffset(LogicalPlayer, "gamedll_ph_x64_rwdi.dll", "LogicalPlayer", LPVOID)
|
||||
AddVTOffset(PlayerDI_PH, "gamedll_ph_x64_rwdi.dll", "PlayerDI_PH", LPVOID)
|
||||
AddVTOffset(PlayerState, "gamedll_ph_x64_rwdi.dll", "PlayerState", LPVOID)
|
||||
AddVTOffset(SessionCooperativeDI, "gamedll_ph_x64_rwdi.dll", "SessionCooperativeDI", LPVOID)
|
||||
AddVTOffset(TPPCameraDI, "gamedll_ph_x64_rwdi.dll", "TPPCameraDI", LPVOID)
|
||||
|
||||
AddStaticOffset(gameDI_PH2_offset, 0x28)
|
||||
AddStaticOffset(allowVelocityMod_offset, 0x5C)
|
||||
AddStaticOffset(disableHeadCorrection_offset, 0x108)
|
||||
AddOffset(CLobbySteam, "engine_x64_rwdi.dll", "48 8B 05 [?? ?? ?? ?? 48 85 C0 74 ?? 48 83 C0", Utils::SigScan::PatternType::RelativePointer, LPVOID)
|
||||
AddOffset(g_PlayerObjProperties, "gamedll_ph_x64_rwdi.dll", "48 89 0D [?? ?? ?? ?? E8 ?? ?? ?? ?? 48 85 C0", Utils::SigScan::PatternType::RelativePointer, LPVOID)
|
||||
//AddOffset(g_PlayerDI_PH, "gamedll_ph_x64_rwdi.dll", "48 89 0D [?? ?? ?? ?? E8 ?? ?? ?? ?? 48 85 C0", Utils::SigScan::PatternType::RelativePointer, LPVOID) // also PlayerObjProperties
|
||||
AddOffset(g_DayNightCycle, "gamedll_ph_x64_rwdi.dll", "48 8B 0D [?? ?? ?? ?? 48 85 C9 74 ?? E8 ?? ?? ?? ?? 84 C0 74 ?? B0 ?? 48 83 C4 ?? C3 32 C0", Utils::SigScan::PatternType::RelativePointer, LPVOID)
|
||||
//AddOffset(g_CameraFPPDI, "gamedll_ph_x64_rwdi.dll", "48 89 05 [?? ?? ?? ?? 40 84 FF", PatternType::RelativePointer, PDWORD64)
|
||||
AddOffset(g_FreeCamera, "gamedll_ph_x64_rwdi.dll", "48 89 05 [?? ?? ?? ?? 48 89 4C 24", Utils::SigScan::PatternType::RelativePointer, PDWORD64)
|
||||
//AddOffset(CameraFPPDI_VT, "gamedll_ph_x64_rwdi.dll", "48 8D 05 [?? ?? ?? ?? 48 89 07 48 8D 4F 60", PatternType::RelativePointer, DWORD64)
|
||||
//AddOffset(g_CameraFPPDI, "gamedll_ph_x64_rwdi.dll", "48 89 05 [?? ?? ?? ?? 40 84 FF", PatternType::RelativePointer, DWORD64*)
|
||||
AddOffset(g_FreeCamera, "gamedll_ph_x64_rwdi.dll", "48 89 05 [?? ?? ?? ?? 48 89 4C 24", Utils::SigScan::PatternType::RelativePointer, DWORD64*)
|
||||
AddOffset(SaveGameCRCBoolCheck, "gamedll_ph_x64_rwdi.dll", "FF 50 ?? [40 22 DF 0F 85 ?? ?? ?? ?? 0F B6 05 ?? ?? ?? ?? 48 8D 3D", Utils::SigScan::PatternType::Address, LPVOID)
|
||||
|
||||
// Functions
|
||||
AddOffset(ReadVideoSettings, "engine_x64_rwdi.dll", "48 89 5C 24 ?? 48 89 6C 24 ?? 48 89 74 24 ?? 57 48 83 EC ?? 48 8B FA 48 8B D9 45 84 C0", Utils::SigScan::PatternType::Address, LPVOID)
|
||||
AddOffset(MountDataPaks, "engine_x64_rwdi.dll", "4C 8B DC 4D 89 4B ?? 45 89 43 ?? 89 54 24 ?? 49 89 4B", Utils::SigScan::PatternType::Address, LPVOID)
|
||||
AddOffset(MoveCameraFromForwardUpPos, "engine_x64_rwdi.dll", "48 89 5C 24 ?? 57 48 83 EC ?? 49 8B C1 48 8B F9", Utils::SigScan::PatternType::Address, LPVOID)
|
||||
AddOffset(CalculateFreeCamCollision, "gamedll_ph_x64_rwdi.dll", "48 8B C4 55 53 56 57 48 8D A8 ?? ?? ?? ?? 48 81 EC ?? ?? ?? ?? 83 B9", Utils::SigScan::PatternType::Address, LPVOID)
|
||||
AddOffset(AllowCameraMovement, "gamedll_ph_x64_rwdi.dll", "89 91 ?? ?? ?? ?? C3 CC CC CC CC CC CC CC CC CC 48 8B C4 55 56", Utils::SigScan::PatternType::Address, LPVOID)
|
||||
//AddOffset(GetViewCamera, "engine_x64_rwdi.dll", "E8 [?? ?? ?? ?? 48 85 C0 74 28 48 8B C8", PatternType::RelativePointer, LPVOID)
|
||||
AddOffset(CreatePlayerHealthModule, "gamedll_ph_x64_rwdi.dll", "48 89 5C 24 ?? 55 56 57 41 54 41 55 41 56 41 57 48 8D 6C 24 ?? 48 81 EC ?? ?? ?? ?? 4C 8B F1 E8 ?? ?? ?? ?? 48 8D 05", Utils::SigScan::PatternType::Address, LPVOID)
|
||||
AddOffset(CreatePlayerInfectionModule, "gamedll_ph_x64_rwdi.dll", "48 89 5C 24 ?? 57 48 83 EC ?? 48 8B D9 E8 ?? ?? ?? ?? 33 FF 66 C7 44 24 ?? ?? ?? 48 8D 05 ?? ?? ?? ?? 48 89 03", Utils::SigScan::PatternType::Address, LPVOID)
|
||||
AddOffset(LifeSetHealth, "gamedll_ph_x64_rwdi.dll", "F3 0F 11 49 ?? F3 0F 11 49 ?? F3 0F 11 49 ?? C3", Utils::SigScan::PatternType::Address, LPVOID)
|
||||
AddOffset(TogglePhotoMode1, "gamedll_ph_x64_rwdi.dll", "48 83 EC ?? 38 91 ?? ?? ?? ?? 0F 84", Utils::SigScan::PatternType::Address, LPVOID)
|
||||
AddOffset(TogglePhotoMode2, "gamedll_ph_x64_rwdi.dll", "48 89 5C 24 ?? 57 48 83 EC ?? 48 8B D9 41 0F B6 F8 48 8B 0D", Utils::SigScan::PatternType::Address, LPVOID)
|
||||
@@ -61,10 +93,24 @@ struct Offsets {
|
||||
AddOffset(ShowTPPModelFunc2, "gamedll_ph_x64_rwdi.dll", "40 53 48 83 EC ?? 48 8B 01 48 8B D9 FF 90 ?? ?? ?? ?? 84 C0 74 ?? 48 8B 83 ?? ?? ?? ?? 48 8B 88 ?? ?? ?? ?? 48 85 C9 74 ?? 48 83 B9 ?? ?? ?? ?? ?? 74 ?? 48 8B 81", Utils::SigScan::PatternType::Address, LPVOID)
|
||||
AddOffset(ShowTPPModelFunc3, "gamedll_ph_x64_rwdi.dll", "48 83 EC ?? 38 91 ?? ?? ?? ?? 74 ?? 88 91", Utils::SigScan::PatternType::Address, LPVOID)
|
||||
//AddOffset(CalculateOutOfBoundsTimer, "gamedll_ph_x64_rwdi.dll", "48 89 5C 24 ?? 48 89 74 24 ?? 57 48 81 EC ?? ?? ?? ?? 0F B6 99", PatternType::Address, LPVOID)
|
||||
AddOffset(IsNotOutOfBounds, "gamedll_ph_x64_rwdi.dll", "48 89 5C 24 ?? 48 89 6C 24 ?? 48 89 74 24 ?? 57 41 56 41 57 48 83 EC ?? 4C 8B F9 48 85 D2", Utils::SigScan::PatternType::Address, LPVOID)
|
||||
AddOffset(IsNotOutOfMapBounds, "gamedll_ph_x64_rwdi.dll", "48 89 5C 24 ?? 48 89 6C 24 ?? 48 89 74 24 ?? 57 41 56 41 57 48 83 EC ?? 4C 8B F9 48 85 D2", Utils::SigScan::PatternType::Address, LPVOID)
|
||||
AddOffset(IsNotOutOfMissionBounds, "gamedll_ph_x64_rwdi.dll", "48 89 5C 24 ?? 57 48 83 EC ?? 48 8B F9 48 85 D2 74 ?? 48 8D 8A", Utils::SigScan::PatternType::Address, LPVOID)
|
||||
AddOffset(ReloadJumps, "gamedll_ph_x64_rwdi.dll", "48 83 EC ?? E8 ?? ?? ?? ?? 48 8D 15", Utils::SigScan::PatternType::Address, LPVOID)
|
||||
AddOffset(PlaySoundEvent, "gamedll_ph_x64_rwdi.dll", "4C 8B DC 49 89 5B ?? 49 89 73 ?? 57 48 81 EC ?? ?? ?? ?? 48 8B 44 24 ?? 48 8B F9 48 8B DA", Utils::SigScan::PatternType::Address, LPVOID)
|
||||
AddOffset(CalculateFallHeight, "gamedll_ph_x64_rwdi.dll", "40 55 56 48 8D AC 24 ?? ?? ?? ?? 48 81 EC ?? ?? ?? ?? 44 0F 29 9C 24", Utils::SigScan::PatternType::Address, LPVOID)
|
||||
AddOffset(PlayerHealthModuleKillPlayer, "gamedll_ph_x64_rwdi.dll", "40 53 48 83 EC ?? 48 8B 01 48 8B D9 FF 90 ?? ?? ?? ?? 84 C0 74 ?? 48 8B 4B ?? 48 81 C1 ?? ?? ?? ?? 48 8B 01 FF 50", Utils::SigScan::PatternType::Address, LPVOID)
|
||||
AddOffset(CanUseGrappleHook, "gamedll_ph_x64_rwdi.dll", "48 89 5C 24 ?? 57 48 83 EC ?? 48 8B 01 0F B6 FA 48 8B D9 FF 90 ?? ?? ?? ?? F6 80", Utils::SigScan::PatternType::Address, LPVOID)
|
||||
AddOffset(ReadPlayerJumpParams, "gamedll_ph_x64_rwdi.dll", "40 55 56 57 41 56 41 57 48 8D AC 24 ?? ?? ?? ?? 48 81 EC ?? ?? ?? ?? 4C 8B B5", Utils::SigScan::PatternType::Address, LPVOID)
|
||||
AddOffset(PlayerGetCurrentWeapon, "gamedll_ph_x64_rwdi.dll", "8B C2 48 8D 14 80 48 83 BC D1 ?? ?? ?? ?? ?? 74 ?? 48 8B 84 D1 ?? ?? ?? ?? C3 33 C0 C3 CC CC CC 8B C2", Utils::SigScan::PatternType::Address, LPVOID)
|
||||
AddOffset(PlayerGetInventoryMoney, "gamedll_ph_x64_rwdi.dll", "8B C2 48 8B 44 C1", Utils::SigScan::PatternType::Address, LPVOID)
|
||||
AddOffset(HandleInventoryItemsAmount, "gamedll_ph_x64_rwdi.dll", "48 89 5C 24 ?? 48 89 6C 24 ?? 48 89 74 24 ?? 57 48 83 EC ?? 8B 29", Utils::SigScan::PatternType::Address, LPVOID)
|
||||
AddOffset(SetNewWaypointLocation, "gamedll_ph_x64_rwdi.dll", "85 D2 78 ?? 48 89 74 24 ?? 57 48 83 EC ?? 49 8B F8", Utils::SigScan::PatternType::Address, LPVOID)
|
||||
AddOffset(SetNewWaypointLocationWaypointIsSetBoolInstr, "gamedll_ph_x64_rwdi.dll", "C6 84 33 [?? ?? ?? ?? 01 48 8B 5C 24", Utils::SigScan::PatternType::Address, DWORD*)
|
||||
AddOffset(HandleHeadBob, "gamedll_ph_x64_rwdi.dll", "40 53 48 83 EC ?? 0F 29 74 24 ?? 48 8D 51 ?? 0F 29 7C 24 ?? 0F 28 F3 0F 28 FA F3 0F 11 74 24 ?? F3 0F 10 51 ?? 0F 28 D9 44 0F 29 44 24 ?? 48 8B D9 F3 0F 11 7C 24 ?? 44 0F 28 C1 E8 ?? ?? ?? ?? F3 0F 10 53 ?? 48 8D 53 ?? F3 0F 11 74 24 ?? 48 8D 4B ?? 41 0F 28 D8 F3 0F 11 7C 24 ?? E8 ?? ?? ?? ?? F3 0F 10 53 ?? 48 8D 53 ?? F3 0F 11 74 24 ?? 48 8D 4B ?? 41 0F 28 D8 F3 0F 11 7C 24 ?? E8 ?? ?? ?? ?? F3 0F 10 53", Utils::SigScan::PatternType::Address, LPVOID)
|
||||
AddOffset(SomeFloatCalcFunc, "gamedll_ph_x64_rwdi.dll", "48 89 5C 24 ?? 57 48 81 EC ?? ?? ?? ?? F3 0F 10 0D", Utils::SigScan::PatternType::Address, LPVOID)
|
||||
//AddOffset(CompareAndUpdateFloat, "gamedll_ph_x64_rwdi.dll", "0F 2F C1 73 ?? 0F 28 C1 C3", Utils::SigScan::PatternType::Address, LPVOID)
|
||||
//AddOffset(HandlePlayerImmunity, "gamedll_ph_x64_rwdi.dll", "48 8B C4 53 56 57 41 56 41 57", Utils::SigScan::PatternType::Address, LPVOID)
|
||||
//AddOffset(HandlePlayerImmunity2, "gamedll_ph_x64_rwdi.dll", "40 55 56 41 56 41 57 48 8D 6C 24 ?? 48 81 EC ?? ?? ?? ?? 48 8B F1 45 0F B6 F0", Utils::SigScan::PatternType::Address, LPVOID)
|
||||
//AddOffset(HandleFallHeight, "gamedll_ph_x64_rwdi.dll", "48 89 5C 24 ?? 57 48 83 EC ?? 0F B6 FA 48 8B D9 0F B6 91", Utils::SigScan::PatternType::Address, LPVOID)
|
||||
//AddOffset(HandlePlayerFall, "gamedll_ph_x64_rwdi.dll", "48 89 5C 24 ?? 57 48 83 EC ?? 0F 29 74 24 ?? 48 8B FA 0F 28 F2", Utils::SigScan::PatternType::Address, LPVOID)
|
||||
//AddOffset(GetTimeWeatherSystem, "engine_x64_rwdi.dll", "E8 [?? ?? ?? ?? 33 D2 48 8B C8 E8 ?? ?? ?? ?? 49 8D 4F 38", PatternType::RelativePointer, LPVOID)
|
||||
|
||||
+128
-14
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
#include <functional>
|
||||
#include <set>
|
||||
#include <atomic>
|
||||
#include "..\MinHook\MinHook.h"
|
||||
|
||||
namespace Utils {
|
||||
@@ -28,22 +29,118 @@ namespace Utils {
|
||||
~HookBase();
|
||||
static std::set<HookBase*>* GetInstances();
|
||||
|
||||
virtual void HookLoop() {};
|
||||
virtual bool HookLoop() { return false; };
|
||||
|
||||
const std::string_view name;
|
||||
const std::string_view name{};
|
||||
std::atomic<bool> isHooking = false;
|
||||
std::atomic<bool> isHooked = false;
|
||||
};
|
||||
template <typename GetTargetOffsetRetType>
|
||||
class ByteHook : HookBase {
|
||||
public:
|
||||
ByteHook(const std::string_view& name, GetTargetOffsetRetType(*pGetOffsetFunc)(), unsigned char* patchBytes, size_t bytesAmount, Option* optionRef = nullptr) : HookBase(name), pGetOffsetFunc(pGetOffsetFunc), patchBytes(patchBytes), bytesAmount(bytesAmount), optionRef(optionRef) {}
|
||||
|
||||
bool HookLoop() override {
|
||||
if (isHooked || (optionRef && !optionRef->GetValue()))
|
||||
return true;
|
||||
if (isHooking)
|
||||
return true;
|
||||
|
||||
isHooking = true;
|
||||
timeSpentHooking = Utils::Time::Timer(120000);
|
||||
|
||||
while (true) {
|
||||
if (timeSpentHooking.DidTimePass()) {
|
||||
spdlog::error("Failed hooking \"{}\" after 120 seconds", name);
|
||||
isHooking = false;
|
||||
return false;
|
||||
}
|
||||
if (!pGetOffsetFunc || !pGetOffsetFunc())
|
||||
continue;
|
||||
|
||||
DWORD originalProtection = 0;
|
||||
DWORD oldProtection = 0;
|
||||
|
||||
VirtualProtect(pGetOffsetFunc(), bytesAmount, PAGE_EXECUTE_READWRITE, &originalProtection);
|
||||
if (!origBytes) {
|
||||
origBytes = new unsigned char[bytesAmount];
|
||||
memcpy_s(origBytes, bytesAmount, pGetOffsetFunc(), bytesAmount);
|
||||
}
|
||||
memcpy_s(pGetOffsetFunc(), bytesAmount, patchBytes, bytesAmount);
|
||||
VirtualProtect(pGetOffsetFunc(), bytesAmount, originalProtection, &oldProtection);
|
||||
isHooked = true;
|
||||
isHooking = false;
|
||||
return true;
|
||||
|
||||
Sleep(10);
|
||||
}
|
||||
}
|
||||
|
||||
void Enable() {
|
||||
if (isHooked)
|
||||
return;
|
||||
|
||||
DWORD originalProtection = 0;
|
||||
DWORD oldProtection = 0;
|
||||
|
||||
VirtualProtect(pGetOffsetFunc(), bytesAmount, PAGE_EXECUTE_READWRITE, &originalProtection);
|
||||
if (!origBytes) {
|
||||
origBytes = new unsigned char[bytesAmount];
|
||||
memcpy_s(origBytes, bytesAmount, pGetOffsetFunc(), bytesAmount);
|
||||
}
|
||||
memcpy_s(pGetOffsetFunc(), bytesAmount, patchBytes, bytesAmount);
|
||||
VirtualProtect(pGetOffsetFunc(), bytesAmount, originalProtection, &oldProtection);
|
||||
isHooked = true;
|
||||
}
|
||||
void Disable() {
|
||||
if (!isHooked)
|
||||
return;
|
||||
|
||||
DWORD originalProtection = 0;
|
||||
DWORD oldProtection = 0;
|
||||
|
||||
VirtualProtect(pGetOffsetFunc(), bytesAmount, PAGE_EXECUTE_READWRITE, &originalProtection);
|
||||
memcpy_s(pGetOffsetFunc(), bytesAmount, origBytes, bytesAmount);
|
||||
VirtualProtect(pGetOffsetFunc(), bytesAmount, originalProtection, &oldProtection);
|
||||
isHooked = false;
|
||||
}
|
||||
void Toggle() {
|
||||
if (!optionRef) {
|
||||
isHooked ? Disable() : Enable();
|
||||
return;
|
||||
}
|
||||
|
||||
optionRef->GetValue() ? Enable() : Disable();
|
||||
}
|
||||
|
||||
Option* optionRef = nullptr;
|
||||
private:
|
||||
GetTargetOffsetRetType(*pGetOffsetFunc)() = nullptr;
|
||||
unsigned char* origBytes = nullptr;
|
||||
unsigned char* patchBytes = nullptr;
|
||||
size_t bytesAmount = 0;
|
||||
|
||||
Utils::Time::Timer timeSpentHooking{ 120000 };
|
||||
};
|
||||
template <typename GetTargetOffsetRetType, typename OrigType>
|
||||
class MHook : HookBase {
|
||||
public:
|
||||
MHook(const std::string_view& name, GetTargetOffsetRetType(*pGetOffsetFunc)(), OrigType pDetour) : HookBase(name), pGetOffsetFunc(pGetOffsetFunc), pDetour(pDetour) {}
|
||||
|
||||
void HookLoop() override {
|
||||
timeSpentHooking = Utils::Time::Timer(60000);
|
||||
bool HookLoop() override {
|
||||
if (pOriginal)
|
||||
return true;
|
||||
if (isHooking)
|
||||
return true;
|
||||
|
||||
isHooking = true;
|
||||
timeSpentHooking = Utils::Time::Timer(120000);
|
||||
|
||||
while (true) {
|
||||
if (timeSpentHooking.DidTimePass()) {
|
||||
spdlog::error("Failed hooking function \"{}\" after 60 seconds", name);
|
||||
break;
|
||||
spdlog::error("Failed hooking function \"{}\" after 120 seconds", name);
|
||||
isHooking = false;
|
||||
return false;
|
||||
}
|
||||
if (!pGetOffsetFunc)
|
||||
continue;
|
||||
@@ -52,8 +149,12 @@ namespace Utils {
|
||||
pTarget = reinterpret_cast<OrigType>(pGetOffsetFunc());
|
||||
else if (!pOriginal && MH_CreateHook(pTarget, pDetour, reinterpret_cast<LPVOID*>(&pOriginal)) == MH_OK) {
|
||||
MH_EnableHook(pTarget);
|
||||
break;
|
||||
isHooked = true;
|
||||
isHooking = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
Sleep(10);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,20 +164,27 @@ namespace Utils {
|
||||
GetTargetOffsetRetType(*pGetOffsetFunc)() = nullptr;
|
||||
OrigType pDetour = nullptr;
|
||||
|
||||
Utils::Time::Timer timeSpentHooking{ 60000 };
|
||||
Utils::Time::Timer timeSpentHooking{ 120000 };
|
||||
};
|
||||
template <typename GetTargetOffsetRetType, typename OrigType>
|
||||
class VTHook : HookBase {
|
||||
public:
|
||||
VTHook(const std::string_view& name, GetTargetOffsetRetType(*pGetOffsetFunc)(), OrigType pDetour, DWORD offset) : HookBase(name), pGetOffsetFunc(pGetOffsetFunc), pDetour(pDetour), offset(offset) {}
|
||||
|
||||
void HookLoop() override {
|
||||
timeSpentHooking = Utils::Time::Timer(60000);
|
||||
bool HookLoop() override {
|
||||
if (pOriginal)
|
||||
return true;
|
||||
if (isHooking)
|
||||
return true;
|
||||
|
||||
isHooking = true;
|
||||
timeSpentHooking = Utils::Time::Timer(120000);
|
||||
|
||||
while (true) {
|
||||
if (timeSpentHooking.DidTimePass()) {
|
||||
spdlog::error("Failed hooking function \"{}\" after 60 seconds", name);
|
||||
break;
|
||||
spdlog::error("Failed hooking function \"{}\" after 120 seconds", name);
|
||||
isHooking = false;
|
||||
return false;
|
||||
}
|
||||
if (!pGetOffsetFunc)
|
||||
continue;
|
||||
@@ -85,8 +193,14 @@ namespace Utils {
|
||||
pInstance = pGetOffsetFunc();
|
||||
else if (!pOriginal) {
|
||||
HookVT(pInstance, pDetour, reinterpret_cast<LPVOID*>(&pOriginal), offset);
|
||||
break;
|
||||
if (pOriginal) {
|
||||
isHooked = true;
|
||||
isHooking = false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
Sleep(10);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,7 +210,7 @@ namespace Utils {
|
||||
LPVOID pInstance = nullptr;
|
||||
OrigType pDetour = nullptr;
|
||||
|
||||
Utils::Time::Timer timeSpentHooking{ 60000 };
|
||||
Utils::Time::Timer timeSpentHooking{ 120000 };
|
||||
|
||||
DWORD offset = 0x0;
|
||||
};
|
||||
|
||||
@@ -3,13 +3,23 @@
|
||||
namespace Utils {
|
||||
namespace Memory {
|
||||
const MODULEINFO GetModuleInfo(const char* szModule) {
|
||||
const HMODULE hModule = GetModuleHandle(szModule);
|
||||
if (!szModule)
|
||||
return MODULEINFO();
|
||||
|
||||
static std::unordered_map<std::string_view, MODULEINFO> moduleInfoCache;
|
||||
auto it = moduleInfoCache.find(szModule);
|
||||
if (it != moduleInfoCache.end())
|
||||
return it->second;
|
||||
|
||||
HMODULE hModule = GetModuleHandle(szModule);
|
||||
if (hModule == 0)
|
||||
return MODULEINFO();
|
||||
|
||||
MODULEINFO moduleInfo{};
|
||||
GetModuleInformation(GetCurrentProcess(), hModule, &moduleInfo, sizeof(MODULEINFO));
|
||||
return moduleInfo;
|
||||
moduleInfoCache[szModule] = moduleInfo;
|
||||
|
||||
return moduleInfoCache[szModule];
|
||||
}
|
||||
const FARPROC GetProcAddr(const std::string_view& module, const std::string_view& funcName) {
|
||||
const HMODULE moduleHandle = GetModuleHandleA(module.data());
|
||||
@@ -26,5 +36,74 @@ namespace Utils {
|
||||
const DWORD64 moduleEndPoint = moduleEntryPoint + moduleInf.SizeOfImage;
|
||||
return ptr && (ptr <= moduleEndPoint && ptr >= moduleEntryPoint);
|
||||
}
|
||||
|
||||
std::string BytesToIDAPattern(BYTE* bytes, size_t size) {
|
||||
std::stringstream idaPattern;
|
||||
idaPattern << std::hex << std::uppercase << std::setfill('0');
|
||||
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
const int currentByte = bytes[i];
|
||||
if (currentByte != SigScanWildCard)
|
||||
idaPattern << std::setw(2) << currentByte;
|
||||
else
|
||||
idaPattern << "??";
|
||||
|
||||
if (i != size - 1)
|
||||
idaPattern << " ";
|
||||
}
|
||||
|
||||
return idaPattern.str();
|
||||
}
|
||||
std::string ConvertSigToScannerSig(const char* pattern, int* offsetToAddrInSig) {
|
||||
size_t len = strlen(pattern);
|
||||
|
||||
std::string patt{};
|
||||
int bytesCounted = 0;
|
||||
|
||||
for (size_t i = 0; i < len;) {
|
||||
if (pattern[i] == ' ' || i == len - 1)
|
||||
bytesCounted++;
|
||||
|
||||
if (pattern[i] == '[') {
|
||||
i++;
|
||||
if (offsetToAddrInSig)
|
||||
*offsetToAddrInSig = static_cast<int>(bytesCounted);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (pattern[i] == '?') {
|
||||
patt += SigScanWildCardStr;
|
||||
i += (pattern[static_cast<DWORD64>(i) + 1] == '?') ? 2 : 1;
|
||||
} else {
|
||||
patt.push_back(pattern[i]);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
return patt;
|
||||
}
|
||||
DWORD64 CalcTargetAddrOfRelInst(DWORD64 addrOfInst, size_t opSize) {
|
||||
int offset = *reinterpret_cast<int*>(addrOfInst + opSize);
|
||||
|
||||
return addrOfInst + opSize + 4 + offset;
|
||||
}
|
||||
std::vector<DWORD64> GetXrefsTo(DWORD64 address, DWORD64 start, size_t size) {
|
||||
std::vector<DWORD64> xrefs = {};
|
||||
|
||||
const std::string idaPattern = BytesToIDAPattern(reinterpret_cast<BYTE*>(&address), 8);
|
||||
const DWORD64 end = start + size;
|
||||
|
||||
while (start && start < end) {
|
||||
DWORD64 xref = reinterpret_cast<DWORD64>(Utils::SigScan::PatternScanner::FindPattern(reinterpret_cast<LPVOID>(start), size, { idaPattern.c_str(), Utils::SigScan::PatternType::Address }));
|
||||
|
||||
if (!xref)
|
||||
break;
|
||||
|
||||
xrefs.push_back(xref);
|
||||
start = xref + 8;
|
||||
}
|
||||
|
||||
return xrefs;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,14 +5,27 @@
|
||||
|
||||
namespace Utils {
|
||||
namespace Memory {
|
||||
static const BYTE SigScanWildCard = 0xAA;
|
||||
static const std::string_view SigScanWildCardStr = "AA";
|
||||
|
||||
extern const MODULEINFO GetModuleInfo(const char* szModule);
|
||||
extern const FARPROC GetProcAddr(const std::string_view& module, const std::string_view& funcName);
|
||||
|
||||
extern const bool IsAddressValidMod(const DWORD64 ptr, const char* moduleName);
|
||||
|
||||
extern std::string BytesToIDAPattern(BYTE* bytes, size_t size);
|
||||
extern std::string ConvertSigToScannerSig(const char* pattern, int* offsetToAddrInSig = nullptr);
|
||||
|
||||
extern DWORD64 CalcTargetAddrOfRelInst(DWORD64 addrOfInst, size_t opSize);
|
||||
std::vector<DWORD64> GetXrefsTo(DWORD64 address, DWORD64 start, size_t size);
|
||||
|
||||
// Templates
|
||||
template<typename ptrT> bool IsValidPtr(ptrT ptr) {
|
||||
return !IsBadReadPtr(reinterpret_cast<LPVOID>(ptr), sizeof(LPVOID));
|
||||
__try {
|
||||
return !IsBadReadPtr(reinterpret_cast<LPVOID>(ptr), sizeof(LPVOID));
|
||||
} __except(EXCEPTION_EXECUTE_HANDLER) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
template<typename ptrT = LPVOID> bool IsValidPtrMod(ptrT ptr, const char* moduleName, const bool checkForVT = true) {
|
||||
return IsValidPtr<ptrT>(ptr) && IsAddressValidMod(checkForVT ? *(PDWORD64)(ptr) : (DWORD64)(ptr), moduleName);
|
||||
|
||||
@@ -0,0 +1,130 @@
|
||||
#include <pch.h>
|
||||
|
||||
namespace Utils {
|
||||
namespace RTTI {
|
||||
static std::vector<DWORD64> getXrefsTo(DWORD64 moduleBaseAddr, DWORD64 address, DWORD64 start, size_t size) {
|
||||
std::vector<DWORD64> xrefs = {};
|
||||
|
||||
const DWORD64 finalOffset = address - moduleBaseAddr;
|
||||
const std::string idaPattern = Memory::BytesToIDAPattern(reinterpret_cast<BYTE*>(const_cast<DWORD64*>(&finalOffset)), 4);
|
||||
std::string patt = Memory::ConvertSigToScannerSig(idaPattern.c_str());
|
||||
|
||||
// Get the end of the section (in our case the end of the .rdata section)
|
||||
const DWORD64 end = start + size;
|
||||
|
||||
while (start && start < end) {
|
||||
const auto scanner = memscan::mapped_region_t(start, end);
|
||||
auto patternFind = scanner.find_pattern<ms_uptr_t>(patt);
|
||||
|
||||
// If the xref is 0 it means that there either were no xrefs, or there are no remaining xrefs.
|
||||
// So we should break out of our loop, otherwise it will keep on trying to look for xrefs.
|
||||
if (!patternFind.has_value())
|
||||
break;
|
||||
|
||||
// We've found an xref, save it in the vector, and add 8 to start, so it wil now search for xrefs
|
||||
// from the previously found xref untill we're at the end of the section, or there aren't any xrefs left.
|
||||
xrefs.push_back(patternFind.value());
|
||||
start = patternFind.value() + 8;
|
||||
}
|
||||
|
||||
return xrefs;
|
||||
}
|
||||
static bool getSectionInfo(DWORD64 baseAddress, const char* sectionName, DWORD64& sectionStart, DWORD64& sectionSize) {
|
||||
const PIMAGE_DOS_HEADER dosHeader = reinterpret_cast<PIMAGE_DOS_HEADER>(baseAddress);
|
||||
if (dosHeader->e_magic != IMAGE_DOS_SIGNATURE)
|
||||
return false;
|
||||
|
||||
const PIMAGE_NT_HEADERS32 ntHeaders = reinterpret_cast<PIMAGE_NT_HEADERS32>(baseAddress + dosHeader->e_lfanew);
|
||||
if (ntHeaders->Signature != IMAGE_NT_SIGNATURE)
|
||||
return false;
|
||||
|
||||
PIMAGE_SECTION_HEADER sectionHeader = IMAGE_FIRST_SECTION(ntHeaders);
|
||||
USHORT numOfSections = ntHeaders->FileHeader.NumberOfSections;
|
||||
while (numOfSections > 0) {
|
||||
// If we're at the right section
|
||||
if (!strcmp(sectionName, (const char*)sectionHeader->Name)) {
|
||||
sectionStart = baseAddress + sectionHeader->VirtualAddress;
|
||||
sectionSize = sectionHeader->SizeOfRawData;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
sectionHeader++;
|
||||
numOfSections--;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
DWORD64 GetVTablePtr(const char* moduleName, const char* tableName) {
|
||||
if (!moduleName || !tableName)
|
||||
return 0;
|
||||
|
||||
DWORD64 baseAddress = reinterpret_cast<DWORD64>(GetModuleHandleA(moduleName));
|
||||
if (!baseAddress)
|
||||
return 0;
|
||||
|
||||
// Type descriptor names look like this: .?AVFloatPlayerVariable@@ (so: ".?AV" + table_name + "@@")
|
||||
const std::string typeDescriptorName = ".?AV" + std::string(tableName) + "@@";
|
||||
|
||||
// Convert the string to an IDA pattern so that we can pattern scan it
|
||||
std::string idaPattern = Memory::BytesToIDAPattern(reinterpret_cast<BYTE*>(const_cast<char*>(typeDescriptorName.data())), typeDescriptorName.size());
|
||||
|
||||
DWORD64 rttiTypeDescriptor = reinterpret_cast<DWORD64>(Utils::SigScan::PatternScanner::FindPattern(moduleName, { idaPattern.c_str(), Utils::SigScan::PatternType::Address }));
|
||||
if (!rttiTypeDescriptor)
|
||||
return 0;
|
||||
|
||||
// We're doing - 0x10 here, because the location of the rtti_type_descriptor is 0x10 bytes before the string (open up gamedll_ph_x64_rwdi.dll in IDA and take a look)
|
||||
rttiTypeDescriptor -= 0x10;
|
||||
|
||||
// We only need to get xrefs that are inside the .rdata section (there sometimes are xrefs in .text, so we have to filter them out)
|
||||
DWORD64 rdataStart = 0;
|
||||
DWORD64 rdataSize = 0;
|
||||
if (!getSectionInfo(baseAddress, ".rdata", rdataStart, rdataSize))
|
||||
return 0;
|
||||
|
||||
// Get all xrefs to the type_descriptor
|
||||
const std::vector<DWORD64> xrefs = getXrefsTo(baseAddress, rttiTypeDescriptor, rdataStart, rdataSize);
|
||||
for (const DWORD64 xref : xrefs) {
|
||||
// xref - 0x8 = offset of this vtable in complete class (from top)
|
||||
// So if it's 0 it means it's the class we need, and not some class it inherits from (again, opening up gamedll_ph_x64_rwdi.dll in IDA will help you understand)
|
||||
const int offsetFromClass = *reinterpret_cast<int*>(xref - 0x8);
|
||||
if (offsetFromClass != 0)
|
||||
continue;
|
||||
|
||||
// We've found the correct xref, the object locator is 0xC bytes before the xref. (Again, gamedll_ph_x64_rwdi.dll yada yada yada)
|
||||
const DWORD64 objectLocator = xref - 0xC;
|
||||
|
||||
// Now we need to get an xref to the object locator, as that's where the vtable is located
|
||||
{
|
||||
// Convert the object locator address to an IDA pattern
|
||||
idaPattern = Memory::BytesToIDAPattern(reinterpret_cast<BYTE*>(const_cast<DWORD64*>(&objectLocator)), 8);
|
||||
|
||||
const DWORD64 vtableAddr = reinterpret_cast<DWORD64>(Utils::SigScan::PatternScanner::FindPattern(reinterpret_cast<LPVOID>(rdataStart), rdataSize, { idaPattern.c_str(), Utils::SigScan::PatternType::Address })) + 0x8;
|
||||
|
||||
// Here I'm checking for <= 8 as we're adding 0x8 to it. So if the pattern scan returns 0 we still head the fuck out
|
||||
if (vtableAddr <= 8)
|
||||
continue;
|
||||
|
||||
return vtableAddr;
|
||||
|
||||
// We've now found the vtable address, however, we probably want a pointer to the vtable (which is in .text).
|
||||
// To do this, we're going to find a reference to the vtable address, and use that as pointer.
|
||||
|
||||
// If you don't need a pointer to the vtable in your implementation however, just return vtable_address
|
||||
/*DWORD64 textStart = 0;
|
||||
DWORD64 textSize = 0;
|
||||
if (!getSectionInfo(baseAddress, ".text", textStart, textSize))
|
||||
return nullptr;
|
||||
|
||||
// Convert the vtable address to an IDA pattern
|
||||
idaPattern = bytesToIDAPattern(reinterpret_cast<BYTE*>(const_cast<DWORD64*>(&vtableAddr)), 8);
|
||||
return reinterpret_cast<DWORD64*>(Utils::SigScan::PatternScanner::FindPattern(reinterpret_cast<LPVOID>(textStart), textSize, { idaPattern.c_str(), Utils::SigScan::PatternType::Address })) + 0x8;*/
|
||||
}
|
||||
}
|
||||
|
||||
// We for some odd reason didn't find any valid xrefs
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
#include "basetsd.h"
|
||||
|
||||
namespace Utils {
|
||||
namespace RTTI {
|
||||
extern DWORD64 GetVTablePtr(const char* moduleName, const char* tableName);
|
||||
}
|
||||
}
|
||||
@@ -2,17 +2,25 @@
|
||||
|
||||
namespace Utils {
|
||||
namespace SigScan {
|
||||
LPVOID PatternScanner::FindPattern(const std::string_view ModuleName, const Pattern& pattern) {
|
||||
return PatternScanner::FindPattern(GetModuleHandle(ModuleName.data()), Utils::Memory::GetModuleInfo(ModuleName.data()).SizeOfImage, pattern);
|
||||
LPVOID PatternScanner::FindPattern(const std::string_view moduleName, const Pattern& pattern) {
|
||||
HMODULE hModule = GetModuleHandleA(moduleName.data());
|
||||
if (!hModule)
|
||||
return nullptr;
|
||||
|
||||
return PatternScanner::FindPattern(hModule, Utils::Memory::GetModuleInfo(moduleName.data()).SizeOfImage, pattern);
|
||||
}
|
||||
LPVOID PatternScanner::FindPattern(const Pattern& pattern) {
|
||||
MODULEINFO hModuleInfo;
|
||||
GetModuleInformation(GetCurrentProcess(), GetModuleHandle(nullptr), &hModuleInfo, sizeof(hModuleInfo));
|
||||
return PatternScanner::FindPattern(GetModuleHandle(nullptr), hModuleInfo.SizeOfImage, pattern);
|
||||
GetModuleInformation(GetCurrentProcess(), GetModuleHandleA(nullptr), &hModuleInfo, sizeof(hModuleInfo));
|
||||
return PatternScanner::FindPattern(GetModuleHandleA(nullptr), hModuleInfo.SizeOfImage, pattern);
|
||||
}
|
||||
|
||||
std::vector<LPVOID> PatternScanner::FindPatterns(const std::string_view ModuleName, const Pattern& pattern) {
|
||||
return PatternScanner::FindPatterns(GetModuleHandle(ModuleName.data()), Utils::Memory::GetModuleInfo(ModuleName.data()).SizeOfImage, pattern);
|
||||
std::vector<LPVOID> PatternScanner::FindPatterns(const std::string_view moduleName, const Pattern& pattern) {
|
||||
HMODULE hModule = GetModuleHandleA(moduleName.data());
|
||||
if (!hModule)
|
||||
return {};
|
||||
|
||||
return PatternScanner::FindPatterns(hModule, Utils::Memory::GetModuleInfo(moduleName.data()).SizeOfImage, pattern);
|
||||
}
|
||||
std::vector<LPVOID> PatternScanner::FindPatterns(LPVOID startAddress, DWORD64 searchSize, const Pattern& pattern) {
|
||||
std::vector<LPVOID> ret;
|
||||
@@ -30,84 +38,16 @@ namespace Utils {
|
||||
}
|
||||
|
||||
LPVOID PatternScanner::FindPattern(LPVOID startAddress, DWORD64 searchSize, const Pattern& pattern) {
|
||||
size_t len = strlen(pattern.pattern);
|
||||
if (len == 0)
|
||||
return nullptr;
|
||||
|
||||
DWORD64 pos = 0;
|
||||
|
||||
size_t byteCount = 1;
|
||||
uint32_t i = 0;
|
||||
while (i < len - 1) {
|
||||
if (pattern.pattern[i] == ' ')
|
||||
byteCount++;
|
||||
i++;
|
||||
}
|
||||
|
||||
BYTE* patt = reinterpret_cast<BYTE*>(malloc(byteCount + 1));
|
||||
if (!patt)
|
||||
return nullptr;
|
||||
|
||||
BYTE* mask = reinterpret_cast<BYTE*>(malloc(byteCount + 1));
|
||||
if (!mask) {
|
||||
free(patt);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int offset = 0;
|
||||
int bytesCounted = 0;
|
||||
i = 0;
|
||||
while (i < len - 1) {
|
||||
if (pattern.pattern[i] == '[') {
|
||||
i++;
|
||||
offset = bytesCounted;
|
||||
}
|
||||
std::string patt = Memory::ConvertSigToScannerSig(pattern.pattern, &offset);
|
||||
|
||||
if (pattern.pattern[i] == '\0')
|
||||
break;
|
||||
|
||||
if (pattern.pattern[i] == '?' && pattern.pattern[i + 1] == '?') {
|
||||
mask[bytesCounted] = '?';
|
||||
patt[bytesCounted] = '\0';
|
||||
} else {
|
||||
BYTE hn = pattern.pattern[i] > '9' ? pattern.pattern[i] - 'A' + 10 : pattern.pattern[i] - '0';
|
||||
BYTE ln = pattern.pattern[i + 1] > '9' ? pattern.pattern[i + 1] - 'A' + 10 : pattern.pattern[i + 1] - '0';
|
||||
BYTE n = (hn << 4) | ln;
|
||||
|
||||
mask[bytesCounted] = 'x';
|
||||
patt[bytesCounted] = n;
|
||||
}
|
||||
|
||||
bytesCounted++;
|
||||
|
||||
i += 2;
|
||||
while (i < len && (pattern.pattern[i] == ' ' || pattern.pattern[i] == '\t' || pattern.pattern[i] == '\r' || pattern.pattern[i] == '\n'))
|
||||
i++;
|
||||
}
|
||||
if (bytesCounted <= byteCount)
|
||||
mask[bytesCounted] = '\0';
|
||||
|
||||
size_t searchLen = strlen(reinterpret_cast<char*>(&mask[0])) - 1;
|
||||
const auto scanner = memscan::mapped_region_t(reinterpret_cast<DWORD64>(startAddress), reinterpret_cast<DWORD64>(startAddress) + searchSize);
|
||||
auto patternFind = scanner.find_pattern<ms_uptr_t>(patt);
|
||||
|
||||
LPVOID ret = nullptr;
|
||||
for (DWORD64 retAddress = reinterpret_cast<DWORD64>(startAddress); retAddress < reinterpret_cast<DWORD64>(startAddress) + searchSize; retAddress++) {
|
||||
__try {
|
||||
if ((pos < bytesCounted && *reinterpret_cast<BYTE*>(retAddress) == patt[pos]) || mask[pos] == '?') {
|
||||
if (bytesCounted <= byteCount && pos < bytesCounted && mask[pos + 1] == '\0') {
|
||||
ret = reinterpret_cast<LPVOID>(retAddress - searchLen + offset);
|
||||
break;
|
||||
}
|
||||
|
||||
pos++;
|
||||
} else
|
||||
pos = 0;
|
||||
} __except (EXCEPTION_EXECUTE_HANDLER) {
|
||||
pos = 0;
|
||||
}
|
||||
}
|
||||
|
||||
free(patt);
|
||||
free(mask);
|
||||
if (patternFind.has_value())
|
||||
ret = reinterpret_cast<LPVOID>(patternFind.value() + offset);
|
||||
|
||||
switch (pattern.type) {
|
||||
case PatternType::Pointer:
|
||||
@@ -147,6 +87,7 @@ namespace Utils {
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
LPVOID PatternScanner::FindPattern(LPVOID startAddress, DWORD64 searchSize, const Pattern* patterns, float* ratio) {
|
||||
int totalCount = 0;
|
||||
struct result {
|
||||
|
||||
@@ -27,14 +27,14 @@ namespace Utils {
|
||||
class PatternScanner {
|
||||
public:
|
||||
static LPVOID FindPattern(LPVOID startAddress, DWORD64 searchSize, const Pattern& pattern);
|
||||
static LPVOID FindPattern(const std::string_view ModuleName, const Pattern& pattern);
|
||||
static LPVOID FindPattern(const std::string_view moduleName, const Pattern& pattern);
|
||||
static LPVOID FindPattern(const Pattern& pattern);
|
||||
|
||||
static std::vector<LPVOID> FindPatterns(const std::string_view ModuleName, const Pattern& pattern);
|
||||
static std::vector<LPVOID> FindPatterns(const std::string_view moduleName, const Pattern& pattern);
|
||||
static std::vector<LPVOID> FindPatterns(LPVOID startAddress, DWORD64 searchSize, const Pattern& pattern);
|
||||
|
||||
static LPVOID FindPattern(LPVOID startAddress, DWORD64 searchSize, const Pattern* patterns, float* ratio = nullptr);
|
||||
static LPVOID FindPattern(const std::string_view ModuleName, Pattern* patterns, float* ratio = nullptr);
|
||||
static LPVOID FindPattern(const std::string_view moduleName, Pattern* patterns, float* ratio = nullptr);
|
||||
private:
|
||||
template <typename T> static LPVOID ResolveRelativePtr(LPVOID Address) {
|
||||
if (!Address)
|
||||
|
||||
@@ -4,36 +4,24 @@ namespace Utils {
|
||||
namespace Time {
|
||||
Timer::Timer(long timeMs) : timeToPass(std::chrono::milliseconds(timeMs)), timePassed(false) {
|
||||
start = std::chrono::time_point_cast<std::chrono::milliseconds>(clock::now());
|
||||
end = start + timeToPass;
|
||||
}
|
||||
|
||||
const long long Timer::GetTimePassed() {
|
||||
if (timePassed)
|
||||
return -1;
|
||||
|
||||
const auto end = clock::now();
|
||||
const auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
|
||||
const auto currentClock = clock::now();
|
||||
const auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(currentClock - start);
|
||||
const long long timePassedMs = duration.count();
|
||||
|
||||
if (timePassedMs < 0) {
|
||||
start = std::chrono::time_point_cast<std::chrono::milliseconds>(clock::now());
|
||||
return -1;
|
||||
}
|
||||
return timePassedMs;
|
||||
}
|
||||
const bool Timer::DidTimePass() {
|
||||
if (timePassed)
|
||||
return timePassed;
|
||||
return true;
|
||||
|
||||
const auto end = clock::now();
|
||||
const auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
|
||||
const long long timePassedMs = duration.count();
|
||||
|
||||
if (timePassedMs < 0) {
|
||||
start = std::chrono::time_point_cast<std::chrono::milliseconds>(clock::now());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (duration >= timeToPass)
|
||||
if (clock::now() >= end)
|
||||
timePassed = true;
|
||||
return timePassed;
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
namespace Utils {
|
||||
namespace Time {
|
||||
class Timer {
|
||||
using clock = std::chrono::system_clock;
|
||||
using clock = std::chrono::steady_clock;
|
||||
using time_point_type = std::chrono::time_point<clock, std::chrono::milliseconds>;
|
||||
public:
|
||||
std::chrono::milliseconds timeToPass;
|
||||
@@ -16,6 +16,7 @@ namespace Utils {
|
||||
const bool DidTimePass();
|
||||
private:
|
||||
time_point_type start;
|
||||
time_point_type end;
|
||||
bool timePassed;
|
||||
};
|
||||
|
||||
|
||||
@@ -2,13 +2,23 @@
|
||||
|
||||
namespace Utils {
|
||||
namespace Values {
|
||||
const bool are_samef(float a, float b, float precision) { return abs(a - b) < precision; }
|
||||
bool str_ends_with_ci(std::string const& text, std::string const& substr) {
|
||||
if (substr.length() > text.length())
|
||||
return false;
|
||||
|
||||
auto it = std::search(text.rbegin(), text.rbegin() + substr.length(), substr.rbegin(), substr.rend(), [](char ch1, char ch2) {
|
||||
return std::toupper(ch1) == std::toupper(ch2);
|
||||
});
|
||||
return it == text.rbegin();
|
||||
}
|
||||
|
||||
bool are_samef(float a, float b, float precision) { return abs(a - b) < precision; }
|
||||
float round_decimal(float value, int decimal_places) {
|
||||
const double multiplier = std::pow(10.0f, decimal_places);
|
||||
return std::roundf(value * static_cast<float>(multiplier)) / static_cast<float>(multiplier);
|
||||
}
|
||||
|
||||
const bool str_replace(std::string& str, const std::string& from, const std::string& to) {
|
||||
bool str_replace(std::string& str, const std::string& from, const std::string& to) {
|
||||
const size_t start_pos = str.find(from);
|
||||
if (start_pos == std::string::npos)
|
||||
return false;
|
||||
|
||||
@@ -3,10 +3,12 @@
|
||||
|
||||
namespace Utils {
|
||||
namespace Values {
|
||||
extern const bool are_samef(float a, float b, float precision = 0.0001f);
|
||||
extern bool str_ends_with_ci(std::string const& text, std::string const& substr);
|
||||
|
||||
extern bool are_samef(float a, float b, float precision = 0.0001f);
|
||||
extern float round_decimal(float value, int decimal_places = 2);
|
||||
|
||||
extern const bool str_replace(std::string& str, const std::string& from, const std::string& to);
|
||||
extern bool str_replace(std::string& str, const std::string& from, const std::string& to);
|
||||
template <typename T> auto to_string(T val) {
|
||||
if constexpr (std::is_same<T, std::string>::value)
|
||||
return static_cast<std::string>(val);
|
||||
|
||||
@@ -2,13 +2,16 @@
|
||||
Speed=2
|
||||
TeleportPlayerToCamera=0
|
||||
[Camera:Misc]
|
||||
DisableHeadCorrection=0
|
||||
DisablePhotoModeLimits=1
|
||||
DisableSafezoneFOVReduction=1
|
||||
GoProMode=0
|
||||
LensDistortion=20
|
||||
[Camera:ThirdPerson]
|
||||
DistanceBehindPlayer=2
|
||||
Enabled=0
|
||||
HeightAbovePlayer=1.35
|
||||
HorizontalDistanceFromPlayer=0
|
||||
HorizontalDistanceFromPlayer=-0.75
|
||||
UseTPPModel=1
|
||||
[Menu]
|
||||
FirstTimeRunning=1
|
||||
@@ -16,33 +19,68 @@ HasSeenChangelog=0
|
||||
Opacity=99
|
||||
Scale=1
|
||||
[Menu:Keybinds]
|
||||
AllowGrappleHookInSafezoneToggleKey=VK_NONE
|
||||
DisableAirControlToggleKey=VK_NONE
|
||||
DisableGamePauseWhileAFKToggleKey=VK_NONE
|
||||
DisableHUDToggleKey=VK_F8
|
||||
DisableHeadCorrectionToggleKey=VK_NONE
|
||||
DisableOutOfBoundsTimerToggleKey=VK_NONE
|
||||
DisablePhotoModeLimits=VK_NONE
|
||||
DisableSafezoneFOVReduction=VK_NONE
|
||||
FreeCamToggleKey=VK_F3
|
||||
FreezePlayerToggleKey=VK_F7
|
||||
FreezePlayerToggleKey=VK_NONE
|
||||
FreezeTimeToggleKey=VK_NONE
|
||||
GoProMode=VK_NONE
|
||||
GodModeToggleKey=VK_F6
|
||||
InstantReloadToggleKey=VK_NONE
|
||||
MenuToggleKey=VK_F5
|
||||
NightrunnerModeToggleKey=VK_F9
|
||||
NightrunnerModeToggleKey=VK_F7
|
||||
NoRecoilToggleKey=VK_NONE
|
||||
NoSpreadToggleKey=VK_NONE
|
||||
OneHandedModeToggleKey=VK_NONE
|
||||
OneHitKillToggleKey=VK_NONE
|
||||
SlowMotionToggleKey=VK_4
|
||||
TeleportPlayerToCameraToggleKey=VK_F4
|
||||
TeleportToCoordsToggleKey=VK_NONE
|
||||
TeleportToSelectedLocationToggleKey=VK_F9
|
||||
ThirdPersonToggleKey=VK_F1
|
||||
UnlimitedAmmoToggleKey=VK_NONE
|
||||
UnlimitedDurabilityToggleKey=VK_NONE
|
||||
UnlimitedImmunityToggleKey=VK_NONE
|
||||
UnlimitedItemsToggleKey=VK_NONE
|
||||
UnlimitedStaminaToggleKey=VK_NONE
|
||||
UseTPPModelToggleKey=VK_F2
|
||||
[Misc:GameChecks]
|
||||
DisableDataPAKsCRCCheck=1
|
||||
DisableSavegameCRCCheck=1
|
||||
IncreaseDataPAKsLimit=1
|
||||
[Misc:Misc]
|
||||
DisableGamePauseWhileAFK=1
|
||||
[Player:Misc]
|
||||
AllowGrappleHookInSafezone=0
|
||||
DisableOutOfBoundsTimer=1
|
||||
GodMode=0
|
||||
InvisibleToEnemies=0
|
||||
NightrunnerMode=0
|
||||
OneHandedMode=0
|
||||
OneHitKill=0
|
||||
UnlimitedImmunity=0
|
||||
UnlimitedItems=0
|
||||
UnlimitedStamina=0
|
||||
[Player:PlayerJumpParameters]
|
||||
DisableAirControl=0
|
||||
[Player:PlayerVariables]
|
||||
Enabled=0
|
||||
LastLoadSCRFilePath=
|
||||
LastSaveSCRPath=
|
||||
[Teleport:SavedLocations]
|
||||
SavedTeleportLocations=Bazaar - Highest Point:1944,123.6,932.8;Bazaar - Main Entrance:1962.9,50.1,927.9;Colonel Williams Stronghold - Main Entrance Bridge:994.3,22.8,-1138.6;Dynamo Cars Factory - Main Entrance:2295.9,-2.1,-78.6;Fish Eye - Player Safehouse:1180.4,32.4,-146.8;Fish Eye - Top of The Baloon:1122.6,98.8,-101.2;Observatory - Meeting Room:1951.2,-13.4,-329.6;Observatory - The 2 Domes (No Chemicals):1985.4,19.9,-357.2;Out of Bounds - Cut Road Quest:2693.3,-4.7,-241.5;PK Metro Station - Main Entrance:1886.9,50,628.9;PK Ship - Main Entrance:801.8,4.2,139.8;St. Paul Cathedral - GRE Entrance:463.4,4.2,-421;Tolga & Fatin Quest - Underground Loot Box:2343.9,12.2,-661.5;VNC Tower - "V" Logo:1434.2,4.3,-319.3;VNC Tower - Highest Player Safehouse:1424.7,354.6,-455;VNC Tower - Highest Point:1403.8,446.7,-389.8;X13 - Tunnel Near the City Walls Towards Facility:2407.9,36.2,-461.7;X13 - Underground Facility:2437.8,12.2,-649.9;X13 - Waltz Arena:2551.9,15.3,-569.1
|
||||
[Weapon:Misc]
|
||||
InstantReload=0
|
||||
NoRecoil=0
|
||||
NoSpread=0
|
||||
UnlimitedAmmo=0
|
||||
UnlimitedDurability=0
|
||||
[World:Time]
|
||||
SlowMotionSpeed=0.4
|
||||
SlowMotionTransitionTime=1
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user